OSDN Git Service

Merge tag 'mvebu-fixes-5.0-2' of git://git.infradead.org/linux-mvebu into arm/fixes
authorArnd Bergmann <arnd@arndb.de>
Fri, 22 Feb 2019 13:57:27 +0000 (14:57 +0100)
committerArnd Bergmann <arnd@arndb.de>
Fri, 22 Feb 2019 13:58:41 +0000 (14:58 +0100)
mvebu fixes for 5.0 (part 2)

Fix PHY reset signal on clearfog gt 8K (Armada 8040 based)
Fix NAND description on Armada XP boards which was broken since a few
release

* tag 'mvebu-fixes-5.0-2' of git://git.infradead.org/linux-mvebu:
  arm64: dts: clearfog-gt-8k: fix SGMII PHY reset signal
  ARM: dts: armada-xp: fix Armada XP boards NAND description

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
1814 files changed:
.clang-format
Documentation/ABI/stable/sysfs-driver-mlxreg-io
Documentation/ABI/testing/sysfs-block
Documentation/ABI/testing/sysfs-block-zram
Documentation/admin-guide/kernel-parameters.txt
Documentation/block/bfq-iosched.txt
Documentation/block/null_blk.txt
Documentation/block/queue-sysfs.txt
Documentation/blockdev/zram.txt
Documentation/bpf/bpf_design_QA.rst
Documentation/core-api/xarray.rst
Documentation/devicetree/bindings/Makefile
Documentation/devicetree/bindings/arm/cpu-capacity.txt
Documentation/devicetree/bindings/arm/idle-states.txt
Documentation/devicetree/bindings/arm/sp810.txt
Documentation/devicetree/bindings/arm/topology.txt
Documentation/devicetree/bindings/clock/marvell,mmp2.txt
Documentation/devicetree/bindings/display/arm,pl11x.txt
Documentation/devicetree/bindings/display/msm/gpu.txt
Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt
Documentation/devicetree/bindings/reset/socfpga-reset.txt
Documentation/devicetree/bindings/reset/uniphier-reset.txt
Documentation/devicetree/bindings/serio/olpc,ap-sp.txt
Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt
Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.txt
Documentation/driver-model/bus.txt
Documentation/fb/fbcon.txt
Documentation/features/core/cBPF-JIT/arch-support.txt
Documentation/features/core/eBPF-JIT/arch-support.txt
Documentation/features/core/generic-idle-thread/arch-support.txt
Documentation/features/core/jump-labels/arch-support.txt
Documentation/features/core/tracehook/arch-support.txt
Documentation/features/debug/KASAN/arch-support.txt
Documentation/features/debug/gcov-profile-all/arch-support.txt
Documentation/features/debug/kgdb/arch-support.txt
Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
Documentation/features/debug/kprobes/arch-support.txt
Documentation/features/debug/kretprobes/arch-support.txt
Documentation/features/debug/optprobes/arch-support.txt
Documentation/features/debug/stackprotector/arch-support.txt
Documentation/features/debug/uprobes/arch-support.txt
Documentation/features/debug/user-ret-profiler/arch-support.txt
Documentation/features/io/dma-contiguous/arch-support.txt
Documentation/features/locking/cmpxchg-local/arch-support.txt
Documentation/features/locking/lockdep/arch-support.txt
Documentation/features/locking/queued-rwlocks/arch-support.txt
Documentation/features/locking/queued-spinlocks/arch-support.txt
Documentation/features/locking/rwsem-optimized/arch-support.txt
Documentation/features/perf/kprobes-event/arch-support.txt
Documentation/features/perf/perf-regs/arch-support.txt
Documentation/features/perf/perf-stackdump/arch-support.txt
Documentation/features/sched/membarrier-sync-core/arch-support.txt
Documentation/features/sched/numa-balancing/arch-support.txt
Documentation/features/seccomp/seccomp-filter/arch-support.txt
Documentation/features/time/arch-tick-broadcast/arch-support.txt
Documentation/features/time/clockevents/arch-support.txt
Documentation/features/time/context-tracking/arch-support.txt
Documentation/features/time/irq-time-acct/arch-support.txt
Documentation/features/time/modern-timekeeping/arch-support.txt
Documentation/features/time/virt-cpuacct/arch-support.txt
Documentation/features/vm/ELF-ASLR/arch-support.txt
Documentation/features/vm/PG_uncached/arch-support.txt
Documentation/features/vm/THP/arch-support.txt
Documentation/features/vm/TLB/arch-support.txt
Documentation/features/vm/huge-vmap/arch-support.txt
Documentation/features/vm/ioremap_prot/arch-support.txt
Documentation/features/vm/numa-memblock/arch-support.txt
Documentation/features/vm/pte_special/arch-support.txt
Documentation/filesystems/sysfs.txt
Documentation/networking/index.rst
Documentation/networking/operstates.txt
Documentation/networking/rxrpc.txt
Documentation/networking/snmp_counter.rst
Documentation/networking/timestamping.txt
Documentation/sysctl/fs.txt
Documentation/trace/coresight-cpu-debug.txt
Documentation/virtual/kvm/amd-memory-encryption.rst
Documentation/x86/resctrl_ui.txt
MAINTAINERS
Makefile
arch/alpha/include/asm/irq.h
arch/alpha/mm/fault.c
arch/arc/include/asm/Kbuild
arch/arc/include/asm/arcregs.h
arch/arc/include/asm/bitops.h
arch/arc/include/asm/perf_event.h
arch/arc/kernel/perf_event.c
arch/arc/kernel/setup.c
arch/arc/kernel/troubleshoot.c
arch/arc/lib/memset-archs.S
arch/arc/mm/fault.c
arch/arc/mm/init.c
arch/arm/boot/dts/am335x-evm.dts
arch/arm/boot/dts/am335x-evmsk.dts
arch/arm/boot/dts/am335x-shc.dts
arch/arm/boot/dts/da850-evm.dts
arch/arm/boot/dts/da850-lcdk.dts
arch/arm/boot/dts/da850.dtsi
arch/arm/boot/dts/imx6q-pistachio.dts
arch/arm/boot/dts/imx6sll-evk.dts
arch/arm/boot/dts/imx6sx.dtsi
arch/arm/boot/dts/meson.dtsi
arch/arm/boot/dts/meson8b-ec100.dts
arch/arm/boot/dts/meson8b-odroidc1.dts
arch/arm/boot/dts/meson8m2-mxiii-plus.dts
arch/arm/boot/dts/motorola-cpcap-mapphone.dtsi
arch/arm/boot/dts/omap3-gta04.dtsi
arch/arm/boot/dts/omap3-n900.dts
arch/arm/boot/dts/omap3-n950-n9.dtsi
arch/arm/boot/dts/omap4-droid4-xt894.dts
arch/arm/boot/dts/omap5-board-common.dtsi
arch/arm/boot/dts/omap5-cm-t54.dts
arch/arm/boot/dts/omap5-l4.dtsi
arch/arm/boot/dts/r8a7743.dtsi
arch/arm/boot/dts/rk3188.dtsi
arch/arm/boot/dts/sun6i-a31.dtsi
arch/arm/boot/dts/sun8i-h3-beelink-x2.dts
arch/arm/boot/dts/tegra124-nyan.dtsi
arch/arm/boot/dts/vf610-bk4.dts
arch/arm/include/asm/kvm_host.h
arch/arm/include/asm/stage2_pgtable.h
arch/arm/include/asm/xen/page-coherent.h
arch/arm/kvm/coproc.c
arch/arm/kvm/reset.c
arch/arm/mach-cns3xxx/pcie.c
arch/arm/mach-davinci/board-da830-evm.c
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/board-dm355-evm.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/board-omapl138-hawk.c
arch/arm/mach-integrator/impd1.c
arch/arm/mach-iop32x/n2100.c
arch/arm/mach-omap2/cpuidle44xx.c
arch/arm/mach-omap2/display.c
arch/arm/mach-omap2/omap-wakeupgen.c
arch/arm/mach-socfpga/socfpga.c
arch/arm/mach-tango/pm.c
arch/arm/mach-tango/pm.h [new file with mode: 0644]
arch/arm/mach-tango/setup.c
arch/arm/plat-pxa/ssp.c
arch/arm/xen/mm.c
arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts
arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-hwacom-amazetv.dts
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi
arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
arch/arm64/boot/dts/amlogic/meson-gxm-rbox-pro.dts
arch/arm64/boot/dts/freescale/imx8mq-evk.dts
arch/arm64/boot/dts/freescale/imx8mq.dtsi
arch/arm64/boot/dts/qcom/msm8996.dtsi
arch/arm64/boot/dts/renesas/r8a774a1.dtsi
arch/arm64/boot/dts/renesas/r8a7796.dtsi
arch/arm64/boot/dts/renesas/r8a77965.dtsi
arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
arch/arm64/boot/dts/rockchip/rk3399-gru-bob.dts
arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator.dts
arch/arm64/configs/defconfig
arch/arm64/include/asm/asm-prototypes.h
arch/arm64/include/asm/cache.h
arch/arm64/include/asm/device.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/memory.h
arch/arm64/include/asm/mmu.h
arch/arm64/include/asm/pgtable-prot.h
arch/arm64/include/asm/xen/page-coherent.h
arch/arm64/kernel/cpu_errata.c
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/head.S
arch/arm64/kernel/hibernate.c
arch/arm64/kernel/hyp-stub.S
arch/arm64/kernel/kaslr.c
arch/arm64/kernel/machine_kexec_file.c
arch/arm64/kernel/probes/kprobes.c
arch/arm64/kernel/setup.c
arch/arm64/kvm/hyp/switch.c
arch/arm64/kvm/hyp/sysreg-sr.c
arch/arm64/kvm/reset.c
arch/arm64/kvm/sys_regs.c
arch/arm64/mm/dma-mapping.c
arch/arm64/mm/dump.c
arch/arm64/mm/flush.c
arch/c6x/include/asm/Kbuild
arch/csky/include/asm/io.h
arch/csky/include/asm/pgalloc.h
arch/csky/include/asm/pgtable.h
arch/csky/include/asm/processor.h
arch/csky/kernel/dumpstack.c
arch/csky/kernel/module.c
arch/csky/kernel/ptrace.c
arch/csky/kernel/smp.c
arch/csky/mm/ioremap.c
arch/h8300/Makefile
arch/h8300/include/asm/Kbuild
arch/hexagon/include/asm/Kbuild
arch/ia64/Makefile
arch/m68k/emu/nfblock.c
arch/m68k/include/asm/Kbuild
arch/microblaze/include/asm/Kbuild
arch/mips/Kconfig
arch/mips/bcm47xx/setup.c
arch/mips/boot/dts/ingenic/ci20.dts
arch/mips/boot/dts/ingenic/jz4740.dtsi
arch/mips/boot/dts/xilfpga/nexys4ddr.dts
arch/mips/cavium-octeon/setup.c
arch/mips/configs/ath79_defconfig
arch/mips/include/asm/atomic.h
arch/mips/include/asm/barrier.h
arch/mips/include/asm/bitops.h
arch/mips/include/asm/futex.h
arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h
arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
arch/mips/include/asm/pgtable.h
arch/mips/jazz/jazzdma.c
arch/mips/kernel/mips-cm.c
arch/mips/kernel/process.c
arch/mips/lantiq/irq.c
arch/mips/lantiq/xway/dma.c
arch/mips/loongson64/Platform
arch/mips/loongson64/common/reset.c
arch/mips/mm/tlbex.c
arch/mips/pci/msi-octeon.c
arch/mips/pci/pci-octeon.c
arch/mips/vdso/Makefile
arch/nds32/Makefile
arch/openrisc/Makefile
arch/openrisc/include/asm/Kbuild
arch/openrisc/include/asm/uaccess.h
arch/powerpc/include/asm/book3s/64/pgtable.h
arch/powerpc/include/uapi/asm/perf_regs.h
arch/powerpc/kernel/head_8xx.S
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/trace/ftrace.c
arch/powerpc/mm/pgtable-book3s64.c
arch/powerpc/perf/perf_regs.c
arch/powerpc/platforms/4xx/ocm.c
arch/powerpc/platforms/chrp/setup.c
arch/powerpc/platforms/pasemi/dma_lib.c
arch/powerpc/platforms/powernv/npu-dma.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/pseries/papr_scm.c
arch/powerpc/platforms/pseries/pci.c
arch/powerpc/sysdev/fsl_rmu.c
arch/riscv/Kconfig
arch/riscv/configs/defconfig
arch/riscv/include/asm/module.h
arch/riscv/include/asm/page.h
arch/riscv/include/asm/pgtable-bits.h
arch/riscv/include/asm/pgtable.h
arch/riscv/include/asm/processor.h
arch/riscv/include/asm/ptrace.h
arch/riscv/include/asm/syscall.h
arch/riscv/include/asm/thread_info.h
arch/riscv/include/asm/unistd.h
arch/riscv/kernel/asm-offsets.c
arch/riscv/kernel/entry.S
arch/riscv/kernel/module-sections.c
arch/riscv/kernel/ptrace.c
arch/riscv/kernel/setup.c
arch/riscv/kernel/smp.c
arch/riscv/kernel/smpboot.c
arch/riscv/mm/init.c
arch/s390/include/asm/mmu_context.h
arch/s390/kernel/early.c
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/kernel/swsusp.S
arch/s390/kernel/vdso.c
arch/s390/pci/pci.c
arch/unicore32/include/asm/Kbuild
arch/x86/Kconfig
arch/x86/boot/compressed/head_64.S
arch/x86/boot/compressed/pgtable.h
arch/x86/entry/entry_64_compat.S
arch/x86/events/core.c
arch/x86/events/intel/core.c
arch/x86/events/intel/uncore_snbep.c
arch/x86/events/perf_event.h
arch/x86/ia32/ia32_aout.c
arch/x86/include/asm/intel-family.h
arch/x86/include/asm/mmu_context.h
arch/x86/include/asm/page_64_types.h
arch/x86/include/asm/pgtable.h
arch/x86/include/asm/resctrl_sched.h
arch/x86/include/asm/uaccess.h
arch/x86/include/asm/uv/bios.h
arch/x86/kernel/cpu/Makefile
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/mce/core.c
arch/x86/kernel/cpu/microcode/amd.c
arch/x86/kernel/cpu/resctrl/Makefile
arch/x86/kernel/crash.c
arch/x86/kernel/hpet.c
arch/x86/kernel/kexec-bzimage64.c
arch/x86/kernel/kvm.c
arch/x86/kernel/tsc.c
arch/x86/kvm/Makefile
arch/x86/kvm/hyperv.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/trace.h
arch/x86/kvm/vmx/evmcs.c
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/vmx/vmx.h
arch/x86/kvm/x86.c
arch/x86/lib/iomem.c
arch/x86/lib/kaslr.c
arch/x86/mm/fault.c
arch/x86/mm/mem_encrypt_identity.c
arch/x86/mm/pageattr.c
arch/x86/platform/uv/bios_uv.c
arch/x86/xen/enlighten_pv.c
arch/x86/xen/time.c
arch/xtensa/Kconfig
arch/xtensa/boot/dts/Makefile
arch/xtensa/configs/audio_kc705_defconfig
arch/xtensa/configs/cadence_csp_defconfig
arch/xtensa/configs/generic_kc705_defconfig
arch/xtensa/configs/nommu_kc705_defconfig
arch/xtensa/configs/smp_lx200_defconfig
arch/xtensa/kernel/head.S
arch/xtensa/kernel/smp.c
arch/xtensa/kernel/time.c
block/bfq-wf2q.c
block/blk-core.c
block/blk-flush.c
block/blk-iolatency.c
block/blk-mq-debugfs-zoned.c
block/blk-mq-debugfs.c
block/blk-mq.c
block/blk-mq.h
block/blk-wbt.c
crypto/adiantum.c
crypto/authenc.c
crypto/authencesn.c
crypto/sm3_generic.c
drivers/acpi/Kconfig
drivers/acpi/Makefile
drivers/acpi/arm64/iort.c
drivers/acpi/bus.c
drivers/acpi/internal.h
drivers/acpi/nfit/core.c
drivers/acpi/nfit/intel.c
drivers/acpi/numa.c
drivers/acpi/pmic/intel_pmic_xpower.c
drivers/acpi/power.c
drivers/android/binder.c
drivers/android/binder_internal.h
drivers/android/binderfs.c
drivers/ata/Kconfig
drivers/ata/ahci.h
drivers/ata/ahci_mvebu.c
drivers/ata/libahci_platform.c
drivers/ata/libata-core.c
drivers/ata/pata_macio.c
drivers/ata/sata_fsl.c
drivers/ata/sata_inic162x.c
drivers/atm/he.c
drivers/atm/idt77252.c
drivers/auxdisplay/ht16k33.c
drivers/base/cacheinfo.c
drivers/base/power/main.c
drivers/base/power/runtime.c
drivers/base/regmap/regmap-irq.c
drivers/block/floppy.c
drivers/block/loop.c
drivers/block/nbd.c
drivers/block/null_blk.h
drivers/block/rbd.c
drivers/block/skd_main.c
drivers/block/zram/zram_drv.c
drivers/block/zram/zram_drv.h
drivers/bus/ti-sysc.c
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/ipmi/ipmi_ssif.c
drivers/char/mwave/mwavedd.c
drivers/clk/Kconfig
drivers/clk/clk-versaclock5.c
drivers/clk/clk.c
drivers/clk/imx/clk-frac-pll.c
drivers/clk/imx/clk-imx8qxp-lpcg.c
drivers/clk/mmp/clk-of-mmp2.c
drivers/clk/qcom/Kconfig
drivers/clk/qcom/gcc-sdm845.c
drivers/clk/socfpga/clk-pll-s10.c
drivers/clk/socfpga/clk-s10.c
drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
drivers/clk/ti/divider.c
drivers/clk/zynqmp/clkc.c
drivers/clocksource/timer-ti-dm.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/scmi-cpufreq.c
drivers/cpufreq/scpi-cpufreq.c
drivers/cpuidle/poll_state.c
drivers/crypto/Kconfig
drivers/crypto/amcc/crypto4xx_core.c
drivers/crypto/bcm/cipher.c
drivers/crypto/caam/caamalg.c
drivers/crypto/caam/caamhash.c
drivers/crypto/caam/desc.h
drivers/crypto/caam/error.h
drivers/crypto/cavium/cpt/cptpf_main.c
drivers/crypto/cavium/cpt/cptvf_main.c
drivers/crypto/cavium/nitrox/nitrox_lib.c
drivers/crypto/cavium/nitrox/nitrox_reqmgr.c
drivers/crypto/ccp/ccp-dev-v5.c
drivers/crypto/ccree/cc_aead.c
drivers/crypto/ccree/cc_driver.c
drivers/crypto/ccree/cc_pm.c
drivers/crypto/ccree/cc_pm.h
drivers/crypto/hisilicon/sec/sec_algs.c
drivers/crypto/hisilicon/sec/sec_drv.c
drivers/crypto/ixp4xx_crypto.c
drivers/crypto/mediatek/mtk-platform.c
drivers/crypto/qat/qat_common/adf_admin.c
drivers/crypto/qat/qat_common/qat_algs.c
drivers/crypto/qat/qat_common/qat_asym_algs.c
drivers/crypto/talitos.c
drivers/dma/at_xdmac.c
drivers/dma/bcm2835-dma.c
drivers/dma/dmatest.c
drivers/dma/imx-dma.c
drivers/dma/imx-sdma.c
drivers/dma/mediatek/mtk-hsdma.c
drivers/dma/mxs-dma.c
drivers/dma/xgene-dma.c
drivers/dma/xilinx/xilinx_dma.c
drivers/dma/xilinx/zynqmp_dma.c
drivers/edac/altera_edac.h
drivers/firewire/sbp2.c
drivers/firmware/arm_scmi/bus.c
drivers/firmware/efi/arm-runtime.c
drivers/firmware/efi/efi.c
drivers/firmware/efi/libstub/arm-stub.c
drivers/firmware/efi/runtime-wrappers.c
drivers/fpga/stratix10-soc.c
drivers/gpio/gpio-altera-a10sr.c
drivers/gpio/gpio-eic-sprd.c
drivers/gpio/gpio-pca953x.c
drivers/gpio/gpio-pcf857x.c
drivers/gpio/gpio-vf610.c
drivers/gpio/gpiolib-acpi.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/dce_virtual.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c
drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c
drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/amdkfd/Kconfig
drivers/gpu/drm/amd/amdkfd/kfd_crat.c
drivers/gpu/drm/amd/amdkfd/kfd_topology.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/dc_link.h
drivers/gpu/drm/amd/display/dc/dc_stream.h
drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/modules/power/power_helpers.c
drivers/gpu/drm/amd/include/kgd_pp_interface.h
drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
drivers/gpu/drm/bridge/tc358767.c
drivers/gpu/drm/drm_atomic_uapi.c
drivers/gpu/drm/drm_dp_helper.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_lease.c
drivers/gpu/drm/drm_mode_object.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/drm_pci.c
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/hypercall.h
drivers/gpu/drm/i915/gvt/kvmgt.c
drivers/gpu/drm/i915/gvt/mpt.h
drivers/gpu/drm/i915/gvt/scheduler.c
drivers/gpu/drm/i915/gvt/scheduler.h
drivers/gpu/drm/i915/i915_debugfs.c
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_pmu.c
drivers/gpu/drm/i915/i915_pmu.h
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_sysfs.c
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_fbdev.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_opregion.c
drivers/gpu/drm/i915/intel_psr.c
drivers/gpu/drm/i915/intel_ringbuffer.h
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/imx/imx-ldb.c
drivers/gpu/drm/imx/ipuv3-plane.c
drivers/gpu/drm/meson/meson_crtc.c
drivers/gpu/drm/meson/meson_drv.c
drivers/gpu/drm/msm/adreno/a6xx_gmu.c
drivers/gpu/drm/msm/adreno/adreno_gpu.c
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
drivers/gpu/drm/msm/msm_drv.h
drivers/gpu/drm/msm/msm_gem.c
drivers/gpu/drm/msm/msm_gem_vma.c
drivers/gpu/drm/msm/msm_gpu.c
drivers/gpu/drm/msm/msm_gpu.h
drivers/gpu/drm/msm/msm_rd.c
drivers/gpu/drm/nouveau/nouveau_backlight.c
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
drivers/gpu/drm/omapdrm/dss/dsi.c
drivers/gpu/drm/qxl/qxl_drv.c
drivers/gpu/drm/qxl/qxl_prime.c
drivers/gpu/drm/radeon/ci_dpm.c
drivers/gpu/drm/radeon/si_dpm.c
drivers/gpu/drm/rockchip/rockchip_rgb.c
drivers/gpu/drm/rockchip/rockchip_rgb.h
drivers/gpu/drm/scheduler/sched_entity.c
drivers/gpu/drm/sun4i/sun4i_backend.c
drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
drivers/gpu/drm/sun4i/sun4i_tcon.c
drivers/gpu/drm/virtio/virtgpu_drv.c
drivers/gpu/drm/virtio/virtgpu_drv.h
drivers/gpu/drm/virtio/virtgpu_prime.c
drivers/gpu/drm/vkms/vkms_crc.c
drivers/gpu/drm/vkms/vkms_crtc.c
drivers/gpu/drm/vkms/vkms_drv.c
drivers/gpu/drm/vkms/vkms_drv.h
drivers/gpu/drm/vkms/vkms_gem.c
drivers/gpu/drm/vkms/vkms_output.c
drivers/gpu/drm/vkms/vkms_plane.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/ipu-v3/ipu-common.c
drivers/gpu/ipu-v3/ipu-pre.c
drivers/gpu/vga/Kconfig
drivers/hid/hid-core.c
drivers/hid/hid-debug.c
drivers/hid/hid-ids.h
drivers/hid/i2c-hid/i2c-hid-core.c
drivers/hv/channel.c
drivers/hv/hv_balloon.c
drivers/hv/ring_buffer.c
drivers/hv/vmbus_drv.c
drivers/hwmon/lm80.c
drivers/hwmon/nct6775.c
drivers/hwmon/occ/common.c
drivers/hwmon/tmp421.c
drivers/i2c/busses/i2c-bcm2835.c
drivers/i2c/busses/i2c-cadence.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-tegra.c
drivers/i2c/i2c-dev.c
drivers/i3c/master.c
drivers/i3c/master/dw-i3c-master.c
drivers/i3c/master/i3c-master-cdns.c
drivers/ide/ide-atapi.c
drivers/ide/ide-io.c
drivers/ide/ide-park.c
drivers/ide/ide-probe.c
drivers/ide/ide-proc.c
drivers/iio/adc/axp288_adc.c
drivers/iio/adc/ti-ads8688.c
drivers/iio/adc/ti_am335x_adc.c
drivers/iio/chemical/atlas-ph-sensor.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/core_priv.h
drivers/infiniband/core/device.c
drivers/infiniband/core/nldev.c
drivers/infiniband/core/rdma_core.h
drivers/infiniband/core/umem_odp.c
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_ioctl.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/core/uverbs_std_types_device.c
drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
drivers/infiniband/hw/bnxt_re/qplib_res.c
drivers/infiniband/hw/cxgb3/cxio_hal.c
drivers/infiniband/hw/cxgb4/qp.c
drivers/infiniband/hw/hfi1/file_ops.c
drivers/infiniband/hw/hfi1/init.c
drivers/infiniband/hw/hfi1/pio.c
drivers/infiniband/hw/hfi1/sdma.c
drivers/infiniband/hw/hfi1/ud.c
drivers/infiniband/hw/hns/hns_roce_alloc.c
drivers/infiniband/hw/hns/hns_roce_hw_v2.c
drivers/infiniband/hw/hns/hns_roce_srq.c
drivers/infiniband/hw/i40iw/i40iw_utils.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/mlx5/flow.c
drivers/infiniband/hw/mlx5/odp.c
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/hw/mthca/mthca_memfree.c
drivers/infiniband/hw/mthca/mthca_provider.c
drivers/infiniband/hw/ocrdma/ocrdma_hw.c
drivers/infiniband/hw/ocrdma/ocrdma_stats.c
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
drivers/infiniband/hw/qedr/verbs.c
drivers/infiniband/hw/qib/qib_ud.c
drivers/infiniband/hw/vmw_pvrdma/pvrdma.h
drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
drivers/infiniband/sw/rdmavt/qp.c
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_cm.c
drivers/input/joystick/xpad.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/cap11xx.c
drivers/input/keyboard/matrix_keypad.c
drivers/input/keyboard/qt2160.c
drivers/input/keyboard/st-keyscan.c
drivers/input/misc/apanel.c
drivers/input/misc/bma150.c
drivers/input/misc/pwm-vibra.c
drivers/input/misc/uinput.c
drivers/input/mouse/elan_i2c_core.c
drivers/input/mouse/elantech.c
drivers/input/serio/olpc_apsp.c
drivers/input/serio/ps2-gpio.c
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/raspberrypi-ts.c
drivers/iommu/amd_iommu.c
drivers/iommu/intel-iommu.c
drivers/iommu/mtk_iommu_v1.c
drivers/iommu/of_iommu.c
drivers/irqchip/irq-csky-apb-intc.c
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic-v3-mbi.c
drivers/irqchip/irq-madera.c
drivers/irqchip/irq-mmp.c
drivers/irqchip/irq-stm32-exti.c
drivers/irqchip/irq-xtensa-mx.c
drivers/irqchip/irq-xtensa-pic.c
drivers/isdn/hardware/avm/b1.c
drivers/isdn/hardware/mISDN/hfcsusb.c
drivers/isdn/i4l/isdn_tty.c
drivers/isdn/mISDN/timerdev.c
drivers/leds/leds-lp5523.c
drivers/md/dm-crypt.c
drivers/md/dm-rq.c
drivers/md/dm-thin-metadata.c
drivers/md/dm-thin-metadata.h
drivers/md/dm-thin.c
drivers/md/dm.c
drivers/md/md.c
drivers/md/raid1.c
drivers/md/raid5-cache.c
drivers/md/raid5.c
drivers/media/pci/intel/ipu3/ipu3-cio2.c
drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
drivers/media/platform/vim2m.c
drivers/media/v4l2-core/v4l2-ioctl.c
drivers/mfd/Kconfig
drivers/mfd/ab8500-core.c
drivers/mfd/axp20x.c
drivers/mfd/bd9571mwv.c
drivers/mfd/cros_ec_dev.c
drivers/mfd/db8500-prcmu.c
drivers/mfd/exynos-lpass.c
drivers/mfd/madera-core.c
drivers/mfd/max77620.c
drivers/mfd/mc13xxx-core.c
drivers/mfd/mt6397-core.c
drivers/mfd/qcom_rpm.c
drivers/mfd/rave-sp.c
drivers/mfd/stmpe.c
drivers/mfd/ti_am335x_tscadc.c
drivers/mfd/tps65218.c
drivers/mfd/tps6586x.c
drivers/mfd/twl-core.c
drivers/mfd/wm5110-tables.c
drivers/misc/genwqe/card_utils.c
drivers/misc/ibmvmc.c
drivers/misc/mei/client.c
drivers/misc/mei/hbm.c
drivers/misc/mei/hw-me-regs.h
drivers/misc/mei/pci-me.c
drivers/misc/mic/vop/vop_main.c
drivers/misc/pvpanic.c
drivers/mmc/core/block.c
drivers/mmc/core/host.c
drivers/mmc/host/Kconfig
drivers/mmc/host/bcm2835.c
drivers/mmc/host/dw_mmc-bluefield.c
drivers/mmc/host/meson-gx-mmc.c
drivers/mmc/host/mtk-sd.c
drivers/mmc/host/sdhci-iproc.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sunxi-mmc.c
drivers/mtd/mtdcore.c
drivers/mtd/mtdcore.h
drivers/mtd/mtdpart.c
drivers/mtd/nand/raw/denali.c
drivers/mtd/nand/raw/fsmc_nand.c
drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
drivers/mtd/nand/raw/jz4740_nand.c
drivers/mtd/nand/raw/nand_base.c
drivers/mtd/nand/raw/nand_bbt.c
drivers/mtd/nand/raw/qcom_nandc.c
drivers/mtd/nand/spi/core.c
drivers/net/Kconfig
drivers/net/bonding/bond_main.c
drivers/net/caif/caif_serial.c
drivers/net/can/dev.c
drivers/net/can/flexcan.c
drivers/net/dsa/b53/b53_srab.c
drivers/net/dsa/bcm_sf2.c
drivers/net/dsa/microchip/ksz_common.c
drivers/net/dsa/mt7530.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/chip.h
drivers/net/dsa/mv88e6xxx/global1_atu.c
drivers/net/dsa/mv88e6xxx/port.h
drivers/net/dsa/mv88e6xxx/serdes.c
drivers/net/dsa/realtek-smi.c
drivers/net/ethernet/aeroflex/greth.c
drivers/net/ethernet/alacritech/slicoss.c
drivers/net/ethernet/alteon/acenic.c
drivers/net/ethernet/altera/altera_msgdma.c
drivers/net/ethernet/altera/altera_tse_main.c
drivers/net/ethernet/amazon/ena/ena_com.c
drivers/net/ethernet/amazon/ena/ena_netdev.c
drivers/net/ethernet/amazon/ena/ena_netdev.h
drivers/net/ethernet/amd/amd8111e.c
drivers/net/ethernet/amd/xgbe/xgbe-common.h
drivers/net/ethernet/amd/xgbe/xgbe-dev.c
drivers/net/ethernet/apm/xgene-v2/main.c
drivers/net/ethernet/apple/bmac.c
drivers/net/ethernet/atheros/alx/main.c
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/bcm63xx_enet.c
drivers/net/ethernet/broadcom/bcmsysport.c
drivers/net/ethernet/broadcom/bcmsysport.h
drivers/net/ethernet/broadcom/bgmac.c
drivers/net/ethernet/broadcom/bnx2.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
drivers/net/ethernet/broadcom/sb1250-mac.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/cadence/macb.h
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/cavium/Kconfig
drivers/net/ethernet/cavium/thunder/nicvf_queues.c
drivers/net/ethernet/chelsio/cxgb3/sge.c
drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
drivers/net/ethernet/chelsio/cxgb4/sge.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4vf/sge.c
drivers/net/ethernet/cisco/enic/enic_main.c
drivers/net/ethernet/dec/tulip/de2104x.c
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_ethtool.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/faraday/ftgmac100.c
drivers/net/ethernet/faraday/ftmac100.c
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
drivers/net/ethernet/freescale/dpaa2/Kconfig
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/fec_mpc52xx.c
drivers/net/ethernet/freescale/ucc_geth.c
drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
drivers/net/ethernet/hisilicon/hns/hns_enet.c
drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c
drivers/net/ethernet/hisilicon/hns_mdio.c
drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c
drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c
drivers/net/ethernet/huawei/hinic/hinic_hw_io.c
drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c
drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c
drivers/net/ethernet/i825xx/82596.c
drivers/net/ethernet/ibm/emac/mal.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/intel/Kconfig
drivers/net/ethernet/intel/e1000/e1000_ethtool.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/igb/igb.h
drivers/net/ethernet/intel/igb/igb_ethtool.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/ixgb/ixgb_main.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
drivers/net/ethernet/marvell/octeontx2/af/cgx.c
drivers/net/ethernet/marvell/octeontx2/af/common.h
drivers/net/ethernet/marvell/pxa168_eth.c
drivers/net/ethernet/marvell/skge.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mellanox/mlx4/alloc.c
drivers/net/ethernet/mellanox/mlx4/cq.c
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx4/fw.c
drivers/net/ethernet/mellanox/mlx4/icm.c
drivers/net/ethernet/mellanox/mlx4/icm.h
drivers/net/ethernet/mellanox/mlx5/core/alloc.c
drivers/net/ethernet/mellanox/mlx5/core/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
drivers/net/ethernet/mellanox/mlx5/core/en_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_rep.h
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/events.c
drivers/net/ethernet/mellanox/mlx5/core/health.c
drivers/net/ethernet/mellanox/mlx5/core/lag.c
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
drivers/net/ethernet/mellanox/mlx5/core/qp.c
drivers/net/ethernet/mellanox/mlxsw/Kconfig
drivers/net/ethernet/mellanox/mlxsw/pci.c
drivers/net/ethernet/mellanox/mlxsw/pci_hw.h
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
drivers/net/ethernet/microchip/lan743x_main.c
drivers/net/ethernet/myricom/myri10ge/myri10ge.c
drivers/net/ethernet/netronome/nfp/nfp_net_common.c
drivers/net/ethernet/ni/nixge.c
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
drivers/net/ethernet/pasemi/pasemi_mac.c
drivers/net/ethernet/qlogic/qed/qed.h
drivers/net/ethernet/qlogic/qed/qed_cxt.c
drivers/net/ethernet/qlogic/qed/qed_dev.c
drivers/net/ethernet/qlogic/qed/qed_l2.c
drivers/net/ethernet/qlogic/qed/qed_l2.h
drivers/net/ethernet/qlogic/qed/qed_ll2.c
drivers/net/ethernet/qlogic/qed/qed_sp.h
drivers/net/ethernet/qlogic/qed/qed_sp_commands.c
drivers/net/ethernet/qlogic/qed/qed_spq.c
drivers/net/ethernet/qlogic/qed/qed_sriov.c
drivers/net/ethernet/qlogic/qed/qed_vf.c
drivers/net/ethernet/qlogic/qede/qede.h
drivers/net/ethernet/qlogic/qede/qede_fp.c
drivers/net/ethernet/qlogic/qede/qede_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
drivers/net/ethernet/qualcomm/emac/emac-mac.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
drivers/net/ethernet/sfc/ef10.c
drivers/net/ethernet/sfc/falcon/nic.c
drivers/net/ethernet/sfc/nic.c
drivers/net/ethernet/sgi/meth.c
drivers/net/ethernet/smsc/epic100.c
drivers/net/ethernet/socionext/netsec.c
drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
drivers/net/ethernet/sun/cassini.c
drivers/net/ethernet/sun/cassini.h
drivers/net/ethernet/sun/sunbmac.c
drivers/net/ethernet/sun/sunhme.c
drivers/net/ethernet/tehuti/tehuti.c
drivers/net/ethernet/ti/cpmac.c
drivers/net/ethernet/tundra/tsi108_eth.c
drivers/net/ethernet/via/via-velocity.c
drivers/net/ethernet/xilinx/ll_temac_main.c
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
drivers/net/fddi/defxx.c
drivers/net/fddi/skfp/skfddi.c
drivers/net/geneve.c
drivers/net/hyperv/hyperv_net.h
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/hyperv/rndis_filter.c
drivers/net/ieee802154/mcr20a.c
drivers/net/ipvlan/ipvlan_main.c
drivers/net/macvlan.c
drivers/net/phy/asix.c
drivers/net/phy/bcm87xx.c
drivers/net/phy/cortina.c
drivers/net/phy/dp83640.c
drivers/net/phy/marvell.c
drivers/net/phy/mdio-hisi-femac.c
drivers/net/phy/mdio_bus.c
drivers/net/phy/meson-gxl.c
drivers/net/phy/micrel.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/phy/phylink.c
drivers/net/phy/rockchip.c
drivers/net/phy/sfp-bus.c
drivers/net/phy/sfp.c
drivers/net/phy/sfp.h
drivers/net/phy/teranetics.c
drivers/net/ppp/pppoe.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/aqc111.c
drivers/net/usb/asix_devices.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/qmi_wwan.c
drivers/net/virtio_net.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vxlan.c
drivers/net/wan/dscc4.c
drivers/net/wan/fsl_ucc_hdlc.c
drivers/net/wireless/ath/ath10k/ce.c
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath10k/pci.c
drivers/net/wireless/ath/ath10k/wmi.c
drivers/net/wireless/ath/wcn36xx/dxe.c
drivers/net/wireless/ath/wil6210/txrx_edma.c
drivers/net/wireless/broadcom/b43/dma.c
drivers/net/wireless/broadcom/b43legacy/dma.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
drivers/net/wireless/intel/iwlwifi/Kconfig
drivers/net/wireless/intel/iwlwifi/pcie/rx.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h
drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c
drivers/net/wireless/ti/wlcore/sdio.c
drivers/net/wireless/virt_wifi.c
drivers/ntb/hw/mscc/ntb_hw_switchtec.c
drivers/nvdimm/dimm.c
drivers/nvdimm/dimm_devs.c
drivers/nvdimm/nd-core.h
drivers/nvdimm/nd.h
drivers/nvme/host/core.c
drivers/nvme/host/fabrics.c
drivers/nvme/host/multipath.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/nvme/host/rdma.c
drivers/nvme/host/tcp.c
drivers/nvme/target/rdma.c
drivers/nvme/target/tcp.c
drivers/of/dynamic.c
drivers/of/fdt.c
drivers/of/overlay.c
drivers/of/pdt.c
drivers/of/property.c
drivers/opp/core.c
drivers/pci/Kconfig
drivers/pci/controller/dwc/pci-imx6.c
drivers/pci/controller/dwc/pci-meson.c
drivers/pci/controller/dwc/pcie-armada8k.c
drivers/pci/controller/pcie-iproc-msi.c
drivers/pci/msi.c
drivers/pci/pci.c
drivers/pci/quirks.c
drivers/pci/switch/switchtec.c
drivers/phy/marvell/phy-berlin-sata.c
drivers/phy/qualcomm/phy-ath79-usb.c
drivers/phy/ti/Kconfig
drivers/phy/ti/phy-gmii-sel.c
drivers/pinctrl/intel/pinctrl-cherryview.c
drivers/pinctrl/mediatek/Kconfig
drivers/pinctrl/pinctrl-mcp23s08.c
drivers/pinctrl/sunxi/pinctrl-sun50i-h6.c
drivers/pinctrl/sunxi/pinctrl-sunxi.c
drivers/pinctrl/sunxi/pinctrl-sunxi.h
drivers/platform/x86/Kconfig
drivers/ptp/ptp_chardev.c
drivers/rapidio/devices/tsi721.c
drivers/rapidio/devices/tsi721_dma.c
drivers/remoteproc/remoteproc_virtio.c
drivers/reset/Kconfig
drivers/reset/Makefile
drivers/reset/core.c
drivers/reset/reset-hsdk.c
drivers/reset/reset-simple.c
drivers/reset/reset-socfpga.c [new file with mode: 0644]
drivers/reset/reset-uniphier-glue.c [moved from drivers/reset/reset-uniphier-usb3.c with 73% similarity]
drivers/s390/block/dasd_eckd.c
drivers/s390/char/sclp_config.c
drivers/s390/crypto/ap_bus.c
drivers/s390/net/ism_drv.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3_main.c
drivers/s390/scsi/zfcp_aux.c
drivers/s390/scsi/zfcp_scsi.c
drivers/s390/virtio/virtio_ccw.c
drivers/scsi/3w-sas.c
drivers/scsi/53c700.c
drivers/scsi/a100u2w.c
drivers/scsi/aacraid/linit.c
drivers/scsi/aic94xx/aic94xx_init.c
drivers/scsi/arcmsr/arcmsr_hba.c
drivers/scsi/be2iscsi/be_main.c
drivers/scsi/be2iscsi/be_mgmt.c
drivers/scsi/bfa/bfad_bsg.c
drivers/scsi/bnx2fc/bnx2fc_hwi.c
drivers/scsi/bnx2fc/bnx2fc_io.c
drivers/scsi/bnx2fc/bnx2fc_tgt.c
drivers/scsi/bnx2i/bnx2i_hwi.c
drivers/scsi/csiostor/csio_attr.c
drivers/scsi/csiostor/csio_wr.c
drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
drivers/scsi/cxgbi/libcxgbi.c
drivers/scsi/cxgbi/libcxgbi.h
drivers/scsi/cxlflash/main.c
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
drivers/scsi/isci/init.c
drivers/scsi/libfc/fc_lport.c
drivers/scsi/libfc/fc_rport.c
drivers/scsi/lpfc/lpfc_bsg.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_mbox.c
drivers/scsi/lpfc/lpfc_nvme.c
drivers/scsi/lpfc/lpfc_nvme.h
drivers/scsi/lpfc/lpfc_nvmet.c
drivers/scsi/lpfc/lpfc_nvmet.h
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/megaraid/megaraid_mbox.c
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/scsi/mesh.c
drivers/scsi/mvumi.c
drivers/scsi/pm8001/pm8001_sas.c
drivers/scsi/qedf/qedf_main.c
drivers/scsi/qedi/qedi_iscsi.c
drivers/scsi/qedi/qedi_iscsi.h
drivers/scsi/qedi/qedi_main.c
drivers/scsi/qla1280.c
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_bsg.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_gs.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla4xxx/ql4_init.c
drivers/scsi/qla4xxx/ql4_mbx.c
drivers/scsi/qla4xxx/ql4_nx.c
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_pm.c
drivers/scsi/sd.c
drivers/scsi/sd_zbc.c
drivers/scsi/smartpqi/smartpqi_init.c
drivers/scsi/ufs/ufs.h
drivers/scsi/ufs/ufshcd.c
drivers/soc/fsl/qbman/dpaa_sys.c
drivers/soc/fsl/qbman/qman.c
drivers/soc/fsl/qe/qe_tdm.c
drivers/soc/renesas/Kconfig
drivers/soc/renesas/r8a774c0-sysc.c
drivers/spi/spi-pic32-sqi.c
drivers/staging/android/ion/ion.c
drivers/staging/mt7621-eth/mtk_eth_soc.c
drivers/staging/octeon/ethernet-mdio.c
drivers/staging/rtl8188eu/core/rtw_security.c
drivers/staging/rtl8188eu/os_dep/usb_intf.c
drivers/staging/rtl8723bs/include/ieee80211.h
drivers/staging/rtl8723bs/os_dep/sdio_intf.c
drivers/staging/speakup/spk_ttyio.c
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
drivers/staging/vt6655/device_main.c
drivers/staging/wilc1000/host_interface.c
drivers/staging/wilc1000/wilc_wlan.c
drivers/target/iscsi/iscsi_target.c
drivers/target/target_core_configfs.c
drivers/target/target_core_user.c
drivers/thermal/cpu_cooling.c
drivers/thermal/intel/int340x_thermal/Kconfig
drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
drivers/thermal/of-thermal.c
drivers/tty/n_hdlc.c
drivers/tty/serial/8250/8250_core.c
drivers/tty/serial/8250/8250_mtk.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/Kconfig
drivers/tty/serial/Makefile
drivers/tty/serial/earlycon-riscv-sbi.c [new file with mode: 0644]
drivers/tty/serial/fsl_lpuart.c
drivers/tty/serial/lantiq.c
drivers/tty/serial/qcom_geni_serial.c
drivers/tty/serial/serial_core.c
drivers/tty/serial/sh-sci.c
drivers/tty/tty_io.c
drivers/tty/vt/vt.c
drivers/usb/chipidea/ci_hdrc_imx.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/generic.c
drivers/usb/core/ledtrig-usbport.c
drivers/usb/core/quirks.c
drivers/usb/dwc2/gadget.c
drivers/usb/dwc3/dwc3-exynos.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/function/f_sourcesink.c
drivers/usb/gadget/udc/bdc/bdc_core.c
drivers/usb/gadget/udc/net2272.c
drivers/usb/host/ehci-mv.c
drivers/usb/host/uhci-hcd.c
drivers/usb/host/xhci-mem.c
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/musbhsdma.c
drivers/usb/phy/Kconfig
drivers/usb/phy/phy-am335x.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/keyspan_usa26msg.h
drivers/usb/serial/keyspan_usa28msg.h
drivers/usb/serial/keyspan_usa49msg.h
drivers/usb/serial/keyspan_usa67msg.h
drivers/usb/serial/keyspan_usa90msg.h
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/serial/usb-serial-simple.c
drivers/usb/storage/scsiglue.c
drivers/usb/storage/unusual_devs.h
drivers/usb/typec/tcpm/tcpm.c
drivers/usb/usbip/README [deleted file]
drivers/vfio/pci/trace.h
drivers/vfio/pci/vfio_pci_nvlink2.c
drivers/vfio/vfio_iommu_type1.c
drivers/vhost/net.c
drivers/vhost/scsi.c
drivers/vhost/vhost.c
drivers/vhost/vhost.h
drivers/vhost/vsock.c
drivers/video/backlight/88pm860x_bl.c
drivers/video/backlight/pwm_bl.c
drivers/video/console/vgacon.c
drivers/video/fbdev/core/fbcon.c
drivers/video/fbdev/core/fbmem.c
drivers/video/fbdev/da8xx-fb.c
drivers/video/fbdev/offb.c
drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c
drivers/video/logo/Kconfig
drivers/virtio/virtio_balloon.c
drivers/virtio/virtio_mmio.c
drivers/virtio/virtio_pci_common.c
drivers/virtio/virtio_ring.c
drivers/watchdog/mt7621_wdt.c
drivers/watchdog/rt2880_wdt.c
drivers/watchdog/tqmx86_wdt.c
drivers/xen/events/events_base.c
drivers/xen/pvcalls-back.c
drivers/xen/pvcalls-front.c
drivers/xen/swiotlb-xen.c
fs/afs/flock.c
fs/afs/inode.c
fs/afs/protocol_yfs.h
fs/afs/rxrpc.c
fs/afs/server_list.c
fs/afs/yfsclient.c
fs/aio.c
fs/autofs/expire.c
fs/autofs/inode.c
fs/binfmt_script.c
fs/block_dev.c
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/volumes.c
fs/buffer.c
fs/ceph/addr.c
fs/ceph/caps.c
fs/ceph/quota.c
fs/ceph/super.c
fs/cifs/cifs_debug.c
fs/cifs/cifsfs.h
fs/cifs/cifsglob.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dfs_cache.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/smb2file.c
fs/cifs/smb2inode.c
fs/cifs/smb2misc.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/smb2pdu.h
fs/cifs/trace.c
fs/cifs/trace.h
fs/cifs/transport.c
fs/dcache.c
fs/debugfs/inode.c
fs/direct-io.c
fs/drop_caches.c
fs/ext4/fsync.c
fs/fs-writeback.c
fs/fuse/dev.c
fs/fuse/file.c
fs/fuse/inode.c
fs/gfs2/glops.c
fs/gfs2/log.c
fs/gfs2/lops.c
fs/gfs2/lops.h
fs/gfs2/ops_fstype.c
fs/gfs2/recovery.c
fs/gfs2/recovery.h
fs/gfs2/rgrp.c
fs/gfs2/super.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/iomap.c
fs/nfs/nfs4file.c
fs/nfs/super.c
fs/nfs/write.c
fs/nfsd/nfsctl.c
fs/nfsd/vfs.c
fs/notify/inotify/inotify_user.c
fs/proc/generic.c
fs/proc/internal.h
fs/proc/proc_net.c
fs/proc/task_mmu.c
fs/pstore/ram.c
fs/sysfs/dir.c
fs/sysfs/file.c
fs/sysfs/group.c
fs/sysfs/symlink.c
fs/xfs/scrub/repair.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_buf.c
include/asm-generic/shmparam.h [moved from include/uapi/asm-generic/shmparam.h with 100% similarity]
include/drm/drm_dp_helper.h
include/drm/drm_dp_mst_helper.h
include/dt-bindings/clock/imx8mq-clock.h
include/dt-bindings/clock/marvell,mmp2.h
include/dt-bindings/reset/amlogic,meson-axg-reset.h
include/kvm/arm_vgic.h
include/linux/backing-dev-defs.h
include/linux/bcma/bcma_soc.h
include/linux/blk_types.h
include/linux/blktrace_api.h
include/linux/bpf_verifier.h
include/linux/bpfilter.h
include/linux/ceph/libceph.h
include/linux/ceph/osd_client.h
include/linux/compiler-clang.h
include/linux/compiler-gcc.h
include/linux/compiler-intel.h
include/linux/compiler.h
include/linux/compiler_attributes.h
include/linux/cpu.h
include/linux/dcache.h
include/linux/dma-mapping.h
include/linux/efi.h
include/linux/fb.h
include/linux/filter.h
include/linux/fs.h
include/linux/hid-debug.h
include/linux/hid.h
include/linux/hyperv.h
include/linux/ide.h
include/linux/if_arp.h
include/linux/interrupt.h
include/linux/irqchip/arm-gic-v3.h
include/linux/libnvdimm.h
include/linux/memblock.h
include/linux/memory_hotplug.h
include/linux/mfd/cros_ec_commands.h
include/linux/mfd/ingenic-tcu.h
include/linux/mfd/madera/core.h
include/linux/mfd/ti_am335x_tscadc.h
include/linux/mfd/tmio.h
include/linux/mmc/card.h
include/linux/mmzone.h
include/linux/module.h
include/linux/netdevice.h
include/linux/of.h
include/linux/pci-dma-compat.h
include/linux/perf_event.h
include/linux/phy.h
include/linux/phy/phy.h
include/linux/pm_opp.h
include/linux/pm_runtime.h
include/linux/qcom_scm.h
include/linux/qed/qed_chain.h
include/linux/reset.h
include/linux/sched.h
include/linux/sched/coredump.h
include/linux/sched/wake_q.h
include/linux/signal.h
include/linux/skbuff.h
include/linux/stmmac.h
include/linux/umh.h
include/linux/virtio_config.h
include/linux/xarray.h
include/net/af_rxrpc.h
include/net/ax25.h
include/net/inetpeer.h
include/net/ip_fib.h
include/net/l3mdev.h
include/net/netfilter/nf_flow_table.h
include/net/netfilter/nf_tables.h
include/net/sock.h
include/net/tls.h
include/rdma/ib_verbs.h
include/sound/compress_driver.h
include/sound/hda_codec.h
include/sound/soc.h
include/trace/events/afs.h
include/uapi/linux/android/binderfs.h [moved from include/uapi/linux/android/binder_ctl.h with 83% similarity]
include/uapi/linux/audit.h
include/uapi/linux/blkzoned.h
include/uapi/linux/in.h
include/uapi/linux/inet_diag.h
include/uapi/linux/input.h
include/uapi/linux/ptp_clock.h
include/uapi/linux/virtio_config.h
include/uapi/linux/virtio_ring.h
include/uapi/rdma/hns-abi.h
include/uapi/rdma/vmw_pvrdma-abi.h
include/xen/arm/page-coherent.h
init/Kconfig
init/main.c
kernel/bpf/btf.c
kernel/bpf/cgroup.c
kernel/bpf/hashtab.c
kernel/bpf/map_in_map.c
kernel/bpf/percpu_freelist.c
kernel/bpf/percpu_freelist.h
kernel/bpf/stackmap.c
kernel/bpf/syscall.c
kernel/bpf/verifier.c
kernel/cpu.c
kernel/dma/swiotlb.c
kernel/events/core.c
kernel/events/ring_buffer.c
kernel/exit.c
kernel/fork.c
kernel/futex.c
kernel/irq/irqdesc.c
kernel/irq/manage.c
kernel/locking/rtmutex.c
kernel/locking/rwsem-xadd.c
kernel/relay.c
kernel/sched/core.c
kernel/sched/fair.c
kernel/sched/psi.c
kernel/seccomp.c
kernel/signal.c
kernel/smp.c
kernel/sys.c
kernel/time/posix-cpu-timers.c
kernel/trace/bpf_trace.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_probe_tmpl.h
kernel/trace/trace_uprobe.c
kernel/umh.c
kernel/workqueue.c
kernel/workqueue_internal.h
lib/crc32.c
lib/int_sqrt.c
lib/sbitmap.c
lib/test_kmod.c
lib/test_rhashtable.c
lib/test_xarray.c
lib/xarray.c
mm/backing-dev.c
mm/gup.c
mm/hugetlb.c
mm/kasan/Makefile
mm/kasan/common.c
mm/memblock.c
mm/memory-failure.c
mm/memory.c
mm/memory_hotplug.c
mm/migrate.c
mm/mincore.c
mm/oom_kill.c
mm/page_alloc.c
mm/page_ext.c
mm/rmap.c
mm/slab.c
mm/slub.c
mm/usercopy.c
mm/userfaultfd.c
mm/util.c
mm/vmscan.c
net/ax25/ax25_ip.c
net/ax25/ax25_route.c
net/batman-adv/bat_v_elp.c
net/batman-adv/hard-interface.c
net/batman-adv/soft-interface.c
net/bpfilter/bpfilter_kern.c
net/bpfilter/bpfilter_umh_blob.S
net/bridge/br_fdb.c
net/bridge/br_forward.c
net/bridge/br_netfilter_hooks.c
net/bridge/br_netfilter_ipv6.c
net/bridge/br_private.h
net/bridge/br_vlan.c
net/bridge/netfilter/ebtables.c
net/bridge/netfilter/nft_reject_bridge.c
net/can/bcm.c
net/can/gw.c
net/ceph/ceph_common.c
net/ceph/debugfs.c
net/ceph/messenger.c
net/ceph/osd_client.c
net/core/dev.c
net/core/filter.c
net/core/lwt_bpf.c
net/core/neighbour.c
net/core/skbuff.c
net/core/skmsg.c
net/core/sock.c
net/dccp/ccid.h
net/decnet/dn_dev.c
net/dsa/master.c
net/dsa/slave.c
net/ipv4/bpfilter/sockopt.c
net/ipv4/devinet.c
net/ipv4/fib_frontend.c
net/ipv4/fib_trie.c
net/ipv4/fou.c
net/ipv4/gre_demux.c
net/ipv4/inet_diag.c
net/ipv4/inetpeer.c
net/ipv4/ip_gre.c
net/ipv4/ip_input.c
net/ipv4/ip_sockglue.c
net/ipv4/ip_tunnel.c
net/ipv4/ip_vti.c
net/ipv4/netfilter/ipt_CLUSTERIP.c
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c
net/ipv4/netfilter/nf_nat_snmp_basic_main.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_timer.c
net/ipv4/udp.c
net/ipv4/udp_impl.h
net/ipv4/udplite.c
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/datagram.c
net/ipv6/fou6.c
net/ipv6/icmp.c
net/ipv6/ip6_gre.c
net/ipv6/ip6mr.c
net/ipv6/netfilter.c
net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
net/ipv6/route.c
net/ipv6/seg6.c
net/ipv6/seg6_iptunnel.c
net/ipv6/sit.c
net/ipv6/udp.c
net/ipv6/udp_impl.h
net/ipv6/udplite.c
net/l2tp/l2tp_core.c
net/l2tp/l2tp_core.h
net/l2tp/l2tp_ip.c
net/l2tp/l2tp_ip6.c
net/mac80211/agg-tx.c
net/mac80211/cfg.c
net/mac80211/rx.c
net/mac80211/tx.c
net/mac80211/util.c
net/netfilter/ipvs/Kconfig
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_flow_table_core.c
net/netfilter/nf_tables_api.c
net/netfilter/nfnetlink_osf.c
net/netfilter/nft_compat.c
net/netfilter/nft_dynset.c
net/netfilter/nft_flow_offload.c
net/netfilter/nft_immediate.c
net/netfilter/nft_lookup.c
net/netfilter/nft_objref.c
net/netfilter/x_tables.c
net/netrom/nr_timer.c
net/openvswitch/flow.c
net/openvswitch/flow_netlink.c
net/packet/af_packet.c
net/rds/bind.c
net/rds/ib_send.c
net/rds/message.c
net/rds/rds.h
net/rds/send.c
net/rose/rose_route.c
net/rxrpc/af_rxrpc.c
net/rxrpc/ar-internal.h
net/rxrpc/call_object.c
net/rxrpc/conn_client.c
net/rxrpc/recvmsg.c
net/rxrpc/sendmsg.c
net/sched/act_tunnel_key.c
net/sched/cls_api.c
net/sched/cls_flower.c
net/sched/cls_tcindex.c
net/sched/sch_cake.c
net/sched/sch_cbs.c
net/sched/sch_drr.c
net/sched/sch_dsmark.c
net/sched/sch_generic.c
net/sched/sch_hfsc.c
net/sched/sch_htb.c
net/sched/sch_prio.c
net/sched/sch_qfq.c
net/sched/sch_tbf.c
net/sctp/diag.c
net/sctp/ipv6.c
net/sctp/offload.c
net/sctp/protocol.c
net/sctp/sm_make_chunk.c
net/sctp/socket.c
net/sctp/stream.c
net/smc/af_smc.c
net/smc/smc_cdc.c
net/smc/smc_cdc.h
net/smc/smc_clc.c
net/smc/smc_close.c
net/smc/smc_core.c
net/smc/smc_core.h
net/smc/smc_ib.c
net/smc/smc_llc.c
net/smc/smc_pnet.c
net/smc/smc_tx.c
net/smc/smc_wr.c
net/smc/smc_wr.h
net/socket.c
net/sunrpc/auth.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/gss_krb5_seqnum.c
net/sunrpc/clnt.c
net/sunrpc/debugfs.c
net/sunrpc/xprt.c
net/sunrpc/xprtrdma/svc_rdma_sendto.c
net/sunrpc/xprtrdma/svc_rdma_transport.c
net/sunrpc/xprtrdma/verbs.c
net/sunrpc/xprtsock.c
net/tipc/link.c
net/tipc/msg.h
net/tipc/netlink_compat.c
net/tipc/node.c
net/tipc/topsrv.c
net/tls/tls_sw.c
net/vmw_vsock/virtio_transport.c
net/vmw_vsock/vmci_transport.c
net/wireless/ap.c
net/wireless/core.c
net/wireless/core.h
net/wireless/nl80211.c
net/wireless/pmsr.c
net/wireless/reg.c
net/wireless/sme.c
net/wireless/util.c
net/x25/af_x25.c
net/xdp/xdp_umem.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_user.c
samples/bpf/Makefile
samples/bpf/asm_goto_workaround.h [new file with mode: 0644]
samples/bpf/test_cgrp2_attach2.c
samples/bpf/test_current_task_under_cgroup_user.c
samples/bpf/xdp1_user.c
samples/mei/mei-amt-version.c
samples/seccomp/Makefile
scripts/Kbuild.include
scripts/coccinelle/api/alloc/alloc_cast.cocci
scripts/coccinelle/api/alloc/zalloc-simple.cocci
scripts/gcc-plugins/arm_ssp_per_task_plugin.c
scripts/kconfig/Makefile
scripts/mod/modpost.c
security/apparmor/domain.c
security/apparmor/lsm.c
security/security.c
security/selinux/ss/policydb.c
security/yama/yama_lsm.c
sound/aoa/soundbus/i2sbus/core.c
sound/core/compress_offload.c
sound/core/pcm_lib.c
sound/pci/cs46xx/dsp_spos.c
sound/pci/hda/hda_bind.c
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/hdac_hdmi.c
sound/soc/codecs/hdmi-codec.c
sound/soc/codecs/pcm512x.c
sound/soc/codecs/rt274.c
sound/soc/codecs/rt5514-spi.c
sound/soc/codecs/rt5682.c
sound/soc/codecs/rt5682.h
sound/soc/codecs/tlv320aic32x4.c
sound/soc/fsl/imx-audmux.c
sound/soc/intel/Kconfig
sound/soc/intel/atom/sst-mfld-platform-pcm.c
sound/soc/intel/boards/broadwell.c
sound/soc/intel/boards/glk_rt5682_max98357a.c
sound/soc/intel/boards/haswell.c
sound/soc/intel/skylake/skl.c
sound/soc/qcom/qdsp6/q6asm-dai.c
sound/soc/qcom/sdm845.c
sound/soc/samsung/i2s.c
sound/soc/sh/dma-sh7760.c
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/ssi.c
sound/soc/sh/rcar/ssiu.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/soc-topology.c
sound/soc/ti/davinci-mcasp.c
sound/soc/xilinx/Kconfig
sound/soc/xilinx/xlnx_i2s.c
sound/sparc/dbri.c
sound/usb/card.c
sound/usb/mixer.c
sound/usb/pcm.c
sound/usb/quirks-table.h
sound/usb/quirks.c
sound/usb/stream.c
tools/arch/powerpc/include/uapi/asm/perf_regs.h
tools/arch/powerpc/include/uapi/asm/unistd.h [deleted file]
tools/arch/riscv/include/uapi/asm/bitsperlong.h [new file with mode: 0644]
tools/arch/x86/include/asm/cpufeatures.h
tools/arch/x86/include/asm/disabled-features.h
tools/bpf/bpftool/Makefile
tools/bpf/bpftool/btf_dumper.c
tools/bpf/bpftool/common.c
tools/bpf/bpftool/json_writer.c
tools/bpf/bpftool/json_writer.h
tools/bpf/bpftool/map.c
tools/bpf/bpftool/prog.c
tools/iio/iio_generic_buffer.c
tools/include/uapi/asm-generic/unistd.h
tools/include/uapi/asm/bitsperlong.h
tools/include/uapi/drm/i915_drm.h
tools/include/uapi/linux/fs.h
tools/include/uapi/linux/if_link.h
tools/include/uapi/linux/in.h
tools/include/uapi/linux/kvm.h
tools/include/uapi/linux/mount.h [new file with mode: 0644]
tools/include/uapi/linux/pkt_sched.h [new file with mode: 0644]
tools/include/uapi/linux/prctl.h
tools/include/uapi/linux/vhost.h
tools/lib/bpf/.gitignore
tools/lib/bpf/README.rst
tools/lib/bpf/bpf.c
tools/lib/traceevent/event-parse-api.c
tools/lib/traceevent/event-parse-local.h
tools/lib/traceevent/event-parse.c
tools/lib/traceevent/event-parse.h
tools/lib/traceevent/plugin_kvm.c
tools/lib/traceevent/trace-seq.c
tools/perf/Documentation/perf-c2c.txt
tools/perf/Documentation/perf-mem.txt
tools/perf/Makefile.perf
tools/perf/arch/arm/tests/Build
tools/perf/arch/arm/tests/arch-tests.c
tools/perf/arch/arm/tests/vectors-page.c [new file with mode: 0644]
tools/perf/arch/powerpc/Makefile
tools/perf/arch/powerpc/entry/syscalls/mksyscalltbl
tools/perf/arch/powerpc/entry/syscalls/syscall.tbl [new file with mode: 0644]
tools/perf/arch/powerpc/include/perf_regs.h
tools/perf/arch/powerpc/util/Build
tools/perf/arch/powerpc/util/mem-events.c [new file with mode: 0644]
tools/perf/arch/powerpc/util/perf_regs.c
tools/perf/builtin-script.c
tools/perf/builtin-stat.c
tools/perf/builtin-top.c
tools/perf/builtin-trace.c
tools/perf/check-headers.sh
tools/perf/perf-read-vdso.c
tools/perf/tests/attr.py
tools/perf/tests/evsel-tp-sched.c
tools/perf/tests/shell/lib/probe_vfs_getname.sh
tools/perf/tests/tests.h
tools/perf/trace/beauty/mount_flags.sh
tools/perf/trace/beauty/prctl_option.sh
tools/perf/ui/browsers/annotate.c
tools/perf/util/annotate.c
tools/perf/util/c++/clang.cpp
tools/perf/util/callchain.c
tools/perf/util/callchain.h
tools/perf/util/cpumap.c
tools/perf/util/find-map.c [moved from tools/perf/util/find-vdso-map.c with 71% similarity]
tools/perf/util/machine.c
tools/perf/util/mem-events.c
tools/perf/util/ordered-events.c
tools/perf/util/setup.py
tools/perf/util/strbuf.c
tools/perf/util/symbol-elf.c
tools/perf/util/symbol.c
tools/perf/util/vdso.c
tools/testing/nvdimm/dimm_devs.c
tools/testing/selftests/Makefile
tools/testing/selftests/bpf/.gitignore
tools/testing/selftests/bpf/Makefile
tools/testing/selftests/bpf/bpf_util.h
tools/testing/selftests/bpf/cgroup_helpers.c
tools/testing/selftests/bpf/test_btf.c
tools/testing/selftests/bpf/test_cgroup_storage.c
tools/testing/selftests/bpf/test_dev_cgroup.c
tools/testing/selftests/bpf/test_netcnt.c
tools/testing/selftests/bpf/test_progs.c
tools/testing/selftests/bpf/test_skb_cgroup_id_user.c
tools/testing/selftests/bpf/test_sock.c
tools/testing/selftests/bpf/test_sock_addr.c
tools/testing/selftests/bpf/test_socket_cookie.c
tools/testing/selftests/bpf/test_tcpbpf_user.c
tools/testing/selftests/bpf/test_tcpnotify_user.c
tools/testing/selftests/bpf/test_verifier.c
tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh
tools/testing/selftests/drivers/net/mlxsw/rtnetlink.sh
tools/testing/selftests/drivers/net/mlxsw/vxlan.sh
tools/testing/selftests/filesystems/binderfs/.gitignore [new file with mode: 0644]
tools/testing/selftests/filesystems/binderfs/Makefile [new file with mode: 0644]
tools/testing/selftests/filesystems/binderfs/binderfs_test.c [new file with mode: 0644]
tools/testing/selftests/filesystems/binderfs/config [new file with mode: 0644]
tools/testing/selftests/gpio/gpio-mockup-chardev.c
tools/testing/selftests/ir/Makefile
tools/testing/selftests/kvm/lib/kvm_util.c
tools/testing/selftests/kvm/x86_64/evmcs_test.c
tools/testing/selftests/net/Makefile
tools/testing/selftests/net/forwarding/bridge_vlan_aware.sh
tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh
tools/testing/selftests/net/ip_defrag.c
tools/testing/selftests/net/ip_defrag.sh
tools/testing/selftests/net/xfrm_policy.sh
tools/testing/selftests/netfilter/Makefile
tools/testing/selftests/netfilter/config
tools/testing/selftests/netfilter/nft_nat.sh [new file with mode: 0755]
tools/testing/selftests/networking/timestamping/Makefile
tools/testing/selftests/networking/timestamping/txtimestamp.c
tools/testing/selftests/proc/.gitignore
tools/testing/selftests/proc/Makefile
tools/testing/selftests/proc/setns-dcache.c [new file with mode: 0644]
tools/testing/selftests/rtc/rtctest.c
tools/testing/selftests/seccomp/Makefile
tools/testing/selftests/seccomp/seccomp_bpf.c
tools/testing/selftests/tc-testing/tc-tests/actions/ife.json
tools/testing/selftests/tc-testing/tc-tests/actions/tunnel_key.json
tools/testing/selftests/timers/Makefile
tools/testing/selftests/vm/gup_benchmark.c
tools/testing/selftests/x86/mpx-mini-test.c
tools/testing/selftests/x86/protection_keys.c
tools/testing/selftests/x86/unwind_vdso.c
tools/thermal/tmon/Makefile
tools/vm/page_owner_sort.c
virt/kvm/arm/arm.c
virt/kvm/arm/mmu.c
virt/kvm/arm/psci.c
virt/kvm/arm/vgic/vgic-debug.c
virt/kvm/arm/vgic/vgic-init.c
virt/kvm/arm/vgic/vgic-its.c
virt/kvm/arm/vgic/vgic-mmio-v2.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/kvm_main.c

index e6080f5..bc2ffb2 100644 (file)
@@ -72,6 +72,10 @@ ForEachMacros:
   - 'apei_estatus_for_each_section'
   - 'ata_for_each_dev'
   - 'ata_for_each_link'
+  - '__ata_qc_for_each'
+  - 'ata_qc_for_each'
+  - 'ata_qc_for_each_raw'
+  - 'ata_qc_for_each_with_internal'
   - 'ax25_for_each'
   - 'ax25_uid_for_each'
   - 'bio_for_each_integrity_vec'
@@ -85,6 +89,7 @@ ForEachMacros:
   - 'blk_queue_for_each_rl'
   - 'bond_for_each_slave'
   - 'bond_for_each_slave_rcu'
+  - 'bpf_for_each_spilled_reg'
   - 'btree_for_each_safe128'
   - 'btree_for_each_safe32'
   - 'btree_for_each_safe64'
@@ -103,6 +108,8 @@ ForEachMacros:
   - '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_connector_for_each_possible_encoder'
   - 'drm_for_each_connector_iter'
   - 'drm_for_each_crtc'
   - 'drm_for_each_encoder'
@@ -121,11 +128,21 @@ ForEachMacros:
   - 'for_each_bio'
   - 'for_each_board_func_rsrc'
   - 'for_each_bvec'
+  - 'for_each_card_components'
+  - 'for_each_card_links'
+  - 'for_each_card_links_safe'
+  - 'for_each_card_prelinks'
+  - 'for_each_card_rtds'
+  - 'for_each_card_rtds_safe'
+  - 'for_each_cgroup_storage_type'
   - 'for_each_child_of_node'
   - 'for_each_clear_bit'
   - 'for_each_clear_bit_from'
   - 'for_each_cmsghdr'
   - 'for_each_compatible_node'
+  - 'for_each_component_dais'
+  - 'for_each_component_dais_safe'
+  - 'for_each_comp_order'
   - 'for_each_console'
   - 'for_each_cpu'
   - 'for_each_cpu_and'
@@ -133,6 +150,10 @@ ForEachMacros:
   - 'for_each_cpu_wrap'
   - 'for_each_dev_addr'
   - 'for_each_dma_cap_mask'
+  - 'for_each_dpcm_be'
+  - 'for_each_dpcm_be_rollback'
+  - 'for_each_dpcm_be_safe'
+  - 'for_each_dpcm_fe'
   - 'for_each_drhd_unit'
   - 'for_each_dss_dev'
   - 'for_each_efi_memory_desc'
@@ -149,6 +170,7 @@ ForEachMacros:
   - 'for_each_iommu'
   - 'for_each_ip_tunnel_rcu'
   - 'for_each_irq_nr'
+  - 'for_each_link_codecs'
   - 'for_each_lru'
   - 'for_each_matching_node'
   - 'for_each_matching_node_and_match'
@@ -160,6 +182,7 @@ ForEachMacros:
   - 'for_each_mem_range_rev'
   - 'for_each_migratetype_order'
   - 'for_each_msi_entry'
+  - 'for_each_msi_entry_safe'
   - 'for_each_net'
   - 'for_each_netdev'
   - 'for_each_netdev_continue'
@@ -183,12 +206,14 @@ ForEachMacros:
   - 'for_each_node_with_property'
   - 'for_each_of_allnodes'
   - 'for_each_of_allnodes_from'
+  - 'for_each_of_cpu_node'
   - 'for_each_of_pci_range'
   - 'for_each_old_connector_in_state'
   - 'for_each_old_crtc_in_state'
   - 'for_each_oldnew_connector_in_state'
   - 'for_each_oldnew_crtc_in_state'
   - 'for_each_oldnew_plane_in_state'
+  - 'for_each_oldnew_plane_in_state_reverse'
   - 'for_each_oldnew_private_obj_in_state'
   - 'for_each_old_plane_in_state'
   - 'for_each_old_private_obj_in_state'
@@ -206,14 +231,17 @@ ForEachMacros:
   - 'for_each_process'
   - 'for_each_process_thread'
   - 'for_each_property_of_node'
+  - 'for_each_registered_fb'
   - 'for_each_reserved_mem_region'
-  - 'for_each_resv_unavail_range'
+  - 'for_each_rtd_codec_dai'
+  - 'for_each_rtd_codec_dai_rollback'
   - 'for_each_rtdcom'
   - 'for_each_rtdcom_safe'
   - 'for_each_set_bit'
   - 'for_each_set_bit_from'
   - 'for_each_sg'
   - 'for_each_sg_page'
+  - 'for_each_sibling_event'
   - '__for_each_thread'
   - 'for_each_thread'
   - 'for_each_zone'
@@ -251,6 +279,8 @@ ForEachMacros:
   - 'hlist_nulls_for_each_entry_from'
   - 'hlist_nulls_for_each_entry_rcu'
   - 'hlist_nulls_for_each_entry_safe'
+  - 'i3c_bus_for_each_i2cdev'
+  - 'i3c_bus_for_each_i3cdev'
   - 'ide_host_for_each_port'
   - 'ide_port_for_each_dev'
   - 'ide_port_for_each_present_dev'
@@ -267,11 +297,14 @@ ForEachMacros:
   - 'kvm_for_each_memslot'
   - 'kvm_for_each_vcpu'
   - 'list_for_each'
+  - 'list_for_each_codec'
+  - 'list_for_each_codec_safe'
   - 'list_for_each_entry'
   - 'list_for_each_entry_continue'
   - 'list_for_each_entry_continue_rcu'
   - 'list_for_each_entry_continue_reverse'
   - 'list_for_each_entry_from'
+  - 'list_for_each_entry_from_rcu'
   - 'list_for_each_entry_from_reverse'
   - 'list_for_each_entry_lockless'
   - 'list_for_each_entry_rcu'
@@ -291,6 +324,7 @@ ForEachMacros:
   - 'media_device_for_each_intf'
   - 'media_device_for_each_link'
   - 'media_device_for_each_pad'
+  - 'nanddev_io_for_each_page'
   - 'netdev_for_each_lower_dev'
   - 'netdev_for_each_lower_private'
   - 'netdev_for_each_lower_private_rcu'
@@ -357,12 +391,14 @@ ForEachMacros:
   - 'sk_nulls_for_each'
   - 'sk_nulls_for_each_from'
   - 'sk_nulls_for_each_rcu'
+  - 'snd_array_for_each'
   - 'snd_pcm_group_for_each_entry'
   - 'snd_soc_dapm_widget_for_each_path'
   - 'snd_soc_dapm_widget_for_each_path_safe'
   - 'snd_soc_dapm_widget_for_each_sink_path'
   - 'snd_soc_dapm_widget_for_each_source_path'
   - 'tb_property_for_each'
+  - 'tcf_exts_for_each_action'
   - 'udp_portaddr_for_each_entry'
   - 'udp_portaddr_for_each_entry_rcu'
   - 'usb_hub_for_each_child'
@@ -371,6 +407,11 @@ ForEachMacros:
   - 'v4l2_m2m_for_each_dst_buf_safe'
   - 'v4l2_m2m_for_each_src_buf'
   - 'v4l2_m2m_for_each_src_buf_safe'
+  - 'virtio_device_for_each_vq'
+  - 'xa_for_each'
+  - 'xas_for_each'
+  - 'xas_for_each_conflict'
+  - 'xas_for_each_marked'
   - 'zorro_for_each_dev'
 
 #IncludeBlocks: Preserve # Unknown to clang-format-5.0
index 9b64266..169fe08 100644 (file)
@@ -24,7 +24,7 @@ What:         /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
                                                        cpld3_version
 
 Date:          November 2018
-KernelVersion: 4.21
+KernelVersion: 5.0
 Contact:       Vadim Pasternak <vadimpmellanox.com>
 Description:   These files show with which CPLD versions have been burned
                on LED board.
@@ -35,7 +35,7 @@ What:         /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
                                                        jtag_enable
 
 Date:          November 2018
-KernelVersion: 4.21
+KernelVersion: 5.0
 Contact:       Vadim Pasternak <vadimpmellanox.com>
 Description:   These files enable and disable the access to the JTAG domain.
                By default access to the JTAG domain is disabled.
@@ -105,7 +105,7 @@ What:               /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
                                                reset_voltmon_upgrade_fail
 
 Date:          November 2018
-KernelVersion: 4.21
+KernelVersion: 5.0
 Contact:       Vadim Pasternak <vadimpmellanox.com>
 Description:   These files show the system reset cause, as following: ComEx
                power fail, reset from ComEx, system platform reset, reset
index 7710d40..dfad742 100644 (file)
@@ -279,3 +279,12 @@ Description:
                size in 512B sectors of the zones of the device, with
                the eventual exception of the last zone of the device
                which may be smaller.
+
+What:          /sys/block/<disk>/queue/io_timeout
+Date:          November 2018
+Contact:       Weiping Zhang <zhangweiping@didiglobal.com>
+Description:
+               io_timeout is the request timeout in milliseconds. If a request
+               does not complete in this time then the block driver timeout
+               handler is invoked. That timeout handler can decide to retry
+               the request, to fail it or to start a device recovery strategy.
index 9d2339a..14b2bf2 100644 (file)
@@ -122,11 +122,18 @@ Description:
                statistics (bd_count, bd_reads, bd_writes) in a format
                similar to block layer statistics file format.
 
+What:          /sys/block/zram<id>/writeback_limit_enable
+Date:          November 2018
+Contact:       Minchan Kim <minchan@kernel.org>
+Description:
+               The writeback_limit_enable file is read-write and specifies
+               eanbe of writeback_limit feature. "1" means eable the feature.
+               No limit "0" is the initial state.
+
 What:          /sys/block/zram<id>/writeback_limit
 Date:          November 2018
 Contact:       Minchan Kim <minchan@kernel.org>
 Description:
                The writeback_limit file is read-write and specifies the maximum
                amount of writeback ZRAM can do. The limit could be changed
-               in run time and "0" means disable the limit.
-               No limit is the initial state.
+               in run time.
index b799bcf..858b6c0 100644 (file)
                        By default, super page will be supported if Intel IOMMU
                        has the capability. With this option, super page will
                        not be supported.
-               sm_off [Default Off]
-                       By default, scalable mode will be supported if the
+               sm_on [Default Off]
+                       By default, scalable mode will be disabled even if the
                        hardware advertises that it has support for the scalable
                        mode translation. With this option set, scalable mode
-                       will not be used even on hardware which claims to support
-                       it.
+                       will be used on hardware which claims to support it.
                tboot_noforce [Default Off]
                        Do not force the Intel IOMMU enabled under tboot.
                        By default, tboot will force Intel IOMMU on, which
index 8d8d8f0..98a8dd5 100644 (file)
@@ -357,6 +357,13 @@ video playing/streaming, a very low drop rate may be more important
 than maximum throughput. In these cases, consider setting the
 strict_guarantees parameter.
 
+slice_idle_us
+-------------
+
+Controls the same tuning parameter as slice_idle, but in microseconds.
+Either tunable can be used to set idling behavior.  Afterwards, the
+other tunable will reflect the newly set value in sysfs.
+
 strict_guarantees
 -----------------
 
index ea2dafe..4cad102 100644 (file)
@@ -88,7 +88,8 @@ shared_tags=[0/1]: Default: 0
 
 zoned=[0/1]: Default: 0
   0: Block device is exposed as a random-access block device.
-  1: Block device is exposed as a host-managed zoned block device.
+  1: Block device is exposed as a host-managed zoned block device. Requires
+     CONFIG_BLK_DEV_ZONED.
 
 zone_size=[MB]: Default: 256
   Per zone size when exposed as a zoned block device. Must be a power of two.
index 39e286d..83b457e 100644 (file)
@@ -67,6 +67,13 @@ If set to a value larger than 0, the kernel will put the process issuing
 IO to sleep for this amount of microseconds before entering classic
 polling.
 
+io_timeout (RW)
+---------------
+io_timeout is the request timeout in milliseconds. If a request does not
+complete in this time then the block driver timeout handler is invoked.
+That timeout handler can decide to retry the request, to fail it or to start
+a device recovery strategy.
+
 iostats (RW)
 -------------
 This file is used to control (on/off) the iostats accounting of the
index 436c5e9..4df0ce2 100644 (file)
@@ -156,22 +156,23 @@ Per-device statistics are exported as various nodes under /sys/block/zram<id>/
 A brief description of exported device attributes. For more details please
 read Documentation/ABI/testing/sysfs-block-zram.
 
-Name            access            description
-----            ------            -----------
-disksize          RW    show and set the device's disk size
-initstate         RO    shows the initialization state of the device
-reset             WO    trigger device reset
-mem_used_max      WO    reset the `mem_used_max' counter (see later)
-mem_limit         WO    specifies the maximum amount of memory ZRAM can use
-                        to store the compressed data
-writeback_limit   WO    specifies the maximum amount of write IO zram can
-                       write out to backing device as 4KB unit
-max_comp_streams  RW    the number of possible concurrent compress operations
-comp_algorithm    RW    show and change the compression algorithm
-compact           WO    trigger memory compaction
-debug_stat        RO    this file is used for zram debugging purposes
-backing_dev      RW    set up backend storage for zram to write out
-idle             WO    mark allocated slot as idle
+Name                   access            description
+----                   ------            -----------
+disksize               RW      show and set the device's disk size
+initstate              RO      shows the initialization state of the device
+reset                  WO      trigger device reset
+mem_used_max           WO      reset the `mem_used_max' counter (see later)
+mem_limit              WO      specifies the maximum amount of memory ZRAM can use
+                               to store the compressed data
+writeback_limit        WO      specifies the maximum amount of write IO zram can
+                               write out to backing device as 4KB unit
+writeback_limit_enable  RW     show and set writeback_limit feature
+max_comp_streams       RW      the number of possible concurrent compress operations
+comp_algorithm         RW      show and change the compression algorithm
+compact                WO      trigger memory compaction
+debug_stat             RO      this file is used for zram debugging purposes
+backing_dev            RW      set up backend storage for zram to write out
+idle                   WO      mark allocated slot as idle
 
 
 User space is advised to use the following files to read the device statistics.
@@ -280,32 +281,51 @@ With the command, zram writeback idle pages from memory to the storage.
 If there are lots of write IO with flash device, potentially, it has
 flash wearout problem so that admin needs to design write limitation
 to guarantee storage health for entire product life.
-To overcome the concern, zram supports "writeback_limit".
-The "writeback_limit"'s default value is 0 so that it doesn't limit
-any writeback. If admin want to measure writeback count in a certain
-period, he could know it via /sys/block/zram0/bd_stat's 3rd column.
+
+To overcome the concern, zram supports "writeback_limit" feature.
+The "writeback_limit_enable"'s default value is 0 so that it doesn't limit
+any writeback. IOW, if admin want to apply writeback budget, he should
+enable writeback_limit_enable via
+
+       $ echo 1 > /sys/block/zramX/writeback_limit_enable
+
+Once writeback_limit_enable is set, zram doesn't allow any writeback
+until admin set the budget via /sys/block/zramX/writeback_limit.
+
+(If admin doesn't enable writeback_limit_enable, writeback_limit's value
+assigned via /sys/block/zramX/writeback_limit is meaninless.)
 
 If admin want to limit writeback as per-day 400M, he could do it
 like below.
 
-    MB_SHIFT=20
-    4K_SHIFT=12
-    echo $((400<<MB_SHIFT>>4K_SHIFT)) > \
-           /sys/block/zram0/writeback_limit.
+       $ MB_SHIFT=20
+       $ 4K_SHIFT=12
+       $ echo $((400<<MB_SHIFT>>4K_SHIFT)) > \
+               /sys/block/zram0/writeback_limit.
+       $ echo 1 > /sys/block/zram0/writeback_limit_enable
 
-If admin want to allow further write again, he could do it like below
+If admin want to allow further write again once the bugdet is exausted,
+he could do it like below
 
-    echo 0 > /sys/block/zram0/writeback_limit
+       $ echo $((400<<MB_SHIFT>>4K_SHIFT)) > \
+               /sys/block/zram0/writeback_limit
 
 If admin want to see remaining writeback budget since he set,
 
-    cat /sys/block/zram0/writeback_limit
+       $ cat /sys/block/zramX/writeback_limit
+
+If admin want to disable writeback limit, he could do
+
+       $ echo 0 > /sys/block/zramX/writeback_limit_enable
 
 The writeback_limit count will reset whenever you reset zram(e.g.,
 system reboot, echo 1 > /sys/block/zramX/reset) so keeping how many of
 writeback happened until you reset the zram to allocate extra writeback
 budget in next setting is user's job.
 
+If admin want to measure writeback count in a certain period, he could
+know it via /sys/block/zram0/bd_stat's 3rd column.
+
 = memory tracking
 
 With CONFIG_ZRAM_MEMORY_TRACKING, user can know information of the
index 6780a6d..7cc9e36 100644 (file)
@@ -157,12 +157,11 @@ Q: Does BPF have a stable ABI?
 ------------------------------
 A: YES. BPF instructions, arguments to BPF programs, set of helper
 functions and their arguments, recognized return codes are all part
-of ABI. However when tracing programs are using bpf_probe_read() helper
-to walk kernel internal datastructures and compile with kernel
-internal headers these accesses can and will break with newer
-kernels. The union bpf_attr -> kern_version is checked at load time
-to prevent accidentally loading kprobe-based bpf programs written
-for a different kernel. Networking programs don't do kern_version check.
+of ABI. However there is one specific exception to tracing programs
+which are using helpers like bpf_probe_read() to walk kernel internal
+data structures and compile with kernel internal headers. Both of these
+kernel internals are subject to change and can break with newer kernels
+such that the program needs to be adapted accordingly.
 
 Q: How much stack space a BPF program uses?
 -------------------------------------------
index 6a6d67a..5d54b27 100644 (file)
@@ -108,12 +108,13 @@ some, but not all of the other indices changing.
 
 Sometimes you need to ensure that a subsequent call to :c:func:`xa_store`
 will not need to allocate memory.  The :c:func:`xa_reserve` function
-will store a reserved entry at the indicated index.  Users of the normal
-API will see this entry as containing ``NULL``.  If you do not need to
-use the reserved entry, you can call :c:func:`xa_release` to remove the
-unused entry.  If another user has stored to the entry in the meantime,
-:c:func:`xa_release` will do nothing; if instead you want the entry to
-become ``NULL``, you should use :c:func:`xa_erase`.
+will store a reserved entry at the indicated index.  Users of the
+normal API will see this entry as containing ``NULL``.  If you do
+not need to use the reserved entry, you can call :c:func:`xa_release`
+to remove the unused entry.  If another user has stored to the entry
+in the meantime, :c:func:`xa_release` will do nothing; if instead you
+want the entry to become ``NULL``, you should use :c:func:`xa_erase`.
+Using :c:func:`xa_insert` on a reserved entry will fail.
 
 If all entries in the array are ``NULL``, the :c:func:`xa_empty` function
 will return ``true``.
@@ -183,6 +184,8 @@ Takes xa_lock internally:
  * :c:func:`xa_store_bh`
  * :c:func:`xa_store_irq`
  * :c:func:`xa_insert`
+ * :c:func:`xa_insert_bh`
+ * :c:func:`xa_insert_irq`
  * :c:func:`xa_erase`
  * :c:func:`xa_erase_bh`
  * :c:func:`xa_erase_irq`
index 6e5cef0..50daa0b 100644 (file)
@@ -17,7 +17,11 @@ extra-y += $(DT_TMP_SCHEMA)
 quiet_cmd_mk_schema = SCHEMA  $@
       cmd_mk_schema = $(DT_MK_SCHEMA) $(DT_MK_SCHEMA_FLAGS) -o $@ $(filter-out FORCE, $^)
 
-DT_DOCS = $(shell cd $(srctree)/$(src) && find * -name '*.yaml')
+DT_DOCS = $(shell \
+       cd $(srctree)/$(src) && \
+       find * \( -name '*.yaml' ! -name $(DT_TMP_SCHEMA) \) \
+       )
+
 DT_SCHEMA_FILES ?= $(addprefix $(src)/,$(DT_DOCS))
 
 extra-y += $(patsubst $(src)/%.yaml,%.example.dts, $(DT_SCHEMA_FILES))
index 84262cd..96fa46c 100644 (file)
@@ -235,4 +235,4 @@ cpus {
 ===========================================
 
 [1] ARM Linux Kernel documentation - CPUs bindings
-    Documentation/devicetree/bindings/arm/cpus.txt
+    Documentation/devicetree/bindings/arm/cpus.yaml
index 8f0937d..45730ba 100644 (file)
@@ -684,7 +684,7 @@ cpus {
 ===========================================
 
 [1] ARM Linux Kernel documentation - CPUs bindings
-    Documentation/devicetree/bindings/arm/cpus.txt
+    Documentation/devicetree/bindings/arm/cpus.yaml
 
 [2] ARM Linux Kernel documentation - PSCI bindings
     Documentation/devicetree/bindings/arm/psci.txt
index 1b2ab1f..46652bf 100644 (file)
@@ -4,7 +4,7 @@ SP810 System Controller
 Required properties:
 
 - compatible:  standard compatible string for a Primecell peripheral,
-               see Documentation/devicetree/bindings/arm/primecell.txt
+               see Documentation/devicetree/bindings/arm/primecell.yaml
                for more details
                should be: "arm,sp810", "arm,primecell"
 
index de9eb04..b0d80c0 100644 (file)
@@ -472,4 +472,4 @@ cpus {
 
 ===============================================================================
 [1] ARM Linux kernel documentation
-    Documentation/devicetree/bindings/arm/cpus.txt
+    Documentation/devicetree/bindings/arm/cpus.yaml
index af376a0..23b52dc 100644 (file)
@@ -18,4 +18,4 @@ Required Properties:
 Each clock is assigned an identifier and client nodes use this identifier
 to specify the clock which they consume.
 
-All these identifier could be found in <dt-bindings/clock/marvell-mmp2.h>.
+All these identifiers could be found in <dt-bindings/clock/marvell,mmp2.h>.
index ef89ab4..572fa27 100644 (file)
@@ -1,6 +1,6 @@
 * ARM PrimeCell Color LCD Controller PL110/PL111
 
-See also Documentation/devicetree/bindings/arm/primecell.txt
+See also Documentation/devicetree/bindings/arm/primecell.yaml
 
 Required properties:
 
index ac8df3b..f875914 100644 (file)
@@ -27,7 +27,6 @@ Example:
                reg = <0x04300000 0x20000>;
                reg-names = "kgsl_3d0_reg_memory";
                interrupts = <GIC_SPI 80 0>;
-               interrupt-names = "kgsl_3d0_irq";
                clock-names =
                    "core",
                    "iface",
index 38ca220..2e097b5 100644 (file)
@@ -14,8 +14,6 @@ Required properties:
 
     "marvell,armada-8k-gpio" should be used for the Armada 7K and 8K
     SoCs (either from AP or CP), see
-    Documentation/devicetree/bindings/arm/marvell/cp110-system-controller0.txt
-    and
     Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt
     for specific details about the offset property.
 
index b83bb82..a3be529 100644 (file)
@@ -78,7 +78,7 @@ Sub-nodes:
 PPI affinity can be expressed as a single "ppi-partitions" node,
 containing a set of sub-nodes, each with the following property:
 - affinity: Should be a list of phandles to CPU nodes (as described in
-Documentation/devicetree/bindings/arm/cpus.txt).
+  Documentation/devicetree/bindings/arm/cpus.yaml).
 
 GICv3 has one or more Interrupt Translation Services (ITS) that are
 used to route Message Signalled Interrupts (MSI) to the CPUs.
index 98c9f56..38fe34f 100644 (file)
@@ -1,7 +1,8 @@
 Altera SOCFPGA Reset Manager
 
 Required properties:
-- compatible : "altr,rst-mgr"
+- compatible : "altr,rst-mgr" for (Cyclone5/Arria5/Arria10)
+              "altr,stratix10-rst-mgr","altr,rst-mgr" for Stratix10 ARM64 SoC
 - reg : Should contain 1 register ranges(address and length)
 - altr,modrst-offset : Should contain the offset of the first modrst register.
 - #reset-cells: 1
index 101743d..ea00517 100644 (file)
@@ -120,27 +120,30 @@ Example:
        };
 
 
-USB3 core reset
----------------
+Peripheral core reset in glue layer
+-----------------------------------
 
-USB3 core reset belongs to USB3 glue layer. Before using the core reset,
-it is necessary to control the clocks and resets to enable this layer.
-These clocks and resets should be described in each property.
+Some peripheral core reset belongs to its own glue layer. Before using
+this core reset, it is necessary to control the clocks and resets to enable
+this layer. These clocks and resets should be described in each property.
 
 Required properties:
 - compatible: Should be
-    "socionext,uniphier-pro4-usb3-reset" - for Pro4 SoC
-    "socionext,uniphier-pxs2-usb3-reset" - for PXs2 SoC
-    "socionext,uniphier-ld20-usb3-reset" - for LD20 SoC
-    "socionext,uniphier-pxs3-usb3-reset" - for PXs3 SoC
+    "socionext,uniphier-pro4-usb3-reset" - for Pro4 SoC USB3
+    "socionext,uniphier-pxs2-usb3-reset" - for PXs2 SoC USB3
+    "socionext,uniphier-ld20-usb3-reset" - for LD20 SoC USB3
+    "socionext,uniphier-pxs3-usb3-reset" - for PXs3 SoC USB3
+    "socionext,uniphier-pro4-ahci-reset" - for Pro4 SoC AHCI
+    "socionext,uniphier-pxs2-ahci-reset" - for PXs2 SoC AHCI
+    "socionext,uniphier-pxs3-ahci-reset" - for PXs3 SoC AHCI
 - #reset-cells: Should be 1.
 - reg: Specifies offset and length of the register set for the device.
-- clocks: A list of phandles to the clock gate for USB3 glue layer.
+- clocks: A list of phandles to the clock gate for the glue layer.
        According to the clock-names, appropriate clocks are required.
 - clock-names: Should contain
     "gio", "link" - for Pro4 SoC
     "link"        - for others
-- resets: A list of phandles to the reset control for USB3 glue layer.
+- resets: A list of phandles to the reset control for the glue layer.
        According to the reset-names, appropriate resets are required.
 - reset-names: Should contain
     "gio", "link" - for Pro4 SoC
index 3660341..0e72183 100644 (file)
@@ -4,14 +4,10 @@ Required properties:
 - compatible : "olpc,ap-sp"
 - reg : base address and length of SoC's WTM registers
 - interrupts : SP-AP interrupt
-- clocks : phandle + clock-specifier for the clock that drives the WTM
-- clock-names:  should be "sp"
 
 Example:
        ap-sp@d4290000 {
                compatible = "olpc,ap-sp";
                reg = <0xd4290000 0x1000>;
                interrupts = <40>;
-               clocks = <&soc_clocks MMP2_CLK_SP>;
-               clock-names = "sp";
        }
index 0b8cc53..cf759e5 100644 (file)
@@ -55,7 +55,7 @@ of these nodes are defined by the individual bindings for the specific function
 = EXAMPLE
 The following example represents the GLINK RPM node on a MSM8996 device, with
 the function for the "rpm_request" channel defined, which is used for
-regualtors and root clocks.
+regulators and root clocks.
 
        apcs_glb: mailbox@9820000 {
                compatible = "qcom,msm8996-apcs-hmss-global";
index a35af2d..49e1d72 100644 (file)
@@ -41,12 +41,12 @@ processor ID) and a string identifier.
 - qcom,local-pid:
        Usage: required
        Value type: <u32>
-       Definition: specifies the identfier of the local endpoint of this edge
+       Definition: specifies the identifier of the local endpoint of this edge
 
 - qcom,remote-pid:
        Usage: required
        Value type: <u32>
-       Definition: specifies the identfier of the remote endpoint of this edge
+       Definition: specifies the identifier of the remote endpoint of this edge
 
 = SUBNODES
 Each SMP2P pair contain a set of inbound and outbound entries, these are
index b577a45..c247b48 100644 (file)
@@ -124,11 +124,11 @@ struct bus_attribute {
        ssize_t (*store)(struct bus_type *, const char * buf, size_t count);
 };
 
-Bus drivers can export attributes using the BUS_ATTR macro that works
-similarly to the DEVICE_ATTR macro for devices. For example, a definition 
-like this:
+Bus drivers can export attributes using the BUS_ATTR_RW macro that works
+similarly to the DEVICE_ATTR_RW macro for devices. For example, a
+definition like this:
 
-static BUS_ATTR(debug,0644,show_debug,store_debug);
+static BUS_ATTR_RW(debug);
 
 is equivalent to declaring:
 
index 62af305..60a5ec0 100644 (file)
@@ -163,6 +163,14 @@ C. Boot options
        be preserved until there actually is some text is output to the console.
        This option causes fbcon to bind immediately to the fbdev device.
 
+7. fbcon=logo-pos:<location>
+
+       The only possible 'location' is 'center' (without quotes), and when
+       given, the bootup logo is moved from the default top-left corner
+       location to the center of the framebuffer. If more than one logo is
+       displayed due to multiple CPUs, the collected line of logos is moved
+       as a whole.
+
 C. Attaching, Detaching and Unloading
 
 Before going on to how to attach, detach and unload the framebuffer console, an
index 90459cd..8620c38 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: | TODO |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index c90a038..9ae6e8d 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 0ef6acd..365df2c 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: |  ok  |
     |       h8300: | TODO |
     |     hexagon: |  ok  |
     |        ia64: |  ok  |
index 6011139..7fc2e24 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index f44c274..d344b99 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: |  ok  |
+    |        csky: |  ok  |
     |       h8300: | TODO |
     |     hexagon: |  ok  |
     |        ia64: |  ok  |
index 282ecc8..304dcd4 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 01b2b30..059d58a 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 3b4dff2..3e6b8f0 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: |  ok  |
     |     hexagon: |  ok  |
     |        ia64: | TODO |
index 7e963d0..68f2669 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: | TODO |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 4ada027..f4e45bd 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: |  ok  |
index 044e13f..1d5651e 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: |  ok  |
index dce7669..fb297a8 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: | TODO |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 954ac1c..9999ea5 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 1a3f9d3..1c577d0 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 1d78d10..6bfa36b 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: | TODO |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 30c072d..eb28b5c 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: |  ok  |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 51704a2..242ff5a 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index bd39c5e..941fd5b 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: |  ok  |
     |        ia64: | TODO |
index da7aff3..c683da1 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: |  ok  |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 478e910..e3080b8 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: | TODO |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index e54b1f1..7521d75 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: |  ok  |
index 7331402..d8278bf 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: |  ok  |
     |        ia64: | TODO |
index 53feeee..687d049 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 1616434..90996e3 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index c7858dd..8a521a6 100644 (file)
@@ -34,6 +34,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index c68bb2c..3508236 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ..  |
     |       arm64: |  ok  |
     |         c6x: |  ..  |
+    |        csky: |  ..  |
     |       h8300: |  ..  |
     |     hexagon: |  ..  |
     |        ia64: | TODO |
index d4271b4..4fe6c3c 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 83d9e68..593536f 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 3d4908f..7a27157 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: |  ok  |
+    |        csky: |  ok  |
     |       h8300: |  ok  |
     |     hexagon: |  ok  |
     |        ia64: | TODO |
index c29974a..048bfb6 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 8d73c46..a14bbad 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: |  ..  |
index e7c6ea6..2855dfe 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: |  ok  |
     |         c6x: |  ok  |
+    |        csky: |  ok  |
     |       h8300: |  ok  |
     |     hexagon: |  ok  |
     |        ia64: |  ok  |
index 4646457..fb0d0ca 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: |  ok  |
index 1f71d09..adc2587 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index fbd5aa4..f05588f 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: | TODO |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: |  ok  |
index 5d7ecc3..cdfe892 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: |  ..  |
+    |        csky: |  ..  |
     |       h8300: |  ..  |
     |     hexagon: |  ..  |
     |        ia64: | TODO |
index f7af967..2bdd3b6 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: | TODO |
     |         c6x: |  ..  |
+    |        csky: | TODO |
     |       h8300: |  ..  |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index d0713cc..019131c 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 326e479..3a6b87d 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: | TODO |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 1a98805..3004beb 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ..  |
     |       arm64: |  ok  |
     |         c6x: |  ..  |
+    |        csky: |  ..  |
     |       h8300: |  ..  |
     |     hexagon: |  ..  |
     |        ia64: |  ok  |
index a837842..2dc5df6 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index a1426ca..41411b0 100644 (file)
@@ -344,7 +344,9 @@ struct bus_attribute {
 
 Declaring:
 
-BUS_ATTR(_name, _mode, _show, _store)
+static BUS_ATTR_RW(name);
+static BUS_ATTR_RO(name);
+static BUS_ATTR_WO(name);
 
 Creation/Removal:
 
index 6a47629..59e86de 100644 (file)
@@ -11,19 +11,19 @@ Contents:
    batman-adv
    can
    can_ucan_protocol
-   dpaa2/index
-   e100
-   e1000
-   e1000e
-   fm10k
-   igb
-   igbvf
-   ixgb
-   ixgbe
-   ixgbevf
-   i40e
-   iavf
-   ice
+   device_drivers/freescale/dpaa2/index
+   device_drivers/intel/e100
+   device_drivers/intel/e1000
+   device_drivers/intel/e1000e
+   device_drivers/intel/fm10k
+   device_drivers/intel/igb
+   device_drivers/intel/igbvf
+   device_drivers/intel/ixgb
+   device_drivers/intel/ixgbe
+   device_drivers/intel/ixgbevf
+   device_drivers/intel/i40e
+   device_drivers/intel/iavf
+   device_drivers/intel/ice
    kapi
    z8530book
    msg_zerocopy
index 355c6d8..b203d13 100644 (file)
@@ -22,8 +22,9 @@ and changeable from userspace under certain rules.
 2. Querying from userspace
 
 Both admin and operational state can be queried via the netlink
-operation RTM_GETLINK. It is also possible to subscribe to RTMGRP_LINK
-to be notified of updates. This is important for setting from userspace.
+operation RTM_GETLINK. It is also possible to subscribe to RTNLGRP_LINK
+to be notified of updates while the interface is admin up. This is
+important for setting from userspace.
 
 These values contain interface state:
 
@@ -101,8 +102,9 @@ because some driver controlled protocol establishment has to
 complete. Corresponding functions are netif_dormant_on() to set the
 flag, netif_dormant_off() to clear it and netif_dormant() to query.
 
-On device allocation, networking core sets the flags equivalent to
-netif_carrier_ok() and !netif_dormant().
+On device allocation, both flags __LINK_STATE_NOCARRIER and
+__LINK_STATE_DORMANT are cleared, so the effective state is equivalent
+to netif_carrier_ok() and !netif_dormant().
 
 
 Whenever the driver CHANGES one of these flags, a workqueue event is
@@ -133,11 +135,11 @@ netif_carrier_ok() && !netif_dormant() is set by the
 driver. Afterwards, the userspace application can set IFLA_OPERSTATE
 to IF_OPER_DORMANT or IF_OPER_UP as long as the driver does not set
 netif_carrier_off() or netif_dormant_on(). Changes made by userspace
-are multicasted on the netlink group RTMGRP_LINK.
+are multicasted on the netlink group RTNLGRP_LINK.
 
 So basically a 802.1X supplicant interacts with the kernel like this:
 
--subscribe to RTMGRP_LINK
+-subscribe to RTNLGRP_LINK
 -set IFLA_LINKMODE to 1 via RTM_SETLINK
 -query RTM_GETLINK once to get initial state
 -if initial flags are not (IFF_LOWER_UP && !IFF_DORMANT), wait until
index c9d052e..2df5894 100644 (file)
@@ -1000,51 +1000,6 @@ The kernel interface functions are as follows:
      size should be set when the call is begun.  tx_total_len may not be less
      than zero.
 
- (*) Check to see the completion state of a call so that the caller can assess
-     whether it needs to be retried.
-
-       enum rxrpc_call_completion {
-               RXRPC_CALL_SUCCEEDED,
-               RXRPC_CALL_REMOTELY_ABORTED,
-               RXRPC_CALL_LOCALLY_ABORTED,
-               RXRPC_CALL_LOCAL_ERROR,
-               RXRPC_CALL_NETWORK_ERROR,
-       };
-
-       int rxrpc_kernel_check_call(struct socket *sock, struct rxrpc_call *call,
-                                   enum rxrpc_call_completion *_compl,
-                                   u32 *_abort_code);
-
-     On return, -EINPROGRESS will be returned if the call is still ongoing; if
-     it is finished, *_compl will be set to indicate the manner of completion,
-     *_abort_code will be set to any abort code that occurred.  0 will be
-     returned on a successful completion, -ECONNABORTED will be returned if the
-     client failed due to a remote abort and anything else will return an
-     appropriate error code.
-
-     The caller should look at this information to decide if it's worth
-     retrying the call.
-
- (*) Retry a client call.
-
-       int rxrpc_kernel_retry_call(struct socket *sock,
-                                   struct rxrpc_call *call,
-                                   struct sockaddr_rxrpc *srx,
-                                   struct key *key);
-
-     This attempts to partially reinitialise a call and submit it again while
-     reusing the original call's Tx queue to avoid the need to repackage and
-     re-encrypt the data to be sent.  call indicates the call to retry, srx the
-     new address to send it to and key the encryption key to use for signing or
-     encrypting the packets.
-
-     For this to work, the first Tx data packet must still be in the transmit
-     queue, and currently this is only permitted for local and network errors
-     and the call must not have been aborted.  Any partially constructed Tx
-     packet is left as is and can continue being filled afterwards.
-
-     It returns 0 if the call was requeued and an error otherwise.
-
  (*) Get call RTT.
 
        u64 rxrpc_kernel_get_rtt(struct socket *sock, struct rxrpc_call *call);
index b0dfdaa..fe8f741 100644 (file)
@@ -336,7 +336,26 @@ time client replies ACK, this socket will get another chance to move
 to the accept queue.
 
 
-TCP Fast Open
+* TcpEstabResets
+Defined in `RFC1213 tcpEstabResets`_.
+
+.. _RFC1213 tcpEstabResets: https://tools.ietf.org/html/rfc1213#page-48
+
+* TcpAttemptFails
+Defined in `RFC1213 tcpAttemptFails`_.
+
+.. _RFC1213 tcpAttemptFails: https://tools.ietf.org/html/rfc1213#page-48
+
+* TcpOutRsts
+Defined in `RFC1213 tcpOutRsts`_. The RFC says this counter indicates
+the 'segments sent containing the RST flag', but in linux kernel, this
+couner indicates the segments kerenl tried to send. The sending
+process might be failed due to some errors (e.g. memory alloc failed).
+
+.. _RFC1213 tcpOutRsts: https://tools.ietf.org/html/rfc1213#page-52
+
+
+TCP Fast Path
 ============
 When kernel receives a TCP packet, it has two paths to handler the
 packet, one is fast path, another is slow path. The comment in kernel
@@ -383,8 +402,6 @@ increase 1.
 
 TCP abort
 ========
-
-
 * TcpExtTCPAbortOnData
 It means TCP layer has data in flight, but need to close the
 connection. So TCP layer sends a RST to the other side, indicate the
@@ -545,7 +562,6 @@ packet yet, the sender would know packet 4 is out of order. The TCP
 stack of kernel will increase TcpExtTCPSACKReorder for both of the
 above scenarios.
 
-
 DSACK
 =====
 The DSACK is defined in `RFC2883`_. The receiver uses DSACK to report
@@ -566,13 +582,63 @@ The TCP stack receives an out of order duplicate packet, so it sends a
 DSACK to the sender.
 
 * TcpExtTCPDSACKRecv
-The TCP stack receives a DSACK, which indicate an acknowledged
+The TCP stack receives a DSACK, which indicates an acknowledged
 duplicate packet is received.
 
 * TcpExtTCPDSACKOfoRecv
 The TCP stack receives a DSACK, which indicate an out of order
 duplicate packet is received.
 
+invalid SACK and DSACK
+====================
+When a SACK (or DSACK) block is invalid, a corresponding counter would
+be updated. The validation method is base on the start/end sequence
+number of the SACK block. For more details, please refer the comment
+of the function tcp_is_sackblock_valid in the kernel source code. A
+SACK option could have up to 4 blocks, they are checked
+individually. E.g., if 3 blocks of a SACk is invalid, the
+corresponding counter would be updated 3 times. The comment of the
+`Add counters for discarded SACK blocks`_ patch has additional
+explaination:
+
+.. _Add counters for discarded SACK blocks: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=18f02545a9a16c9a89778b91a162ad16d510bb32
+
+* TcpExtTCPSACKDiscard
+This counter indicates how many SACK blocks are invalid. If the invalid
+SACK block is caused by ACK recording, the TCP stack will only ignore
+it and won't update this counter.
+
+* TcpExtTCPDSACKIgnoredOld and TcpExtTCPDSACKIgnoredNoUndo
+When a DSACK block is invalid, one of these two counters would be
+updated. Which counter will be updated depends on the undo_marker flag
+of the TCP socket. If the undo_marker is not set, the TCP stack isn't
+likely to re-transmit any packets, and we still receive an invalid
+DSACK block, the reason might be that the packet is duplicated in the
+middle of the network. In such scenario, TcpExtTCPDSACKIgnoredNoUndo
+will be updated. If the undo_marker is set, TcpExtTCPDSACKIgnoredOld
+will be updated. As implied in its name, it might be an old packet.
+
+SACK shift
+=========
+The linux networking stack stores data in sk_buff struct (skb for
+short). If a SACK block acrosses multiple skb, the TCP stack will try
+to re-arrange data in these skb. E.g. if a SACK block acknowledges seq
+10 to 15, skb1 has seq 10 to 13, skb2 has seq 14 to 20. The seq 14 and
+15 in skb2 would be moved to skb1. This operation is 'shift'. If a
+SACK block acknowledges seq 10 to 20, skb1 has seq 10 to 13, skb2 has
+seq 14 to 20. All data in skb2 will be moved to skb1, and skb2 will be
+discard, this operation is 'merge'.
+
+* TcpExtTCPSackShifted
+A skb is shifted
+
+* TcpExtTCPSackMerged
+A skb is merged
+
+* TcpExtTCPSackShiftFallback
+A skb should be shifted or merged, but the TCP stack doesn't do it for
+some reasons.
+
 TCP out of order
 ===============
 * TcpExtTCPOFOQueue
@@ -662,6 +728,60 @@ unacknowledged number (more strict than `RFC 5961 section 5.2`_).
 .. _RFC 5961 section 4.2: https://tools.ietf.org/html/rfc5961#page-9
 .. _RFC 5961 section 5.2: https://tools.ietf.org/html/rfc5961#page-11
 
+TCP receive window
+=================
+* TcpExtTCPWantZeroWindowAdv
+Depending on current memory usage, the TCP stack tries to set receive
+window to zero. But the receive window might still be a no-zero
+value. For example, if the previous window size is 10, and the TCP
+stack receives 3 bytes, the current window size would be 7 even if the
+window size calculated by the memory usage is zero.
+
+* TcpExtTCPToZeroWindowAdv
+The TCP receive window is set to zero from a no-zero value.
+
+* TcpExtTCPFromZeroWindowAdv
+The TCP receive window is set to no-zero value from zero.
+
+
+Delayed ACK
+==========
+The TCP Delayed ACK is a technique which is used for reducing the
+packet count in the network. For more details, please refer the
+`Delayed ACK wiki`_
+
+.. _Delayed ACK wiki: https://en.wikipedia.org/wiki/TCP_delayed_acknowledgment
+
+* TcpExtDelayedACKs
+A delayed ACK timer expires. The TCP stack will send a pure ACK packet
+and exit the delayed ACK mode.
+
+* TcpExtDelayedACKLocked
+A delayed ACK timer expires, but the TCP stack can't send an ACK
+immediately due to the socket is locked by a userspace program. The
+TCP stack will send a pure ACK later (after the userspace program
+unlock the socket). When the TCP stack sends the pure ACK later, the
+TCP stack will also update TcpExtDelayedACKs and exit the delayed ACK
+mode.
+
+* TcpExtDelayedACKLost
+It will be updated when the TCP stack receives a packet which has been
+ACKed. A Delayed ACK loss might cause this issue, but it would also be
+triggered by other reasons, such as a packet is duplicated in the
+network.
+
+Tail Loss Probe (TLP)
+===================
+TLP is an algorithm which is used to detect TCP packet loss. For more
+details, please refer the `TLP paper`_.
+
+.. _TLP paper: https://tools.ietf.org/html/draft-dukkipati-tcpm-tcp-loss-probe-01
+
+* TcpExtTCPLossProbes
+A TLP probe packet is sent.
+
+* TcpExtTCPLossProbeRecovery
+A packet loss is detected and recovered by TLP.
 
 examples
 =======
index 1be0b6f..9d1432e 100644 (file)
@@ -417,7 +417,7 @@ is again deprecated and ts[2] holds a hardware timestamp if set.
 
 Hardware time stamping must also be initialized for each device driver
 that is expected to do hardware time stamping. The parameter is defined in
-/include/linux/net_tstamp.h as:
+include/uapi/linux/net_tstamp.h as:
 
 struct hwtstamp_config {
        int flags;      /* no flags defined right now, must be zero */
@@ -487,7 +487,7 @@ enum {
        HWTSTAMP_FILTER_PTP_V1_L4_EVENT,
 
        /* for the complete list of values, please check
-        * the include file /include/linux/net_tstamp.h
+        * the include file include/uapi/linux/net_tstamp.h
         */
 };
 
index 819caf8..ebc679b 100644 (file)
@@ -56,26 +56,34 @@ of any kernel data structures.
 
 dentry-state:
 
-From linux/fs/dentry.c:
+From linux/include/linux/dcache.h:
 --------------------------------------------------------------
-struct {
+struct dentry_stat_t dentry_stat {
         int nr_dentry;
         int nr_unused;
         int age_limit;         /* age in seconds */
         int want_pages;        /* pages requested by system */
-        int dummy[2];
-} dentry_stat = {0, 0, 45, 0,};
--------------------------------------------------------------- 
-
-Dentries are dynamically allocated and deallocated, and
-nr_dentry seems to be 0 all the time. Hence it's safe to
-assume that only nr_unused, age_limit and want_pages are
-used. Nr_unused seems to be exactly what its name says.
+        int nr_negative;       /* # of unused negative dentries */
+        int dummy;             /* Reserved for future use */
+};
+--------------------------------------------------------------
+
+Dentries are dynamically allocated and deallocated.
+
+nr_dentry shows the total number of dentries allocated (active
++ unused). nr_unused shows the number of dentries that are not
+actively used, but are saved in the LRU list for future reuse.
+
 Age_limit is the age in seconds after which dcache entries
 can be reclaimed when memory is short and want_pages is
 nonzero when shrink_dcache_pages() has been called and the
 dcache isn't pruned yet.
 
+nr_negative shows the number of unused dentries that are also
+negative dentries which do not map to any files. Instead,
+they help speeding up rejection of non-existing files provided
+by the users.
+
 ==============================================================
 
 dquot-max & dquot-nr:
index 89ab09e..f07e380 100644 (file)
@@ -165,7 +165,7 @@ Do some work...
 The same can also be done from an application program.
 
 Disable specific CPU's specific idle state from cpuidle sysfs (see
-Documentation/cpuidle/sysfs.txt):
+Documentation/admin-guide/pm/cpuidle.rst):
 # echo 1 > /sys/devices/system/cpu/cpu$cpu/cpuidle/state$state/disable
 
 
index 71d6d25..659bbc0 100644 (file)
@@ -242,6 +242,6 @@ References
 ==========
 
 .. [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%20API_Specification.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
index d9aed83..c1f95b5 100644 (file)
@@ -9,7 +9,7 @@ Fenghua Yu <fenghua.yu@intel.com>
 Tony Luck <tony.luck@intel.com>
 Vikas Shivappa <vikas.shivappa@intel.com>
 
-This feature is enabled by the CONFIG_RESCTRL and the X86 /proc/cpuinfo
+This feature is enabled by the CONFIG_X86_CPU_RESCTRL and the x86 /proc/cpuinfo
 flag bits:
 RDT (Resource Director Technology) Allocation - "rdt_a"
 CAT (Cache Allocation Technology) - "cat_l3", "cat_l2"
index 32d4444..41ce5f4 100644 (file)
@@ -2848,6 +2848,9 @@ F:        include/uapi/linux/if_bonding.h
 BPF (Safe dynamic programs and tools)
 M:     Alexei Starovoitov <ast@kernel.org>
 M:     Daniel Borkmann <daniel@iogearbox.net>
+R:     Martin KaFai Lau <kafai@fb.com>
+R:     Song Liu <songliubraving@fb.com>
+R:     Yonghong Song <yhs@fb.com>
 L:     netdev@vger.kernel.org
 L:     linux-kernel@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git
@@ -2873,6 +2876,8 @@ F:        samples/bpf/
 F:     tools/bpf/
 F:     tools/lib/bpf/
 F:     tools/testing/selftests/bpf/
+K:     bpf
+N:     bpf
 
 BPF JIT for ARM
 M:     Shubham Bansal <illusionist.neo@gmail.com>
@@ -3052,8 +3057,8 @@ F:        include/linux/bcm963xx_nvram.h
 F:     include/linux/bcm963xx_tag.h
 
 BROADCOM BNX2 GIGABIT ETHERNET DRIVER
-M:     Rasesh Mody <rasesh.mody@cavium.com>
-M:     Dept-GELinuxNICDev@cavium.com
+M:     Rasesh Mody <rmody@marvell.com>
+M:     GR-Linux-NIC-Dev@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/broadcom/bnx2.*
@@ -3072,9 +3077,9 @@ S:        Supported
 F:     drivers/scsi/bnx2i/
 
 BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER
-M:     Ariel Elior <ariel.elior@cavium.com>
-M:     Sudarsana Kalluru <sudarsana.kalluru@cavium.com>
-M:     everest-linux-l2@cavium.com
+M:     Ariel Elior <aelior@marvell.com>
+M:     Sudarsana Kalluru <skalluru@marvell.com>
+M:     GR-everest-linux-l2@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/broadcom/bnx2x/
@@ -3249,9 +3254,9 @@ S:        Supported
 F:     drivers/scsi/bfa/
 
 BROCADE BNA 10 GIGABIT ETHERNET DRIVER
-M:     Rasesh Mody <rasesh.mody@cavium.com>
-M:     Sudarsana Kalluru <sudarsana.kalluru@cavium.com>
-M:     Dept-GELinuxNICDev@cavium.com
+M:     Rasesh Mody <rmody@marvell.com>
+M:     Sudarsana Kalluru <skalluru@marvell.com>
+M:     GR-Linux-NIC-Dev@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/brocade/bna/
@@ -3471,10 +3476,9 @@ F:       drivers/i2c/busses/i2c-octeon*
 F:     drivers/i2c/busses/i2c-thunderx*
 
 CAVIUM LIQUIDIO NETWORK DRIVER
-M:     Derek Chickles <derek.chickles@caviumnetworks.com>
-M:     Satanand Burla <satananda.burla@caviumnetworks.com>
-M:     Felix Manlunas <felix.manlunas@caviumnetworks.com>
-M:     Raghu Vatsavayi <raghu.vatsavayi@caviumnetworks.com>
+M:     Derek Chickles <dchickles@marvell.com>
+M:     Satanand Burla <sburla@marvell.com>
+M:     Felix Manlunas <fmanlunas@marvell.com>
 L:     netdev@vger.kernel.org
 W:     http://www.cavium.com
 S:     Supported
@@ -3951,7 +3955,7 @@ L:        netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/ti/cpmac.c
 
-CPU FREQUENCY DRIVERS
+CPU FREQUENCY SCALING FRAMEWORK
 M:     "Rafael J. Wysocki" <rjw@rjwysocki.net>
 M:     Viresh Kumar <viresh.kumar@linaro.org>
 L:     linux-pm@vger.kernel.org
@@ -3959,6 +3963,8 @@ S:        Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
 T:     git git://git.linaro.org/people/vireshk/linux.git (For ARM Updates)
 B:     https://bugzilla.kernel.org
+F:     Documentation/admin-guide/pm/cpufreq.rst
+F:     Documentation/admin-guide/pm/intel_pstate.rst
 F:     Documentation/cpu-freq/
 F:     Documentation/devicetree/bindings/cpufreq/
 F:     drivers/cpufreq/
@@ -3977,6 +3983,7 @@ F:        drivers/cpufreq/arm_big_little.c
 CPU POWER MONITORING SUBSYSTEM
 M:     Thomas Renninger <trenn@suse.com>
 M:     Shuah Khan <shuah@kernel.org>
+M:     Shuah Khan <skhan@linuxfoundation.org>
 L:     linux-pm@vger.kernel.org
 S:     Maintained
 F:     tools/power/cpupower/
@@ -4006,13 +4013,14 @@ S:      Supported
 F:     drivers/cpuidle/cpuidle-exynos.c
 F:     arch/arm/mach-exynos/pm.c
 
-CPUIDLE DRIVERS
+CPU IDLE TIME MANAGEMENT FRAMEWORK
 M:     "Rafael J. Wysocki" <rjw@rjwysocki.net>
 M:     Daniel Lezcano <daniel.lezcano@linaro.org>
 L:     linux-pm@vger.kernel.org
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
 B:     https://bugzilla.kernel.org
+F:     Documentation/admin-guide/pm/cpuidle.rst
 F:     drivers/cpuidle/*
 F:     include/linux/cpuidle.h
 
@@ -5178,7 +5186,7 @@ DRM DRIVERS FOR XEN
 M:     Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
 T:     git git://anongit.freedesktop.org/drm/drm-misc
 L:     dri-devel@lists.freedesktop.org
-L:     xen-devel@lists.xen.org
+L:     xen-devel@lists.xenproject.org (moderated for non-subscribers)
 S:     Supported
 F:     drivers/gpu/drm/xen/
 F:     Documentation/gpu/xen-front.rst
@@ -6143,7 +6151,7 @@ FREESCALE SOC SOUND DRIVERS
 M:     Timur Tabi <timur@kernel.org>
 M:     Nicolin Chen <nicoleotsuka@gmail.com>
 M:     Xiubo Li <Xiubo.Lee@gmail.com>
-R:     Fabio Estevam <fabio.estevam@nxp.com>
+R:     Fabio Estevam <festevam@gmail.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 L:     linuxppc-dev@lists.ozlabs.org
 S:     Maintained
@@ -8256,6 +8264,7 @@ F:        include/uapi/linux/sunrpc/
 
 KERNEL SELFTEST FRAMEWORK
 M:     Shuah Khan <shuah@kernel.org>
+M:     Shuah Khan <skhan@linuxfoundation.org>
 L:     linux-kselftest@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git
 Q:     https://patchwork.kernel.org/project/linux-kselftest/list/
@@ -10686,9 +10695,9 @@ S:      Maintained
 F:     drivers/net/netdevsim/*
 
 NETXEN (1/10) GbE SUPPORT
-M:     Manish Chopra <manish.chopra@cavium.com>
-M:     Rahul Verma <rahul.verma@cavium.com>
-M:     Dept-GELinuxNICDev@cavium.com
+M:     Manish Chopra <manishc@marvell.com>
+M:     Rahul Verma <rahulv@marvell.com>
+M:     GR-Linux-NIC-Dev@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/qlogic/netxen/
@@ -10889,7 +10898,7 @@ F:      include/linux/nvmem-consumer.h
 F:     include/linux/nvmem-provider.h
 
 NXP SGTL5000 DRIVER
-M:     Fabio Estevam <fabio.estevam@nxp.com>
+M:     Fabio Estevam <festevam@gmail.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Maintained
 F:     Documentation/devicetree/bindings/sound/sgtl5000.txt
@@ -11303,10 +11312,12 @@ F:    include/dt-bindings/
 
 OPENCORES I2C BUS DRIVER
 M:     Peter Korsgaard <peter@korsgaard.com>
+M:     Andrew Lunn <andrew@lunn.ch>
 L:     linux-i2c@vger.kernel.org
 S:     Maintained
 F:     Documentation/i2c/busses/i2c-ocores
 F:     drivers/i2c/busses/i2c-ocores.c
+F:     include/linux/platform_data/i2c-ocores.h
 
 OPENRISC ARCHITECTURE
 M:     Jonas Bonn <jonas@southpole.se>
@@ -12472,8 +12483,8 @@ S:      Supported
 F:     drivers/scsi/qedi/
 
 QLOGIC QL4xxx ETHERNET DRIVER
-M:     Ariel Elior <Ariel.Elior@cavium.com>
-M:     everest-linux-l2@cavium.com
+M:     Ariel Elior <aelior@marvell.com>
+M:     GR-everest-linux-l2@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/qlogic/qed/
@@ -12481,8 +12492,8 @@ F:      include/linux/qed/
 F:     drivers/net/ethernet/qlogic/qede/
 
 QLOGIC QL4xxx RDMA DRIVER
-M:     Michal Kalderon <Michal.Kalderon@cavium.com>
-M:     Ariel Elior <Ariel.Elior@cavium.com>
+M:     Michal Kalderon <mkalderon@marvell.com>
+M:     Ariel Elior <aelior@marvell.com>
 L:     linux-rdma@vger.kernel.org
 S:     Supported
 F:     drivers/infiniband/hw/qedr/
@@ -12502,7 +12513,7 @@ F:      Documentation/scsi/LICENSE.qla2xxx
 F:     drivers/scsi/qla2xxx/
 
 QLOGIC QLA3XXX NETWORK DRIVER
-M:     Dept-GELinuxNICDev@cavium.com
+M:     GR-Linux-NIC-Dev@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     Documentation/networking/device_drivers/qlogic/LICENSE.qla3xxx
@@ -12516,16 +12527,16 @@ F:    Documentation/scsi/LICENSE.qla4xxx
 F:     drivers/scsi/qla4xxx/
 
 QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER
-M:     Shahed Shaikh <Shahed.Shaikh@cavium.com>
-M:     Manish Chopra <manish.chopra@cavium.com>
-M:     Dept-GELinuxNICDev@cavium.com
+M:     Shahed Shaikh <shshaikh@marvell.com>
+M:     Manish Chopra <manishc@marvell.com>
+M:     GR-Linux-NIC-Dev@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/qlogic/qlcnic/
 
 QLOGIC QLGE 10Gb ETHERNET DRIVER
-M:     Manish Chopra <manish.chopra@cavium.com>
-M:     Dept-GELinuxNICDev@cavium.com
+M:     Manish Chopra <manishc@marvell.com>
+M:     GR-Linux-NIC-Dev@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/qlogic/qlge/
@@ -12864,6 +12875,13 @@ F:     Documentation/devicetree/bindings/net/dsa/realtek-smi.txt
 F:     drivers/net/dsa/realtek-smi*
 F:     drivers/net/dsa/rtl83*
 
+REDPINE WIRELESS DRIVER
+M:     Amitkumar Karwar <amitkarwar@gmail.com>
+M:     Siva Rebbagondla <siva8118@gmail.com>
+L:     linux-wireless@vger.kernel.org
+S:     Maintained
+F:     drivers/net/wireless/rsi/
+
 REGISTER MAP ABSTRACTION
 M:     Mark Brown <broonie@kernel.org>
 L:     linux-kernel@vger.kernel.org
@@ -13692,6 +13710,15 @@ L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/sfc/
 
+SFF/SFP/SFP+ MODULE SUPPORT
+M:     Russell King <linux@armlinux.org.uk>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/net/phy/phylink.c
+F:     drivers/net/phy/sfp*
+F:     include/linux/phylink.h
+F:     include/linux/sfp.h
+
 SGI GRU DRIVER
 M:     Dimitri Sivanich <sivanich@sgi.com>
 S:     Maintained
@@ -13820,8 +13847,9 @@ F:      drivers/media/mmc/siano/
 
 SIFIVE DRIVERS
 M:     Palmer Dabbelt <palmer@sifive.com>
+M:     Paul Walmsley <paul.walmsley@sifive.com>
 L:     linux-riscv@lists.infradead.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/palmer/riscv-linux.git
+T:     git git://github.com/sifive/riscv-linux.git
 S:     Supported
 K:     sifive
 N:     sifive
@@ -14432,6 +14460,11 @@ M:     Florian Schilhabel <florian.c.schilhabel@googlemail.com>.
 S:     Odd Fixes
 F:     drivers/staging/rtl8712/
 
+STAGING - REALTEK RTL8188EU DRIVERS
+M:     Larry Finger <Larry.Finger@lwfinger.net>
+S:     Odd Fixes
+F:     drivers/staging/rtl8188eu/
+
 STAGING - SILICON MOTION SM750 FRAME BUFFER DRIVER
 M:     Sudip Mukherjee <sudipm.mukherjee@gmail.com>
 M:     Teddy Wang <teddy.wang@siliconmotion.com>
@@ -15802,7 +15835,6 @@ M:      Alan Stern <stern@rowland.harvard.edu>
 L:     linux-usb@vger.kernel.org
 L:     usb-storage@lists.one-eyed-alien.net
 S:     Maintained
-W:     http://www.one-eyed-alien.net/~mdharm/linux-usb/
 F:     drivers/usb/storage/
 
 USB MIDI DRIVER
@@ -15834,6 +15866,7 @@ F:      drivers/usb/common/usb-otg-fsm.c
 USB OVER IP DRIVER
 M:     Valentina Manea <valentina.manea.m@gmail.com>
 M:     Shuah Khan <shuah@kernel.org>
+M:     Shuah Khan <skhan@linuxfoundation.org>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     Documentation/usb/usbip_protocol.txt
@@ -16631,6 +16664,15 @@ S:     Maintained
 F:     drivers/platform/x86/
 F:     drivers/platform/olpc/
 
+X86 PLATFORM DRIVERS - ARCH
+R:     Darren Hart <dvhart@infradead.org>
+R:     Andy Shevchenko <andy@infradead.org>
+L:     platform-driver-x86@vger.kernel.org
+L:     x86@kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/core
+S:     Maintained
+F:     arch/x86/platform
+
 X86 VDSO
 M:     Andy Lutomirski <luto@kernel.org>
 L:     linux-kernel@vger.kernel.org
@@ -16663,6 +16705,24 @@ T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     drivers/media/tuners/tuner-xc2028.*
 
+XDP (eXpress Data Path)
+M:     Alexei Starovoitov <ast@kernel.org>
+M:     Daniel Borkmann <daniel@iogearbox.net>
+M:     David S. Miller <davem@davemloft.net>
+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
+S:     Supported
+F:     net/core/xdp.c
+F:     include/net/xdp.h
+F:     kernel/bpf/devmap.c
+F:     kernel/bpf/cpumap.c
+F:     include/trace/events/xdp.h
+K:     xdp
+N:     xdp
+
 XDP SOCKETS (AF_XDP)
 M:     Björn Töpel <bjorn.topel@intel.com>
 M:     Magnus Karlsson <magnus.karlsson@intel.com>
index 8c55b64..96c5335 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 0
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc7
 NAME = Shy Crocodile
 
 # *DOCUMENTATION*
@@ -955,6 +955,7 @@ ifdef CONFIG_STACK_VALIDATION
   endif
 endif
 
+PHONY += prepare0
 
 ifeq ($(KBUILD_EXTMOD),)
 core-y         += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
@@ -1061,8 +1062,7 @@ scripts: scripts_basic scripts_dtc
 # archprepare is used in arch Makefiles and when processed asm symlink,
 # version.h and scripts_basic is processed / created.
 
-# Listed in dependency order
-PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3
+PHONY += prepare archprepare prepare1 prepare2 prepare3
 
 # prepare3 is used to check if we are building in a separate output directory,
 # and if so do:
@@ -1360,11 +1360,11 @@ mrproper: rm-dirs  := $(wildcard $(MRPROPER_DIRS))
 mrproper: rm-files := $(wildcard $(MRPROPER_FILES))
 mrproper-dirs      := $(addprefix _mrproper_,scripts)
 
-PHONY += $(mrproper-dirs) mrproper archmrproper
+PHONY += $(mrproper-dirs) mrproper
 $(mrproper-dirs):
        $(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@)
 
-mrproper: clean archmrproper $(mrproper-dirs)
+mrproper: clean $(mrproper-dirs)
        $(call cmd,rmdirs)
        $(call cmd,rmfiles)
 
index 4d17cac..432402c 100644 (file)
 
 #elif defined(CONFIG_ALPHA_DP264) || \
       defined(CONFIG_ALPHA_LYNX)  || \
-      defined(CONFIG_ALPHA_SHARK) || \
-      defined(CONFIG_ALPHA_EIGER)
+      defined(CONFIG_ALPHA_SHARK)
 # define NR_IRQS       64
 
 #elif defined(CONFIG_ALPHA_TITAN)
 #define NR_IRQS                80
 
 #elif defined(CONFIG_ALPHA_RAWHIDE) || \
-       defined(CONFIG_ALPHA_TAKARA)
+      defined(CONFIG_ALPHA_TAKARA) || \
+      defined(CONFIG_ALPHA_EIGER)
 # define NR_IRQS       128
 
 #elif defined(CONFIG_ALPHA_WILDFIRE)
index d73dc47..188fc92 100644 (file)
@@ -78,7 +78,7 @@ __load_new_mm_context(struct mm_struct *next_mm)
 /* Macro for exception fixup code to access integer registers.  */
 #define dpf_reg(r)                                                     \
        (((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-16 :  \
-                                (r) <= 18 ? (r)+8 : (r)-10])
+                                (r) <= 18 ? (r)+10 : (r)-10])
 
 asmlinkage void
 do_page_fault(unsigned long address, unsigned long mmcsr,
index feed50c..caa2702 100644 (file)
@@ -3,23 +3,19 @@ generic-y += bugs.h
 generic-y += compat.h
 generic-y += device.h
 generic-y += div64.h
-generic-y += dma-mapping.h
 generic-y += emergency-restart.h
 generic-y += extable.h
-generic-y += fb.h
 generic-y += ftrace.h
 generic-y += hardirq.h
 generic-y += hw_irq.h
 generic-y += irq_regs.h
 generic-y += irq_work.h
-generic-y += kmap_types.h
 generic-y += local.h
 generic-y += local64.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += msi.h
 generic-y += parport.h
-generic-y += pci.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += topology.h
index 49bfbd8..f1b86ce 100644 (file)
@@ -216,6 +216,14 @@ struct bcr_fp_arcv2 {
 #endif
 };
 
+struct bcr_actionpoint {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int pad:21, min:1, num:2, ver:8;
+#else
+       unsigned int ver:8, num:2, min:1, pad:21;
+#endif
+};
+
 #include <soc/arc/timers.h>
 
 struct bcr_bpu_arcompact {
@@ -283,7 +291,7 @@ struct cpuinfo_arc_cache {
 };
 
 struct cpuinfo_arc_bpu {
-       unsigned int ver, full, num_cache, num_pred;
+       unsigned int ver, full, num_cache, num_pred, ret_stk;
 };
 
 struct cpuinfo_arc_ccm {
@@ -302,7 +310,7 @@ struct cpuinfo_arc {
        struct {
                unsigned int swap:1, norm:1, minmax:1, barrel:1, crc:1, swape:1, pad1:2,
                             fpu_sp:1, fpu_dp:1, dual:1, dual_enb:1, pad2:4,
-                            debug:1, ap:1, smart:1, rtt:1, pad3:4,
+                            ap_num:4, ap_full:1, smart:1, rtt:1, pad3:1,
                             timer0:1, timer1:1, rtc:1, gfrc:1, pad4:4;
        } extn;
        struct bcr_mpy extn_mpy;
index ee92461..202b74c 100644 (file)
@@ -340,7 +340,7 @@ static inline __attribute__ ((const)) int __fls(unsigned long x)
 /*
  * __ffs: Similar to ffs, but zero based (0-31)
  */
-static inline __attribute__ ((const)) int __ffs(unsigned long word)
+static inline __attribute__ ((const)) unsigned long __ffs(unsigned long word)
 {
        if (!word)
                return word;
@@ -400,9 +400,9 @@ static inline __attribute__ ((const)) int ffs(unsigned long x)
 /*
  * __ffs: Similar to ffs, but zero based (0-31)
  */
-static inline __attribute__ ((const)) int __ffs(unsigned long x)
+static inline __attribute__ ((const)) unsigned long __ffs(unsigned long x)
 {
-       int n;
+       unsigned long n;
 
        asm volatile(
        "       ffs.f   %0, %1          \n"  /* 0:31; 31(Z) if src 0 */
index 9185541..6958545 100644 (file)
@@ -103,7 +103,8 @@ static const char * const arc_pmu_ev_hw_map[] = {
 
        /* counts condition */
        [PERF_COUNT_HW_INSTRUCTIONS] = "iall",
-       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = "ijmp", /* Excludes ZOL jumps */
+       /* All jump instructions that are taken */
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = "ijmptak",
        [PERF_COUNT_ARC_BPOK]         = "bpok",   /* NP-NT, PT-T, PNT-NT */
 #ifdef CONFIG_ISA_ARCV2
        [PERF_COUNT_HW_BRANCH_MISSES] = "bpmp",
index 8aec462..861a8ae 100644 (file)
@@ -1,15 +1,10 @@
-/*
- * Linux performance counter support for ARC700 series
- *
- * Copyright (C) 2013-2015 Synopsys, Inc. (www.synopsys.com)
- *
- * This code is inspired by the perf support of various other architectures.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Linux performance counter support for ARC CPUs.
+// This code is inspired by the perf support of various other architectures.
+//
+// Copyright (C) 2013-2018 Synopsys, Inc. (www.synopsys.com)
+
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <asm/arcregs.h>
 #include <asm/stacktrace.h>
 
+/* HW holds 8 symbols + one for null terminator */
+#define ARCPMU_EVENT_NAME_LEN  9
+
+enum arc_pmu_attr_groups {
+       ARCPMU_ATTR_GR_EVENTS,
+       ARCPMU_ATTR_GR_FORMATS,
+       ARCPMU_NR_ATTR_GR
+};
+
+struct arc_pmu_raw_event_entry {
+       char name[ARCPMU_EVENT_NAME_LEN];
+};
+
 struct arc_pmu {
        struct pmu      pmu;
        unsigned int    irq;
        int             n_counters;
+       int             n_events;
        u64             max_period;
        int             ev_hw_idx[PERF_COUNT_ARC_HW_MAX];
+
+       struct arc_pmu_raw_event_entry  *raw_entry;
+       struct attribute                **attrs;
+       struct perf_pmu_events_attr     *attr;
+       const struct attribute_group    *attr_groups[ARCPMU_NR_ATTR_GR + 1];
 };
 
 struct arc_pmu_cpu {
@@ -49,6 +63,7 @@ static int callchain_trace(unsigned int addr, void *data)
 {
        struct arc_callchain_trace *ctrl = data;
        struct perf_callchain_entry_ctx *entry = ctrl->perf_stuff;
+
        perf_callchain_store(entry, addr);
 
        if (ctrl->depth++ < 3)
@@ -57,8 +72,8 @@ static int callchain_trace(unsigned int addr, void *data)
        return -1;
 }
 
-void
-perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
+void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
+                          struct pt_regs *regs)
 {
        struct arc_callchain_trace ctrl = {
                .depth = 0,
@@ -68,8 +83,8 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re
        arc_unwind_core(NULL, regs, callchain_trace, &ctrl);
 }
 
-void
-perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
+void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
+                        struct pt_regs *regs)
 {
        /*
         * User stack can't be unwound trivially with kernel dwarf unwinder
@@ -82,10 +97,10 @@ static struct arc_pmu *arc_pmu;
 static DEFINE_PER_CPU(struct arc_pmu_cpu, arc_pmu_cpu);
 
 /* read counter #idx; note that counter# != event# on ARC! */
-static uint64_t arc_pmu_read_counter(int idx)
+static u64 arc_pmu_read_counter(int idx)
 {
-       uint32_t tmp;
-       uint64_t result;
+       u32 tmp;
+       u64 result;
 
        /*
         * ARC supports making 'snapshots' of the counters, so we don't
@@ -94,7 +109,7 @@ static uint64_t arc_pmu_read_counter(int idx)
        write_aux_reg(ARC_REG_PCT_INDEX, idx);
        tmp = read_aux_reg(ARC_REG_PCT_CONTROL);
        write_aux_reg(ARC_REG_PCT_CONTROL, tmp | ARC_REG_PCT_CONTROL_SN);
-       result = (uint64_t) (read_aux_reg(ARC_REG_PCT_SNAPH)) << 32;
+       result = (u64) (read_aux_reg(ARC_REG_PCT_SNAPH)) << 32;
        result |= read_aux_reg(ARC_REG_PCT_SNAPL);
 
        return result;
@@ -103,9 +118,9 @@ static uint64_t arc_pmu_read_counter(int idx)
 static void arc_perf_event_update(struct perf_event *event,
                                  struct hw_perf_event *hwc, int idx)
 {
-       uint64_t prev_raw_count = local64_read(&hwc->prev_count);
-       uint64_t new_raw_count = arc_pmu_read_counter(idx);
-       int64_t delta = new_raw_count - prev_raw_count;
+       u64 prev_raw_count = local64_read(&hwc->prev_count);
+       u64 new_raw_count = arc_pmu_read_counter(idx);
+       s64 delta = new_raw_count - prev_raw_count;
 
        /*
         * We aren't afraid of hwc->prev_count changing beneath our feet
@@ -155,7 +170,7 @@ static int arc_pmu_event_init(struct perf_event *event)
        int ret;
 
        if (!is_sampling_event(event)) {
-               hwc->sample_period  = arc_pmu->max_period;
+               hwc->sample_period = arc_pmu->max_period;
                hwc->last_period = hwc->sample_period;
                local64_set(&hwc->period_left, hwc->sample_period);
        }
@@ -192,6 +207,18 @@ static int arc_pmu_event_init(struct perf_event *event)
                pr_debug("init cache event with h/w %08x \'%s\'\n",
                         (int)hwc->config, arc_pmu_ev_hw_map[ret]);
                return 0;
+
+       case PERF_TYPE_RAW:
+               if (event->attr.config >= arc_pmu->n_events)
+                       return -ENOENT;
+
+               hwc->config |= event->attr.config;
+               pr_debug("init raw event with idx %lld \'%s\'\n",
+                        event->attr.config,
+                        arc_pmu->raw_entry[event->attr.config].name);
+
+               return 0;
+
        default:
                return -ENOENT;
        }
@@ -200,7 +227,7 @@ static int arc_pmu_event_init(struct perf_event *event)
 /* starts all counters */
 static void arc_pmu_enable(struct pmu *pmu)
 {
-       uint32_t tmp;
+       u32 tmp;
        tmp = read_aux_reg(ARC_REG_PCT_CONTROL);
        write_aux_reg(ARC_REG_PCT_CONTROL, (tmp & 0xffff0000) | 0x1);
 }
@@ -208,7 +235,7 @@ static void arc_pmu_enable(struct pmu *pmu)
 /* stops all counters */
 static void arc_pmu_disable(struct pmu *pmu)
 {
-       uint32_t tmp;
+       u32 tmp;
        tmp = read_aux_reg(ARC_REG_PCT_CONTROL);
        write_aux_reg(ARC_REG_PCT_CONTROL, (tmp & 0xffff0000) | 0x0);
 }
@@ -228,7 +255,7 @@ static int arc_pmu_event_set_period(struct perf_event *event)
                local64_set(&hwc->period_left, left);
                hwc->last_period = period;
                overflow = 1;
-       } else  if (unlikely(left <= 0)) {
+       } else if (unlikely(left <= 0)) {
                /* left underflowed by less than period. */
                left += period;
                local64_set(&hwc->period_left, left);
@@ -246,8 +273,8 @@ static int arc_pmu_event_set_period(struct perf_event *event)
        write_aux_reg(ARC_REG_PCT_INDEX, idx);
 
        /* Write value */
-       write_aux_reg(ARC_REG_PCT_COUNTL, (u32)value);
-       write_aux_reg(ARC_REG_PCT_COUNTH, (value >> 32));
+       write_aux_reg(ARC_REG_PCT_COUNTL, lower_32_bits(value));
+       write_aux_reg(ARC_REG_PCT_COUNTH, upper_32_bits(value));
 
        perf_event_update_userpage(event);
 
@@ -277,7 +304,7 @@ static void arc_pmu_start(struct perf_event *event, int flags)
        /* Enable interrupt for this counter */
        if (is_sampling_event(event))
                write_aux_reg(ARC_REG_PCT_INT_CTRL,
-                             read_aux_reg(ARC_REG_PCT_INT_CTRL) | (1 << idx));
+                             read_aux_reg(ARC_REG_PCT_INT_CTRL) | BIT(idx));
 
        /* enable ARC pmu here */
        write_aux_reg(ARC_REG_PCT_INDEX, idx);          /* counter # */
@@ -295,9 +322,9 @@ static void arc_pmu_stop(struct perf_event *event, int flags)
                 * Reset interrupt flag by writing of 1. This is required
                 * to make sure pending interrupt was not left.
                 */
-               write_aux_reg(ARC_REG_PCT_INT_ACT, 1 << idx);
+               write_aux_reg(ARC_REG_PCT_INT_ACT, BIT(idx));
                write_aux_reg(ARC_REG_PCT_INT_CTRL,
-                             read_aux_reg(ARC_REG_PCT_INT_CTRL) & ~(1 << idx));
+                             read_aux_reg(ARC_REG_PCT_INT_CTRL) & ~BIT(idx));
        }
 
        if (!(event->hw.state & PERF_HES_STOPPED)) {
@@ -349,9 +376,10 @@ static int arc_pmu_add(struct perf_event *event, int flags)
 
        if (is_sampling_event(event)) {
                /* Mimic full counter overflow as other arches do */
-               write_aux_reg(ARC_REG_PCT_INT_CNTL, (u32)arc_pmu->max_period);
+               write_aux_reg(ARC_REG_PCT_INT_CNTL,
+                             lower_32_bits(arc_pmu->max_period));
                write_aux_reg(ARC_REG_PCT_INT_CNTH,
-                             (arc_pmu->max_period >> 32));
+                             upper_32_bits(arc_pmu->max_period));
        }
 
        write_aux_reg(ARC_REG_PCT_CONFIG, 0);
@@ -392,7 +420,7 @@ static irqreturn_t arc_pmu_intr(int irq, void *dev)
                idx = __ffs(active_ints);
 
                /* Reset interrupt flag by writing of 1 */
-               write_aux_reg(ARC_REG_PCT_INT_ACT, 1 << idx);
+               write_aux_reg(ARC_REG_PCT_INT_ACT, BIT(idx));
 
                /*
                 * On reset of "interrupt active" bit corresponding
@@ -400,7 +428,7 @@ static irqreturn_t arc_pmu_intr(int irq, void *dev)
                 * Now we need to re-enable interrupt for the counter.
                 */
                write_aux_reg(ARC_REG_PCT_INT_CTRL,
-                       read_aux_reg(ARC_REG_PCT_INT_CTRL) | (1 << idx));
+                       read_aux_reg(ARC_REG_PCT_INT_CTRL) | BIT(idx));
 
                event = pmu_cpu->act_counter[idx];
                hwc = &event->hw;
@@ -414,7 +442,7 @@ static irqreturn_t arc_pmu_intr(int irq, void *dev)
                                arc_pmu_stop(event, 0);
                }
 
-               active_ints &= ~(1U << idx);
+               active_ints &= ~BIT(idx);
        } while (active_ints);
 
 done:
@@ -441,19 +469,108 @@ static void arc_cpu_pmu_irq_init(void *data)
        write_aux_reg(ARC_REG_PCT_INT_ACT, 0xffffffff);
 }
 
+/* Event field occupies the bottom 15 bits of our config field */
+PMU_FORMAT_ATTR(event, "config:0-14");
+static struct attribute *arc_pmu_format_attrs[] = {
+       &format_attr_event.attr,
+       NULL,
+};
+
+static struct attribute_group arc_pmu_format_attr_gr = {
+       .name = "format",
+       .attrs = arc_pmu_format_attrs,
+};
+
+static ssize_t arc_pmu_events_sysfs_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *page)
+{
+       struct perf_pmu_events_attr *pmu_attr;
+
+       pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
+       return sprintf(page, "event=0x%04llx\n", pmu_attr->id);
+}
+
+/*
+ * We don't add attrs here as we don't have pre-defined list of perf events.
+ * We will generate and add attrs dynamically in probe() after we read HW
+ * configuration.
+ */
+static struct attribute_group arc_pmu_events_attr_gr = {
+       .name = "events",
+};
+
+static void arc_pmu_add_raw_event_attr(int j, char *str)
+{
+       memmove(arc_pmu->raw_entry[j].name, str, ARCPMU_EVENT_NAME_LEN - 1);
+       arc_pmu->attr[j].attr.attr.name = arc_pmu->raw_entry[j].name;
+       arc_pmu->attr[j].attr.attr.mode = VERIFY_OCTAL_PERMISSIONS(0444);
+       arc_pmu->attr[j].attr.show = arc_pmu_events_sysfs_show;
+       arc_pmu->attr[j].id = j;
+       arc_pmu->attrs[j] = &(arc_pmu->attr[j].attr.attr);
+}
+
+static int arc_pmu_raw_alloc(struct device *dev)
+{
+       arc_pmu->attr = devm_kmalloc_array(dev, arc_pmu->n_events + 1,
+               sizeof(*arc_pmu->attr), GFP_KERNEL | __GFP_ZERO);
+       if (!arc_pmu->attr)
+               return -ENOMEM;
+
+       arc_pmu->attrs = devm_kmalloc_array(dev, arc_pmu->n_events + 1,
+               sizeof(*arc_pmu->attrs), GFP_KERNEL | __GFP_ZERO);
+       if (!arc_pmu->attrs)
+               return -ENOMEM;
+
+       arc_pmu->raw_entry = devm_kmalloc_array(dev, arc_pmu->n_events,
+               sizeof(*arc_pmu->raw_entry), GFP_KERNEL | __GFP_ZERO);
+       if (!arc_pmu->raw_entry)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static inline bool event_in_hw_event_map(int i, char *name)
+{
+       if (!arc_pmu_ev_hw_map[i])
+               return false;
+
+       if (!strlen(arc_pmu_ev_hw_map[i]))
+               return false;
+
+       if (strcmp(arc_pmu_ev_hw_map[i], name))
+               return false;
+
+       return true;
+}
+
+static void arc_pmu_map_hw_event(int j, char *str)
+{
+       int i;
+
+       /* See if HW condition has been mapped to a perf event_id */
+       for (i = 0; i < ARRAY_SIZE(arc_pmu_ev_hw_map); i++) {
+               if (event_in_hw_event_map(i, str)) {
+                       pr_debug("mapping perf event %2d to h/w event \'%8s\' (idx %d)\n",
+                                i, str, j);
+                       arc_pmu->ev_hw_idx[i] = j;
+               }
+       }
+}
+
 static int arc_pmu_device_probe(struct platform_device *pdev)
 {
        struct arc_reg_pct_build pct_bcr;
        struct arc_reg_cc_build cc_bcr;
-       int i, j, has_interrupts;
+       int i, has_interrupts;
        int counter_size;       /* in bits */
 
        union cc_name {
                struct {
-                       uint32_t word0, word1;
+                       u32 word0, word1;
                        char sentinel;
                } indiv;
-               char str[9];
+               char str[ARCPMU_EVENT_NAME_LEN];
        } cc_name;
 
 
@@ -463,15 +580,22 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
                return -ENODEV;
        }
        BUILD_BUG_ON(ARC_PERF_MAX_COUNTERS > 32);
-       BUG_ON(pct_bcr.c > ARC_PERF_MAX_COUNTERS);
+       if (WARN_ON(pct_bcr.c > ARC_PERF_MAX_COUNTERS))
+               return -EINVAL;
 
        READ_BCR(ARC_REG_CC_BUILD, cc_bcr);
-       BUG_ON(!cc_bcr.v); /* Counters exist but No countable conditions ? */
+       if (WARN(!cc_bcr.v, "Counters exist but No countable conditions?"))
+               return -EINVAL;
 
        arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu), GFP_KERNEL);
        if (!arc_pmu)
                return -ENOMEM;
 
+       arc_pmu->n_events = cc_bcr.c;
+
+       if (arc_pmu_raw_alloc(&pdev->dev))
+               return -ENOMEM;
+
        has_interrupts = is_isa_arcv2() ? pct_bcr.i : 0;
 
        arc_pmu->n_counters = pct_bcr.c;
@@ -481,30 +605,26 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
 
        pr_info("ARC perf\t: %d counters (%d bits), %d conditions%s\n",
                arc_pmu->n_counters, counter_size, cc_bcr.c,
-               has_interrupts ? ", [overflow IRQ support]":"");
+               has_interrupts ? ", [overflow IRQ support]" : "");
 
-       cc_name.str[8] = 0;
+       cc_name.str[ARCPMU_EVENT_NAME_LEN - 1] = 0;
        for (i = 0; i < PERF_COUNT_ARC_HW_MAX; i++)
                arc_pmu->ev_hw_idx[i] = -1;
 
        /* loop thru all available h/w condition indexes */
-       for (j = 0; j < cc_bcr.c; j++) {
-               write_aux_reg(ARC_REG_CC_INDEX, j);
+       for (i = 0; i < cc_bcr.c; i++) {
+               write_aux_reg(ARC_REG_CC_INDEX, i);
                cc_name.indiv.word0 = read_aux_reg(ARC_REG_CC_NAME0);
                cc_name.indiv.word1 = read_aux_reg(ARC_REG_CC_NAME1);
 
-               /* See if it has been mapped to a perf event_id */
-               for (i = 0; i < ARRAY_SIZE(arc_pmu_ev_hw_map); i++) {
-                       if (arc_pmu_ev_hw_map[i] &&
-                           !strcmp(arc_pmu_ev_hw_map[i], cc_name.str) &&
-                           strlen(arc_pmu_ev_hw_map[i])) {
-                               pr_debug("mapping perf event %2d to h/w event \'%8s\' (idx %d)\n",
-                                        i, cc_name.str, j);
-                               arc_pmu->ev_hw_idx[i] = j;
-                       }
-               }
+               arc_pmu_map_hw_event(i, cc_name.str);
+               arc_pmu_add_raw_event_attr(i, cc_name.str);
        }
 
+       arc_pmu_events_attr_gr.attrs = arc_pmu->attrs;
+       arc_pmu->attr_groups[ARCPMU_ATTR_GR_EVENTS] = &arc_pmu_events_attr_gr;
+       arc_pmu->attr_groups[ARCPMU_ATTR_GR_FORMATS] = &arc_pmu_format_attr_gr;
+
        arc_pmu->pmu = (struct pmu) {
                .pmu_enable     = arc_pmu_enable,
                .pmu_disable    = arc_pmu_disable,
@@ -514,6 +634,7 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
                .start          = arc_pmu_start,
                .stop           = arc_pmu_stop,
                .read           = arc_pmu_read,
+               .attr_groups    = arc_pmu->attr_groups,
        };
 
        if (has_interrupts) {
@@ -535,17 +656,19 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
        } else
                arc_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
 
-       return perf_pmu_register(&arc_pmu->pmu, pdev->name, PERF_TYPE_RAW);
+       /*
+        * perf parser doesn't really like '-' symbol in events name, so let's
+        * use '_' in arc pct name as it goes to kernel PMU event prefix.
+        */
+       return perf_pmu_register(&arc_pmu->pmu, "arc_pct", PERF_TYPE_RAW);
 }
 
-#ifdef CONFIG_OF
 static const struct of_device_id arc_pmu_match[] = {
        { .compatible = "snps,arc700-pct" },
        { .compatible = "snps,archs-pct" },
        {},
 };
 MODULE_DEVICE_TABLE(of, arc_pmu_match);
-#endif
 
 static struct platform_driver arc_pmu_driver = {
        .driver = {
index 2e018b8..feb9009 100644 (file)
@@ -123,6 +123,7 @@ static void read_arc_build_cfg_regs(void)
        struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
        const struct id_to_str *tbl;
        struct bcr_isa_arcv2 isa;
+       struct bcr_actionpoint ap;
 
        FIX_PTR(cpu);
 
@@ -195,6 +196,7 @@ static void read_arc_build_cfg_regs(void)
                cpu->bpu.full = bpu.ft;
                cpu->bpu.num_cache = 256 << bpu.bce;
                cpu->bpu.num_pred = 2048 << bpu.pte;
+               cpu->bpu.ret_stk = 4 << bpu.rse;
 
                if (cpu->core.family >= 0x54) {
                        unsigned int exec_ctrl;
@@ -207,8 +209,11 @@ static void read_arc_build_cfg_regs(void)
                }
        }
 
-       READ_BCR(ARC_REG_AP_BCR, bcr);
-       cpu->extn.ap = bcr.ver ? 1 : 0;
+       READ_BCR(ARC_REG_AP_BCR, ap);
+       if (ap.ver) {
+               cpu->extn.ap_num = 2 << ap.num;
+               cpu->extn.ap_full = !!ap.min;
+       }
 
        READ_BCR(ARC_REG_SMART_BCR, bcr);
        cpu->extn.smart = bcr.ver ? 1 : 0;
@@ -216,8 +221,6 @@ static void read_arc_build_cfg_regs(void)
        READ_BCR(ARC_REG_RTT_BCR, bcr);
        cpu->extn.rtt = bcr.ver ? 1 : 0;
 
-       cpu->extn.debug = cpu->extn.ap | cpu->extn.smart | cpu->extn.rtt;
-
        READ_BCR(ARC_REG_ISA_CFG_BCR, isa);
 
        /* some hacks for lack of feature BCR info in old ARC700 cores */
@@ -299,10 +302,10 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
 
        if (cpu->bpu.ver)
                n += scnprintf(buf + n, len - n,
-                             "BPU\t\t: %s%s match, cache:%d, Predict Table:%d",
+                             "BPU\t\t: %s%s match, cache:%d, Predict Table:%d Return stk: %d",
                              IS_AVAIL1(cpu->bpu.full, "full"),
                              IS_AVAIL1(!cpu->bpu.full, "partial"),
-                             cpu->bpu.num_cache, cpu->bpu.num_pred);
+                             cpu->bpu.num_cache, cpu->bpu.num_pred, cpu->bpu.ret_stk);
 
        if (is_isa_arcv2()) {
                struct bcr_lpb lpb;
@@ -336,11 +339,17 @@ static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
                               IS_AVAIL1(cpu->extn.fpu_sp, "SP "),
                               IS_AVAIL1(cpu->extn.fpu_dp, "DP "));
 
-       if (cpu->extn.debug)
-               n += scnprintf(buf + n, len - n, "DEBUG\t\t: %s%s%s\n",
-                              IS_AVAIL1(cpu->extn.ap, "ActionPoint "),
+       if (cpu->extn.ap_num | cpu->extn.smart | cpu->extn.rtt) {
+               n += scnprintf(buf + n, len - n, "DEBUG\t\t: %s%s",
                               IS_AVAIL1(cpu->extn.smart, "smaRT "),
                               IS_AVAIL1(cpu->extn.rtt, "RTT "));
+               if (cpu->extn.ap_num) {
+                       n += scnprintf(buf + n, len - n, "ActionPoint %d/%s",
+                                      cpu->extn.ap_num,
+                                      cpu->extn.ap_full ? "full":"min");
+               }
+               n += scnprintf(buf + n, len - n, "\n");
+       }
 
        if (cpu->dccm.sz || cpu->iccm.sz)
                n += scnprintf(buf + n, len - n, "Extn [CCM]\t: DCCM @ %x, %d KB / ICCM: @ %x, %d KB\n",
index e8d9fb4..215f515 100644 (file)
@@ -18,6 +18,8 @@
 #include <asm/arcregs.h>
 #include <asm/irqflags.h>
 
+#define ARC_PATH_MAX   256
+
 /*
  * Common routine to print scratch regs (r0-r12) or callee regs (r13-r25)
  *   -Prints 3 regs per line and a CR.
@@ -58,11 +60,12 @@ static void show_callee_regs(struct callee_regs *cregs)
        print_reg_file(&(cregs->r13), 13);
 }
 
-static void print_task_path_n_nm(struct task_struct *tsk, char *buf)
+static void print_task_path_n_nm(struct task_struct *tsk)
 {
        char *path_nm = NULL;
        struct mm_struct *mm;
        struct file *exe_file;
+       char buf[ARC_PATH_MAX];
 
        mm = get_task_mm(tsk);
        if (!mm)
@@ -72,7 +75,7 @@ static void print_task_path_n_nm(struct task_struct *tsk, char *buf)
        mmput(mm);
 
        if (exe_file) {
-               path_nm = file_path(exe_file, buf, 255);
+               path_nm = file_path(exe_file, buf, ARC_PATH_MAX-1);
                fput(exe_file);
        }
 
@@ -80,10 +83,9 @@ done:
        pr_info("Path: %s\n", !IS_ERR(path_nm) ? path_nm : "?");
 }
 
-static void show_faulting_vma(unsigned long address, char *buf)
+static void show_faulting_vma(unsigned long address)
 {
        struct vm_area_struct *vma;
-       char *nm = buf;
        struct mm_struct *active_mm = current->active_mm;
 
        /* can't use print_vma_addr() yet as it doesn't check for
@@ -96,8 +98,11 @@ static void show_faulting_vma(unsigned long address, char *buf)
         * if the container VMA is not found
         */
        if (vma && (vma->vm_start <= address)) {
+               char buf[ARC_PATH_MAX];
+               char *nm = "?";
+
                if (vma->vm_file) {
-                       nm = file_path(vma->vm_file, buf, PAGE_SIZE - 1);
+                       nm = file_path(vma->vm_file, buf, ARC_PATH_MAX-1);
                        if (IS_ERR(nm))
                                nm = "?";
                }
@@ -173,13 +178,14 @@ void show_regs(struct pt_regs *regs)
 {
        struct task_struct *tsk = current;
        struct callee_regs *cregs;
-       char *buf;
 
-       buf = (char *)__get_free_page(GFP_KERNEL);
-       if (!buf)
-               return;
+       /*
+        * generic code calls us with preemption disabled, but some calls
+        * here could sleep, so re-enable to avoid lockdep splat
+        */
+       preempt_enable();
 
-       print_task_path_n_nm(tsk, buf);
+       print_task_path_n_nm(tsk);
        show_regs_print_info(KERN_INFO);
 
        show_ecr_verbose(regs);
@@ -189,7 +195,7 @@ void show_regs(struct pt_regs *regs)
                (void *)regs->blink, (void *)regs->ret);
 
        if (user_mode(regs))
-               show_faulting_vma(regs->ret, buf); /* faulting code, not data */
+               show_faulting_vma(regs->ret); /* faulting code, not data */
 
        pr_info("[STAT32]: 0x%08lx", regs->status32);
 
@@ -222,7 +228,7 @@ void show_regs(struct pt_regs *regs)
        if (cregs)
                show_callee_regs(cregs);
 
-       free_page((unsigned long)buf);
+       preempt_disable();
 }
 
 void show_kernel_fault_diag(const char *str, struct pt_regs *regs,
index 62ad4bc..f230bb7 100644 (file)
@@ -7,11 +7,39 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/cache.h>
 
-#undef PREALLOC_NOT_AVAIL
+/*
+ * The memset implementation below is optimized to use prefetchw and prealloc
+ * instruction in case of CPU with 64B L1 data cache line (L1_CACHE_SHIFT == 6)
+ * If you want to implement optimized memset for other possible L1 data cache
+ * line lengths (32B and 128B) you should rewrite code carefully checking
+ * we don't call any prefetchw/prealloc instruction for L1 cache lines which
+ * don't belongs to memset area.
+ */
+
+#if L1_CACHE_SHIFT == 6
+
+.macro PREALLOC_INSTR  reg, off
+       prealloc        [\reg, \off]
+.endm
+
+.macro PREFETCHW_INSTR reg, off
+       prefetchw       [\reg, \off]
+.endm
+
+#else
+
+.macro PREALLOC_INSTR
+.endm
+
+.macro PREFETCHW_INSTR
+.endm
+
+#endif
 
 ENTRY_CFI(memset)
-       prefetchw [r0]          ; Prefetch the write location
+       PREFETCHW_INSTR r0, 0   ; Prefetch the first write location
        mov.f   0, r2
 ;;; if size is zero
        jz.d    [blink]
@@ -48,11 +76,8 @@ ENTRY_CFI(memset)
 
        lpnz    @.Lset64bytes
        ;; LOOP START
-#ifdef PREALLOC_NOT_AVAIL
-       prefetchw [r3, 64]      ;Prefetch the next write location
-#else
-       prealloc  [r3, 64]
-#endif
+       PREALLOC_INSTR  r3, 64  ; alloc next line w/o fetching
+
 #ifdef CONFIG_ARC_HAS_LL64
        std.ab  r4, [r3, 8]
        std.ab  r4, [r3, 8]
@@ -85,7 +110,6 @@ ENTRY_CFI(memset)
        lsr.f   lp_count, r2, 5 ;Last remaining  max 124 bytes
        lpnz    .Lset32bytes
        ;; LOOP START
-       prefetchw   [r3, 32]    ;Prefetch the next write location
 #ifdef CONFIG_ARC_HAS_LL64
        std.ab  r4, [r3, 8]
        std.ab  r4, [r3, 8]
index a1d7231..8df1638 100644 (file)
@@ -141,12 +141,17 @@ good_area:
         */
        fault = handle_mm_fault(vma, address, flags);
 
-       /* If Pagefault was interrupted by SIGKILL, exit page fault "early" */
        if (fatal_signal_pending(current)) {
-               if ((fault & VM_FAULT_ERROR) && !(fault & VM_FAULT_RETRY))
-                       up_read(&mm->mmap_sem);
-               if (user_mode(regs))
+
+               /*
+                * if fault retry, mmap_sem already relinquished by core mm
+                * so OK to return to user mode (with signal handled first)
+                */
+               if (fault & VM_FAULT_RETRY) {
+                       if (!user_mode(regs))
+                               goto no_context;
                        return;
+               }
        }
 
        perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
index 43bf4c3..e1ab2d7 100644 (file)
@@ -119,7 +119,8 @@ void __init setup_arch_memory(void)
         */
 
        memblock_add_node(low_mem_start, low_mem_sz, 0);
-       memblock_reserve(low_mem_start, __pa(_end) - low_mem_start);
+       memblock_reserve(CONFIG_LINUX_LINK_BASE,
+                        __pa(_end) - CONFIG_LINUX_LINK_BASE);
 
 #ifdef CONFIG_BLK_DEV_INITRD
        if (phys_initrd_size) {
index b67f5fe..dce5be5 100644 (file)
 
 &cpsw_emac0 {
        phy-handle = <&ethphy0>;
-       phy-mode = "rgmii-txid";
+       phy-mode = "rgmii-id";
 };
 
 &tscadc {
index 172c022..b128998 100644 (file)
 
 &cpsw_emac0 {
        phy-handle = <&ethphy0>;
-       phy-mode = "rgmii-txid";
+       phy-mode = "rgmii-id";
        dual_emac_res_vlan = <1>;
 };
 
 &cpsw_emac1 {
        phy-handle = <&ethphy1>;
-       phy-mode = "rgmii-txid";
+       phy-mode = "rgmii-id";
        dual_emac_res_vlan = <2>;
 };
 
index d0fd688..5b25006 100644 (file)
        pinctrl-names = "default";
        pinctrl-0 = <&mmc1_pins>;
        bus-width = <0x4>;
-       cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+       cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
        cd-inverted;
        max-frequency = <26000000>;
        vmmc-supply = <&vmmcsd_fixed>;
index a3c9b34..f04bc3e 100644 (file)
                regulator-boot-on;
        };
 
+       baseboard_3v3: fixedregulator-3v3 {
+               /* TPS73701DCQ */
+               compatible = "regulator-fixed";
+               regulator-name = "baseboard_3v3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               vin-supply = <&vbat>;
+               regulator-always-on;
+               regulator-boot-on;
+       };
+
+       baseboard_1v8: fixedregulator-1v8 {
+               /* TPS73701DCQ */
+               compatible = "regulator-fixed";
+               regulator-name = "baseboard_1v8";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               vin-supply = <&vbat>;
+               regulator-always-on;
+               regulator-boot-on;
+       };
+
        backlight_lcd: backlight-regulator {
                compatible = "regulator-fixed";
                regulator-name = "lcd_backlight_pwr";
 
        sound {
                compatible = "simple-audio-card";
-               simple-audio-card,name = "DA850/OMAP-L138 EVM";
+               simple-audio-card,name = "DA850-OMAPL138 EVM";
                simple-audio-card,widgets =
                        "Line", "Line In",
                        "Line", "Line Out";
 
                /* Regulators */
                IOVDD-supply = <&vdcdc2_reg>;
-               /* Derived from VBAT: Baseboard 3.3V / 1.8V */
-               AVDD-supply = <&vbat>;
-               DRVDD-supply = <&vbat>;
-               DVDD-supply = <&vbat>;
+               AVDD-supply = <&baseboard_3v3>;
+               DRVDD-supply = <&baseboard_3v3>;
+               DVDD-supply = <&baseboard_1v8>;
        };
        tca6416: gpio@20 {
                compatible = "ti,tca6416";
index 0177e3e..3a2fa6e 100644 (file)
                };
        };
 
+       vcc_5vd: fixedregulator-vcc_5vd {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc_5vd";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-boot-on;
+       };
+
+       vcc_3v3d: fixedregulator-vcc_3v3d {
+               /* TPS650250 - VDCDC1 */
+               compatible = "regulator-fixed";
+               regulator-name = "vcc_3v3d";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               vin-supply = <&vcc_5vd>;
+               regulator-always-on;
+               regulator-boot-on;
+       };
+
+       vcc_1v8d: fixedregulator-vcc_1v8d {
+               /* TPS650250 - VDCDC2 */
+               compatible = "regulator-fixed";
+               regulator-name = "vcc_1v8d";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               vin-supply = <&vcc_5vd>;
+               regulator-always-on;
+               regulator-boot-on;
+       };
+
        sound {
                compatible = "simple-audio-card";
-               simple-audio-card,name = "DA850/OMAP-L138 LCDK";
+               simple-audio-card,name = "DA850-OMAPL138 LCDK";
                simple-audio-card,widgets =
                        "Line", "Line In",
                        "Line", "Line Out";
                compatible = "ti,tlv320aic3106";
                reg = <0x18>;
                status = "okay";
+
+               /* Regulators */
+               IOVDD-supply = <&vcc_3v3d>;
+               AVDD-supply = <&vcc_3v3d>;
+               DRVDD-supply = <&vcc_3v3d>;
+               DVDD-supply = <&vcc_1v8d>;
        };
 };
 
index 47aa53b..559659b 100644 (file)
                clocksource: timer@20000 {
                        compatible = "ti,da830-timer";
                        reg = <0x20000 0x1000>;
-                       interrupts = <12>, <13>;
+                       interrupts = <21>, <22>;
                        interrupt-names = "tint12", "tint34";
                        clocks = <&pll0_auxclk>;
                };
index 5edf858..a31b17e 100644 (file)
                power {
                        label = "Power Button";
                        gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                        linux,code = <KEY_POWER>;
                };
        };
index d816370..4a31a41 100644 (file)
        pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
        cd-gpios = <&gpio3 22 GPIO_ACTIVE_LOW>;
        keep-power-in-suspend;
-       enable-sdio-wakeup;
+       wakeup-source;
        vmmc-supply = <&reg_sd3_vmmc>;
        status = "okay";
 };
index 272ff61..d1375d3 100644 (file)
                        };
 
                        gpt: gpt@2098000 {
-                               compatible = "fsl,imx6sx-gpt", "fsl,imx31-gpt";
+                               compatible = "fsl,imx6sx-gpt", "fsl,imx6dl-gpt";
                                reg = <0x02098000 0x4000>;
                                interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SX_CLK_GPT_BUS>,
index e4645f6..2ab7486 100644 (file)
                        compatible = "amlogic,meson6-dwmac", "snps,dwmac";
                        reg = <0xc9410000 0x10000
                               0xc1108108 0x4>;
-                       interrupts = <GIC_SPI 8 IRQ_TYPE_EDGE_RISING>;
+                       interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
                        interrupt-names = "macirq";
                        status = "disabled";
                };
index 0872f6e..d50fc2f 100644 (file)
                cap-sd-highspeed;
                disable-wp;
 
-               cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-               cd-inverted;
+               cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
                vmmc-supply = <&vcc_3v3>;
        };
index 58669ab..0f0a46d 100644 (file)
                /* Realtek RTL8211F (0x001cc916) */
                eth_phy: ethernet-phy@0 {
                        reg = <0>;
-                       eee-broken-1000t;
                        interrupt-parent = <&gpio_intc>;
                        /* GPIOH_3 */
                        interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
                cap-sd-highspeed;
                disable-wp;
 
-               cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-               cd-inverted;
+               cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
                vmmc-supply = <&tflash_vdd>;
                vqmmc-supply = <&tf_io>;
index f585361..6ac02be 100644 (file)
                cap-sd-highspeed;
                disable-wp;
 
-               cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-               cd-inverted;
+               cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
                vmmc-supply = <&vcc_3v3>;
        };
index ddc7a7b..f57acf8 100644 (file)
                        interrupts-extended = <
                                &cpcap 15 0 &cpcap 14 0 &cpcap 28 0 &cpcap 19 0
                                &cpcap 18 0 &cpcap 17 0 &cpcap 16 0 &cpcap 49 0
-                               &cpcap 48 1
+                               &cpcap 48 0
                        >;
                        interrupt-names =
                                "id_ground", "id_float", "se0conn", "vbusvld",
index e53d326..93b4209 100644 (file)
 
        vdda-supply = <&vdac>;
 
-       #address-cells = <1>;
-       #size-cells = <0>;
-
        port {
-               reg = <0>;
                venc_out: endpoint {
                        remote-endpoint = <&opa_in>;
                        ti,channels = <1>;
index 182a539..826920e 100644 (file)
        /* For debugging, it is often good idea to remove this GPIO.
           It means you can remove back cover (to reboot by removing
           battery) and still use the MMC card. */
-       cd-gpios = <&gpio6 0 GPIO_ACTIVE_HIGH>; /* 160 */
+       cd-gpios = <&gpio6 0 GPIO_ACTIVE_LOW>; /* 160 */
 };
 
 /* most boards use vaux3, only some old versions use vmmc2 instead */
index 0d9b853..e142e6c 100644 (file)
                compatible = "ti,omap2-onenand";
                reg = <0 0 0x20000>;    /* CS0, offset 0, IO size 128K */
 
+               /*
+                * These timings are based on CONFIG_OMAP_GPMC_DEBUG=y reported
+                * bootloader set values when booted with v4.19 using both N950
+                * and N9 devices (OneNAND Manufacturer: Samsung):
+                *
+                *   gpmc cs0 before gpmc_cs_program_settings:
+                *   cs0 GPMC_CS_CONFIG1: 0xfd001202
+                *   cs0 GPMC_CS_CONFIG2: 0x00181800
+                *   cs0 GPMC_CS_CONFIG3: 0x00030300
+                *   cs0 GPMC_CS_CONFIG4: 0x18001804
+                *   cs0 GPMC_CS_CONFIG5: 0x03171d1d
+                *   cs0 GPMC_CS_CONFIG6: 0x97080000
+                */
                gpmc,sync-read;
                gpmc,sync-write;
                gpmc,burst-length = <16>;
                gpmc,device-width = <2>;
                gpmc,mux-add-data = <2>;
                gpmc,cs-on-ns = <0>;
-               gpmc,cs-rd-off-ns = <87>;
-               gpmc,cs-wr-off-ns = <87>;
+               gpmc,cs-rd-off-ns = <122>;
+               gpmc,cs-wr-off-ns = <122>;
                gpmc,adv-on-ns = <0>;
-               gpmc,adv-rd-off-ns = <10>;
-               gpmc,adv-wr-off-ns = <10>;
-               gpmc,oe-on-ns = <15>;
-               gpmc,oe-off-ns = <87>;
+               gpmc,adv-rd-off-ns = <15>;
+               gpmc,adv-wr-off-ns = <15>;
+               gpmc,oe-on-ns = <20>;
+               gpmc,oe-off-ns = <122>;
                gpmc,we-on-ns = <0>;
-               gpmc,we-off-ns = <87>;
-               gpmc,rd-cycle-ns = <112>;
-               gpmc,wr-cycle-ns = <112>;
-               gpmc,access-ns = <81>;
+               gpmc,we-off-ns = <122>;
+               gpmc,rd-cycle-ns = <148>;
+               gpmc,wr-cycle-ns = <148>;
+               gpmc,access-ns = <117>;
                gpmc,page-burst-access-ns = <15>;
                gpmc,bus-turnaround-ns = <0>;
                gpmc,cycle2cycle-delay-ns = <0>;
                gpmc,wait-monitoring-ns = <0>;
-               gpmc,clk-activation-ns = <5>;
-               gpmc,wr-data-mux-bus-ns = <30>;
-               gpmc,wr-access-ns = <81>;
-               gpmc,sync-clk-ps = <15000>;
+               gpmc,clk-activation-ns = <10>;
+               gpmc,wr-data-mux-bus-ns = <40>;
+               gpmc,wr-access-ns = <117>;
+
+               gpmc,sync-clk-ps = <15000>; /* TBC; Where this value came? */
 
                /*
                 * MTD partition table corresponding to Nokia's MeeGo 1.2
index 04758a2..67d77ee 100644 (file)
        };
 };
 
+/* Configure pwm clock source for timers 8 & 9 */
+&timer8 {
+       assigned-clocks = <&abe_clkctrl OMAP4_TIMER8_CLKCTRL 24>;
+       assigned-clock-parents = <&sys_clkin_ck>;
+};
+
+&timer9 {
+       assigned-clocks = <&l4_per_clkctrl OMAP4_TIMER9_CLKCTRL 24>;
+       assigned-clock-parents = <&sys_clkin_ck>;
+};
+
 /*
  * As uart1 is wired to mdm6600 with rts and cts, we can use the cts pin for
  * uart1 wakeirq.
index bc853eb..61a06f6 100644 (file)
 
        palmas_sys_nirq_pins: pinmux_palmas_sys_nirq_pins {
                pinctrl-single,pins = <
-                       OMAP5_IOPAD(0x068, PIN_INPUT_PULLUP | MUX_MODE0) /* sys_nirq1 */
+                       /* sys_nirq1 is pulled down as the SoC is inverting it for GIC */
+                       OMAP5_IOPAD(0x068, PIN_INPUT_PULLUP | MUX_MODE0)
                >;
        };
 
 
        palmas: palmas@48 {
                compatible = "ti,palmas";
-               interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */
+               /* sys_nirq/ext_sys_irq pins get inverted at mpuss wakeupgen */
+               interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_LOW>;
                reg = <0x48>;
                interrupt-controller;
                #interrupt-cells = <2>;
                pinctrl-names = "default";
                pinctrl-0 = <&twl6040_pins>;
 
-               interrupts = <GIC_SPI 119 IRQ_TYPE_NONE>; /* IRQ_SYS_2N cascaded to gic */
+               /* sys_nirq/ext_sys_irq pins get inverted at mpuss wakeupgen */
+               interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_LOW>;
 
                /* audpwron gpio defined in the board specific dts */
 
index 5e21fb4..e78d371 100644 (file)
                        OMAP5_IOPAD(0x0042, PIN_INPUT_PULLDOWN | MUX_MODE6)  /* llib_wakereqin.gpio1_wk15 */
                >;
        };
+
+       palmas_sys_nirq_pins: pinmux_palmas_sys_nirq_pins {
+               pinctrl-single,pins = <
+                       /* sys_nirq1 is pulled down as the SoC is inverting it for GIC */
+                       OMAP5_IOPAD(0x068, PIN_INPUT_PULLUP | MUX_MODE0)
+               >;
+       };
 };
 
 &omap5_pmx_core {
 
        palmas: palmas@48 {
                compatible = "ti,palmas";
-               interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */
                reg = <0x48>;
+               pinctrl-0 = <&palmas_sys_nirq_pins>;
+               pinctrl-names = "default";
+               /* sys_nirq/ext_sys_irq pins get inverted at mpuss wakeupgen */
+               interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_LOW>;
                interrupt-controller;
                #interrupt-cells = <2>;
                ti,system-power-controller;
index 9c7e309..0960348 100644 (file)
                                        <SYSC_IDLE_SMART>,
                                        <SYSC_IDLE_SMART_WKUP>;
                        ti,syss-mask = <1>;
-                       ti,no-reset-on-init;
-                       ti,no-idle-on-init;
                        /* Domains (V, P, C): core, core_pwrdm, l4per_clkdm */
                        clocks = <&l4per_clkctrl OMAP5_UART3_CLKCTRL 0>;
                        clock-names = "fck";
index 3cc33f7..3adc158 100644 (file)
 
                du: display@feb00000 {
                        compatible = "renesas,du-r8a7743";
-                       reg = <0 0xfeb00000 0 0x40000>,
-                             <0 0xfeb90000 0 0x1c>;
-                       reg-names = "du", "lvds.0";
+                       reg = <0 0xfeb00000 0 0x40000>;
                        interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 724>,
-                                <&cpg CPG_MOD 723>,
-                                <&cpg CPG_MOD 726>;
-                       clock-names = "du.0", "du.1", "lvds.0";
+                                <&cpg CPG_MOD 723>;
+                       clock-names = "du.0", "du.1";
                        status = "disabled";
 
                        ports {
                                port@1 {
                                        reg = <1>;
                                        du_out_lvds0: endpoint {
+                                               remote-endpoint = <&lvds0_in>;
+                                       };
+                               };
+                       };
+               };
+
+               lvds0: lvds@feb90000 {
+                       compatible = "renesas,r8a7743-lvds";
+                       reg = <0 0xfeb90000 0 0x1c>;
+                       clocks = <&cpg CPG_MOD 726>;
+                       power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 726>;
+                       status = "disabled";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       lvds0_in: endpoint {
+                                               remote-endpoint = <&du_out_lvds0>;
+                                       };
+                               };
+                               port@1 {
+                                       reg = <1>;
+                                       lvds0_out: endpoint {
                                        };
                                };
                        };
index 4acb501..3ed4989 100644 (file)
                        pm_qos = <&qos_lcdc0>,
                                 <&qos_lcdc1>,
                                 <&qos_cif0>,
-                                <&qos_cif1>,
                                 <&qos_ipp>,
                                 <&qos_rga>;
                };
index 353d90f..13304b8 100644 (file)
                        #clock-cells = <0>;
                        compatible = "fixed-clock";
                        clock-frequency = <24000000>;
+                       clock-output-names = "osc24M";
                };
 
                osc32k: clk-32k {
index 5d23667..25540b7 100644 (file)
@@ -53,7 +53,7 @@
 
        aliases {
                serial0 = &uart0;
-               /* ethernet0 is the H3 emac, defined in sun8i-h3.dtsi */
+               ethernet0 = &emac;
                ethernet1 = &sdiowifi;
        };
 
index d5f11d6..bc85b6a 100644 (file)
                stdout-path = "serial0:115200n8";
        };
 
-       memory@80000000 {
+       /*
+        * Note that recent version of the device tree compiler (starting with
+        * version 1.4.2) warn about this node containing a reg property, but
+        * missing a unit-address. However, the bootloader on these Chromebook
+        * devices relies on the full name of this node to be exactly /memory.
+        * Adding the unit-address causes the bootloader to create a /memory
+        * node and write the memory bank configuration to that node, which in
+        * turn leads the kernel to believe that the device has 2 GiB of
+        * memory instead of the amount detected by the bootloader.
+        *
+        * The name of this node is effectively ABI and must not be changed.
+        */
+       memory {
+               device_type = "memory";
                reg = <0x0 0x80000000 0x0 0x80000000>;
        };
 
+       /delete-node/ memory@80000000;
+
        host1x@50000000 {
                hdmi@54280000 {
                        status = "okay";
index 689c893..b08d561 100644 (file)
        bus-num = <3>;
        status = "okay";
        spi-slave;
+       #address-cells = <0>;
 
-       slave@0 {
+       slave {
                compatible = "lwn,bk4";
                spi-max-frequency = <30000000>;
-               reg = <0>;
        };
 };
 
index ca56537..50e8986 100644 (file)
@@ -48,6 +48,7 @@
 #define KVM_REQ_SLEEP \
        KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
 #define KVM_REQ_IRQ_PENDING    KVM_ARCH_REQ(1)
+#define KVM_REQ_VCPU_RESET     KVM_ARCH_REQ(2)
 
 DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
 
@@ -147,6 +148,13 @@ struct kvm_cpu_context {
 
 typedef struct kvm_cpu_context kvm_cpu_context_t;
 
+struct vcpu_reset_state {
+       unsigned long   pc;
+       unsigned long   r0;
+       bool            be;
+       bool            reset;
+};
+
 struct kvm_vcpu_arch {
        struct kvm_cpu_context ctxt;
 
@@ -186,6 +194,8 @@ struct kvm_vcpu_arch {
        /* Cache some mmu pages needed inside spinlock regions */
        struct kvm_mmu_memory_cache mmu_page_cache;
 
+       struct vcpu_reset_state reset_state;
+
        /* Detect first run of a vcpu */
        bool has_run_once;
 };
index c4b1d4f..de20895 100644 (file)
@@ -76,4 +76,9 @@ static inline bool kvm_stage2_has_pud(struct kvm *kvm)
 #define S2_PMD_MASK                            PMD_MASK
 #define S2_PMD_SIZE                            PMD_SIZE
 
+static inline bool kvm_stage2_has_pmd(struct kvm *kvm)
+{
+       return true;
+}
+
 #endif /* __ARM_S2_PGTABLE_H_ */
index b3ef061..2c403e7 100644 (file)
@@ -1 +1,95 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_ARM_XEN_PAGE_COHERENT_H
+#define _ASM_ARM_XEN_PAGE_COHERENT_H
+
+#include <linux/dma-mapping.h>
+#include <asm/page.h>
 #include <xen/arm/page-coherent.h>
+
+static inline const struct dma_map_ops *xen_get_dma_ops(struct device *dev)
+{
+       if (dev && dev->archdata.dev_dma_ops)
+               return dev->archdata.dev_dma_ops;
+       return get_arch_dma_ops(NULL);
+}
+
+static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
+               dma_addr_t *dma_handle, gfp_t flags, unsigned long attrs)
+{
+       return xen_get_dma_ops(hwdev)->alloc(hwdev, size, dma_handle, flags, attrs);
+}
+
+static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
+               void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs)
+{
+       xen_get_dma_ops(hwdev)->free(hwdev, size, cpu_addr, dma_handle, attrs);
+}
+
+static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
+            dma_addr_t dev_addr, unsigned long offset, size_t size,
+            enum dma_data_direction dir, unsigned long attrs)
+{
+       unsigned long page_pfn = page_to_xen_pfn(page);
+       unsigned long dev_pfn = XEN_PFN_DOWN(dev_addr);
+       unsigned long compound_pages =
+               (1<<compound_order(page)) * XEN_PFN_PER_PAGE;
+       bool local = (page_pfn <= dev_pfn) &&
+               (dev_pfn - page_pfn < compound_pages);
+
+       /*
+        * Dom0 is mapped 1:1, while the Linux page can span across
+        * multiple Xen pages, it's not possible for it to contain a
+        * mix of local and foreign Xen pages. So if the first xen_pfn
+        * == mfn the page is local otherwise it's a foreign page
+        * grant-mapped in dom0. If the page is local we can safely
+        * call the native dma_ops function, otherwise we call the xen
+        * specific function.
+        */
+       if (local)
+               xen_get_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
+       else
+               __xen_dma_map_page(hwdev, page, dev_addr, offset, size, dir, attrs);
+}
+
+static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
+               size_t size, enum dma_data_direction dir, unsigned long attrs)
+{
+       unsigned long pfn = PFN_DOWN(handle);
+       /*
+        * Dom0 is mapped 1:1, while the Linux page can be spanned accross
+        * multiple Xen page, it's not possible to have a mix of local and
+        * foreign Xen page. Dom0 is mapped 1:1, so calling pfn_valid on a
+        * foreign mfn will always return false. If the page is local we can
+        * safely call the native dma_ops function, otherwise we call the xen
+        * specific function.
+        */
+       if (pfn_valid(pfn)) {
+               if (xen_get_dma_ops(hwdev)->unmap_page)
+                       xen_get_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs);
+       } else
+               __xen_dma_unmap_page(hwdev, handle, size, dir, attrs);
+}
+
+static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
+               dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+       unsigned long pfn = PFN_DOWN(handle);
+       if (pfn_valid(pfn)) {
+               if (xen_get_dma_ops(hwdev)->sync_single_for_cpu)
+                       xen_get_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir);
+       } else
+               __xen_dma_sync_single_for_cpu(hwdev, handle, size, dir);
+}
+
+static inline void xen_dma_sync_single_for_device(struct device *hwdev,
+               dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+       unsigned long pfn = PFN_DOWN(handle);
+       if (pfn_valid(pfn)) {
+               if (xen_get_dma_ops(hwdev)->sync_single_for_device)
+                       xen_get_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir);
+       } else
+               __xen_dma_sync_single_for_device(hwdev, handle, size, dir);
+}
+
+#endif /* _ASM_ARM_XEN_PAGE_COHERENT_H */
index 222c163..e8bd288 100644 (file)
@@ -1450,6 +1450,6 @@ void kvm_reset_coprocs(struct kvm_vcpu *vcpu)
        reset_coproc_regs(vcpu, table, num);
 
        for (num = 1; num < NR_CP15_REGS; num++)
-               if (vcpu_cp15(vcpu, num) == 0x42424242)
-                       panic("Didn't reset vcpu_cp15(vcpu, %zi)", num);
+               WARN(vcpu_cp15(vcpu, num) == 0x42424242,
+                    "Didn't reset vcpu_cp15(vcpu, %zi)", num);
 }
index 5ed0c3e..e533279 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/cputype.h>
 #include <asm/kvm_arm.h>
 #include <asm/kvm_coproc.h>
+#include <asm/kvm_emulate.h>
 
 #include <kvm/arm_arch_timer.h>
 
@@ -69,6 +70,29 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
        /* Reset CP15 registers */
        kvm_reset_coprocs(vcpu);
 
+       /*
+        * Additional reset state handling that PSCI may have imposed on us.
+        * Must be done after all the sys_reg reset.
+        */
+       if (READ_ONCE(vcpu->arch.reset_state.reset)) {
+               unsigned long target_pc = vcpu->arch.reset_state.pc;
+
+               /* Gracefully handle Thumb2 entry point */
+               if (target_pc & 1) {
+                       target_pc &= ~1UL;
+                       vcpu_set_thumb(vcpu);
+               }
+
+               /* Propagate caller endianness */
+               if (vcpu->arch.reset_state.be)
+                       kvm_vcpu_set_be(vcpu);
+
+               *vcpu_pc(vcpu) = target_pc;
+               vcpu_set_reg(vcpu, 0, vcpu->arch.reset_state.r0);
+
+               vcpu->arch.reset_state.reset = false;
+       }
+
        /* Reset arch_timer context */
        return kvm_timer_vcpu_reset(vcpu);
 }
index 318394e..95a11d5 100644 (file)
@@ -83,7 +83,7 @@ static void __iomem *cns3xxx_pci_map_bus(struct pci_bus *bus,
        } else /* remote PCI bus */
                base = cnspci->cfg1_regs + ((busno & 0xf) << 20);
 
-       return base + (where & 0xffc) + (devfn << 12);
+       return base + where + (devfn << 12);
 }
 
 static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
@@ -93,7 +93,7 @@ static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
        u32 mask = (0x1ull << (size * 8)) - 1;
        int shift = (where % 4) * 8;
 
-       ret = pci_generic_config_read32(bus, devfn, where, size, val);
+       ret = pci_generic_config_read(bus, devfn, where, size, val);
 
        if (ret == PCIBIOS_SUCCESSFUL && !bus->number && !devfn &&
            (where & 0xffc) == PCI_CLASS_REVISION)
index e52ec16..c4da635 100644 (file)
@@ -208,9 +208,9 @@ static struct gpiod_lookup_table mmc_gpios_table = {
        .dev_id = "da830-mmc.0",
        .table = {
                /* gpio chip 1 contains gpio range 32-63 */
-               GPIO_LOOKUP("davinci_gpio.0", DA830_MMCSD_CD_PIN, "cd",
+               GPIO_LOOKUP("davinci_gpio", DA830_MMCSD_CD_PIN, "cd",
                            GPIO_ACTIVE_LOW),
-               GPIO_LOOKUP("davinci_gpio.0", DA830_MMCSD_WP_PIN, "wp",
+               GPIO_LOOKUP("davinci_gpio", DA830_MMCSD_WP_PIN, "wp",
                            GPIO_ACTIVE_LOW),
        },
 };
index 6a29baf..44bca04 100644 (file)
@@ -805,9 +805,9 @@ static struct gpiod_lookup_table mmc_gpios_table = {
        .dev_id = "da830-mmc.0",
        .table = {
                /* gpio chip 2 contains gpio range 64-95 */
-               GPIO_LOOKUP("davinci_gpio.0", DA850_MMCSD_CD_PIN, "cd",
+               GPIO_LOOKUP("davinci_gpio", DA850_MMCSD_CD_PIN, "cd",
                            GPIO_ACTIVE_LOW),
-               GPIO_LOOKUP("davinci_gpio.0", DA850_MMCSD_WP_PIN, "wp",
+               GPIO_LOOKUP("davinci_gpio", DA850_MMCSD_WP_PIN, "wp",
                            GPIO_ACTIVE_HIGH),
        },
 };
index f53a461..f7fa960 100644 (file)
@@ -117,9 +117,9 @@ static struct platform_device davinci_nand_device = {
 static struct gpiod_lookup_table i2c_recovery_gpiod_table = {
        .dev_id = "i2c_davinci.1",
        .table = {
-               GPIO_LOOKUP("davinci_gpio.0", DM355_I2C_SDA_PIN, "sda",
+               GPIO_LOOKUP("davinci_gpio", DM355_I2C_SDA_PIN, "sda",
                            GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
-               GPIO_LOOKUP("davinci_gpio.0", DM355_I2C_SCL_PIN, "scl",
+               GPIO_LOOKUP("davinci_gpio", DM355_I2C_SCL_PIN, "scl",
                            GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
        },
 };
index e142811..b80c4ee 100644 (file)
@@ -660,9 +660,9 @@ static struct i2c_board_info __initdata i2c_info[] =  {
 static struct gpiod_lookup_table i2c_recovery_gpiod_table = {
        .dev_id = "i2c_davinci.1",
        .table = {
-               GPIO_LOOKUP("davinci_gpio.0", DM644X_I2C_SDA_PIN, "sda",
+               GPIO_LOOKUP("davinci_gpio", DM644X_I2C_SDA_PIN, "sda",
                            GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
-               GPIO_LOOKUP("davinci_gpio.0", DM644X_I2C_SCL_PIN, "scl",
+               GPIO_LOOKUP("davinci_gpio", DM644X_I2C_SCL_PIN, "scl",
                            GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
        },
 };
index 8e8d51f..94c4f12 100644 (file)
@@ -134,9 +134,9 @@ static const short hawk_mmcsd0_pins[] = {
 static struct gpiod_lookup_table mmc_gpios_table = {
        .dev_id = "da830-mmc.0",
        .table = {
-               GPIO_LOOKUP("davinci_gpio.0", DA850_HAWK_MMCSD_CD_PIN, "cd",
+               GPIO_LOOKUP("davinci_gpio", DA850_HAWK_MMCSD_CD_PIN, "cd",
                            GPIO_ACTIVE_LOW),
-               GPIO_LOOKUP("davinci_gpio.0", DA850_HAWK_MMCSD_WP_PIN, "wp",
+               GPIO_LOOKUP("davinci_gpio", DA850_HAWK_MMCSD_WP_PIN, "wp",
                            GPIO_ACTIVE_LOW),
        },
 };
index a109f64..8dfad01 100644 (file)
@@ -390,10 +390,14 @@ static int __ref impd1_probe(struct lm_device *dev)
                        char *mmciname;
 
                        lookup = devm_kzalloc(&dev->dev,
-                                             sizeof(*lookup) + 3 * sizeof(struct gpiod_lookup),
+                                             struct_size(lookup, table, 3),
                                              GFP_KERNEL);
                        chipname = devm_kstrdup(&dev->dev, devname, GFP_KERNEL);
-                       mmciname = kasprintf(GFP_KERNEL, "lm%x:00700", dev->id);
+                       mmciname = devm_kasprintf(&dev->dev, GFP_KERNEL,
+                                                 "lm%x:00700", dev->id);
+                       if (!lookup || !chipname || !mmciname)
+                               return -ENOMEM;
+
                        lookup->dev_id = mmciname;
                        /*
                         * Offsets on GPIO block 1:
index 3b73813..23e8c93 100644 (file)
@@ -75,8 +75,7 @@ void __init n2100_map_io(void)
 /*
  * N2100 PCI.
  */
-static int __init
-n2100_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+static int n2100_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
 
index a8b291f..dae514c 100644 (file)
@@ -152,6 +152,10 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
        mpuss_can_lose_context = (cx->mpu_state == PWRDM_POWER_RET) &&
                                 (cx->mpu_logic_state == PWRDM_POWER_OFF);
 
+       /* Enter broadcast mode for periodic timers */
+       tick_broadcast_enable();
+
+       /* Enter broadcast mode for one-shot timers */
        tick_broadcast_enter();
 
        /*
@@ -218,15 +222,6 @@ fail:
        return index;
 }
 
-/*
- * For each cpu, setup the broadcast timer because local timers
- * stops for the states above C1.
- */
-static void omap_setup_broadcast_timer(void *arg)
-{
-       tick_broadcast_enable();
-}
-
 static struct cpuidle_driver omap4_idle_driver = {
        .name                           = "omap4_idle",
        .owner                          = THIS_MODULE,
@@ -319,8 +314,5 @@ int __init omap4_idle_init(void)
        if (!cpu_clkdm[0] || !cpu_clkdm[1])
                return -ENODEV;
 
-       /* Configure the broadcast timer on each cpu */
-       on_each_cpu(omap_setup_broadcast_timer, NULL, 1);
-
        return cpuidle_register(idle_driver, cpu_online_mask);
 }
index f86b72d..1444b4b 100644 (file)
@@ -83,6 +83,7 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
        u32 enable_mask, enable_shift;
        u32 pipd_mask, pipd_shift;
        u32 reg;
+       int ret;
 
        if (dsi_id == 0) {
                enable_mask = OMAP4_DSI1_LANEENABLE_MASK;
@@ -98,7 +99,11 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
                return -ENODEV;
        }
 
-       regmap_read(omap4_dsi_mux_syscon, OMAP4_DSIPHY_SYSCON_OFFSET, &reg);
+       ret = regmap_read(omap4_dsi_mux_syscon,
+                                         OMAP4_DSIPHY_SYSCON_OFFSET,
+                                         &reg);
+       if (ret)
+               return ret;
 
        reg &= ~enable_mask;
        reg &= ~pipd_mask;
index fc5fb77..17558be 100644 (file)
@@ -50,6 +50,9 @@
 #define OMAP4_NR_BANKS         4
 #define OMAP4_NR_IRQS          128
 
+#define SYS_NIRQ1_EXT_SYS_IRQ_1        7
+#define SYS_NIRQ2_EXT_SYS_IRQ_2        119
+
 static void __iomem *wakeupgen_base;
 static void __iomem *sar_base;
 static DEFINE_RAW_SPINLOCK(wakeupgen_lock);
@@ -153,6 +156,37 @@ static void wakeupgen_unmask(struct irq_data *d)
        irq_chip_unmask_parent(d);
 }
 
+/*
+ * The sys_nirq pins bypass peripheral modules and are wired directly
+ * to MPUSS wakeupgen. They get automatically inverted for GIC.
+ */
+static int wakeupgen_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       bool inverted = false;
+
+       switch (type) {
+       case IRQ_TYPE_LEVEL_LOW:
+               type &= ~IRQ_TYPE_LEVEL_MASK;
+               type |= IRQ_TYPE_LEVEL_HIGH;
+               inverted = true;
+               break;
+       case IRQ_TYPE_EDGE_FALLING:
+               type &= ~IRQ_TYPE_EDGE_BOTH;
+               type |= IRQ_TYPE_EDGE_RISING;
+               inverted = true;
+               break;
+       default:
+               break;
+       }
+
+       if (inverted && d->hwirq != SYS_NIRQ1_EXT_SYS_IRQ_1 &&
+           d->hwirq != SYS_NIRQ2_EXT_SYS_IRQ_2)
+               pr_warn("wakeupgen: irq%li polarity inverted in dts\n",
+                       d->hwirq);
+
+       return irq_chip_set_type_parent(d, type);
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 static DEFINE_PER_CPU(u32 [MAX_NR_REG_BANKS], irqmasks);
 
@@ -446,7 +480,7 @@ static struct irq_chip wakeupgen_chip = {
        .irq_mask               = wakeupgen_mask,
        .irq_unmask             = wakeupgen_unmask,
        .irq_retrigger          = irq_chip_retrigger_hierarchy,
-       .irq_set_type           = irq_chip_set_type_parent,
+       .irq_set_type           = wakeupgen_irq_set_type,
        .flags                  = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND,
 #ifdef CONFIG_SMP
        .irq_set_affinity       = irq_chip_set_affinity_parent,
index 5fb6f79..afd9897 100644 (file)
@@ -32,6 +32,8 @@ void __iomem *rst_manager_base_addr;
 void __iomem *sdr_ctl_base_addr;
 unsigned long socfpga_cpu1start_addr;
 
+extern void __init socfpga_reset_init(void);
+
 static void __init socfpga_sysmgr_init(void)
 {
        struct device_node *np;
@@ -64,6 +66,7 @@ static void __init socfpga_init_irq(void)
 
        if (IS_ENABLED(CONFIG_EDAC_ALTERA_OCRAM))
                socfpga_init_ocram_ecc();
+       socfpga_reset_init();
 }
 
 static void __init socfpga_arria10_init_irq(void)
@@ -74,6 +77,7 @@ static void __init socfpga_arria10_init_irq(void)
                socfpga_init_arria10_l2_ecc();
        if (IS_ENABLED(CONFIG_EDAC_ALTERA_OCRAM))
                socfpga_init_arria10_ocram_ecc();
+       socfpga_reset_init();
 }
 
 static void socfpga_cyclone5_restart(enum reboot_mode mode, const char *cmd)
index 028e50c..a32c3b6 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/suspend.h>
 #include <asm/suspend.h>
 #include "smc.h"
+#include "pm.h"
 
 static int tango_pm_powerdown(unsigned long arg)
 {
@@ -24,10 +25,7 @@ static const struct platform_suspend_ops tango_pm_ops = {
        .valid = suspend_valid_only_mem,
 };
 
-static int __init tango_pm_init(void)
+void __init tango_pm_init(void)
 {
        suspend_set_ops(&tango_pm_ops);
-       return 0;
 }
-
-late_initcall(tango_pm_init);
diff --git a/arch/arm/mach-tango/pm.h b/arch/arm/mach-tango/pm.h
new file mode 100644 (file)
index 0000000..35ea705
--- /dev/null
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifdef CONFIG_SUSPEND
+void __init tango_pm_init(void);
+#else
+#define tango_pm_init NULL
+#endif
index 677dd7b..824f907 100644 (file)
@@ -2,6 +2,7 @@
 #include <asm/mach/arch.h>
 #include <asm/hardware/cache-l2x0.h>
 #include "smc.h"
+#include "pm.h"
 
 static void tango_l2c_write(unsigned long val, unsigned int reg)
 {
@@ -15,4 +16,5 @@ DT_MACHINE_START(TANGO_DT, "Sigma Tango DT")
        .dt_compat      = tango_dt_compat,
        .l2c_aux_mask   = ~0,
        .l2c_write_sec  = tango_l2c_write,
+       .init_late      = tango_pm_init,
 MACHINE_END
index ed36dca..f519199 100644 (file)
@@ -190,8 +190,6 @@ static int pxa_ssp_remove(struct platform_device *pdev)
        if (ssp == NULL)
                return -ENODEV;
 
-       iounmap(ssp->mmio_base);
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(res->start, resource_size(res));
 
@@ -201,7 +199,6 @@ static int pxa_ssp_remove(struct platform_device *pdev)
        list_del(&ssp->node);
        mutex_unlock(&ssp_lock);
 
-       kfree(ssp);
        return 0;
 }
 
index cb44aa2..e1d44b9 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/types.h>
-#include <linux/dma-mapping.h>
 #include <linux/vmalloc.h>
 #include <linux/swiotlb.h>
 
index b0c64f7..8974b5a 100644 (file)
                reg = <0x3a3>;
                interrupt-parent = <&r_intc>;
                interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+               x-powers,drive-vbus-en; /* set N_VBUSEN as output pin */
        };
 };
 
index 837a03d..2abb335 100644 (file)
                };
 
                video-codec@1c0e000 {
-                       compatible = "allwinner,sun50i-h5-video-engine";
+                       compatible = "allwinner,sun50i-a64-video-engine";
                        reg = <0x01c0e000 0x1000>;
                        clocks = <&ccu CLK_BUS_VE>, <&ccu CLK_VE>,
                                 <&ccu CLK_DRAM_VE>;
index e14e0ce..016641a 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_boot>;
index 8cd50b7..ade2ee0 100644 (file)
        max-frequency = <200000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddio_ao3v3>;
        vqmmc-supply = <&vddio_tf>;
index 4cf7f6e..25105ac 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_card>;
index 2e1cd5e..1cc9dc6 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&tflash_vdd>;
        vqmmc-supply = <&tf_io>;
index ce86226..0be0f2a 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_card>;
index 93a4acf..ad4d50b 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vcc_3v3>;
 };
index ec09bb5..2d2db78 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vcc_3v3>;
index f1c410e..796baea 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_card>;
index db29344..255cede 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vcc_3v3>;
        vqmmc-supply = <&vcc_card>;
index 6739697..9cbdb85 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_card>;
index a1b3101..bc811a2 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_boot>;
index 3c3a667..3f086ed 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_boot>;
index f7a1cff..8acfd40 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_boot>;
index 7212dc4..7fa20a8 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_boot>;
index 64acccc..f74b13a 100644 (file)
 
        pinctrl_usdhc1_100mhz: usdhc1-100grp {
                fsl,pins = <
-                       MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK                 0x85
-                       MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD                 0xc5
-                       MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7             0xc5
-                       MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE           0x85
+                       MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK                 0x8d
+                       MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD                 0xcd
+                       MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7             0xcd
+                       MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE           0x8d
                        MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B         0xc1
                >;
        };
 
        pinctrl_usdhc1_200mhz: usdhc1-200grp {
                fsl,pins = <
-                       MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK                 0x87
-                       MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD                 0xc7
-                       MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7             0xc7
-                       MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE           0x87
+                       MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK                 0x9f
+                       MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD                 0xdf
+                       MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7             0xdf
+                       MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE           0x9f
                        MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B         0xc1
                >;
        };
index 8e9d6d5..b6d3149 100644 (file)
                                         <&clk IMX8MQ_CLK_NAND_USDHC_BUS>,
                                         <&clk IMX8MQ_CLK_USDHC1_ROOT>;
                                clock-names = "ipg", "ahb", "per";
+                               assigned-clocks = <&clk IMX8MQ_CLK_USDHC1>;
+                               assigned-clock-rates = <400000000>;
                                fsl,tuning-start-tap = <20>;
                                fsl,tuning-step = <2>;
                                bus-width = <4>;
index 99b7495..838e32c 100644 (file)
                };
 
                intc: interrupt-controller@9bc0000 {
-                       compatible = "arm,gic-v3";
+                       compatible = "qcom,msm8996-gic-v3", "arm,gic-v3";
                        #interrupt-cells = <3>;
                        interrupt-controller;
                        #redistributor-regions = <1>;
index 20745a8..719ed9d 100644 (file)
                                 <&cpg CPG_CORE R8A774A1_CLK_S3D1>,
                                 <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x13>, <&dmac1 0x12>,
+                              <&dmac2 0x13>, <&dmac2 0x12>;
+                       dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
                        resets = <&cpg 310>;
                        status = "disabled";
index afedbf5..0648d12 100644 (file)
                                 <&cpg CPG_CORE R8A7796_CLK_S3D1>,
                                 <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x13>, <&dmac1 0x12>,
+                              <&dmac2 0x13>, <&dmac2 0x12>;
+                       dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
                        resets = <&cpg 310>;
                        status = "disabled";
index 6dc9b1f..4b3730f 100644 (file)
                                 <&cpg CPG_CORE R8A77965_CLK_S3D1>,
                                 <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x13>, <&dmac1 0x12>,
+                              <&dmac2 0x13>, <&dmac2 0x12>;
+                       dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
                        resets = <&cpg 310>;
                        status = "disabled";
index bd937d6..040b36e 100644 (file)
@@ -40,6 +40,7 @@
                pinctrl-0 = <&usb30_host_drv>;
                regulator-name = "vcc_host_5v";
                regulator-always-on;
+               regulator-boot-on;
                vin-supply = <&vcc_sys>;
        };
 
@@ -51,6 +52,7 @@
                pinctrl-0 = <&usb20_host_drv>;
                regulator-name = "vcc_host1_5v";
                regulator-always-on;
+               regulator-boot-on;
                vin-supply = <&vcc_sys>;
        };
 
index 1ee0dc0..d1cf404 100644 (file)
@@ -22,7 +22,7 @@
                backlight = <&backlight>;
                power-supply = <&pp3300_disp>;
 
-               ports {
+               port {
                        panel_in_edp: endpoint {
                                remote-endpoint = <&edp_out_panel>;
                        };
index 81e7310..15e254a 100644 (file)
@@ -43,7 +43,7 @@
                backlight = <&backlight>;
                power-supply = <&pp3300_disp>;
 
-               ports {
+               port {
                        panel_in_edp: endpoint {
                                remote-endpoint = <&edp_out_panel>;
                        };
index 0b8f1ed..b48a63c 100644 (file)
@@ -91,7 +91,7 @@
                pinctrl-0 = <&lcd_panel_reset>;
                power-supply = <&vcc3v3_s0>;
 
-               ports {
+               port {
                        panel_in_edp: endpoint {
                                remote-endpoint = <&edp_out_panel>;
                        };
index 3ef443c..c8432e2 100644 (file)
@@ -506,11 +506,15 @@ CONFIG_SND_SOC_ROCKCHIP=m
 CONFIG_SND_SOC_ROCKCHIP_SPDIF=m
 CONFIG_SND_SOC_ROCKCHIP_RT5645=m
 CONFIG_SND_SOC_RK3399_GRU_SOUND=m
+CONFIG_SND_MESON_AXG_SOUND_CARD=m
 CONFIG_SND_SOC_SAMSUNG=y
 CONFIG_SND_SOC_RCAR=m
 CONFIG_SND_SOC_AK4613=m
 CONFIG_SND_SIMPLE_CARD=m
 CONFIG_SND_AUDIO_GRAPH_CARD=m
+CONFIG_SND_SOC_ES7134=m
+CONFIG_SND_SOC_ES7241=m
+CONFIG_SND_SOC_TAS571X=m
 CONFIG_I2C_HID=m
 CONFIG_USB=y
 CONFIG_USB_OTG=y
index 2173ad3..1c9a3a0 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef __ASM_PROTOTYPES_H
 #define __ASM_PROTOTYPES_H
 /*
- * CONFIG_MODEVERIONS requires a C declaration to generate the appropriate CRC
+ * CONFIG_MODVERSIONS requires a C declaration to generate the appropriate CRC
  * for each symbol. Since commit:
  *
  *   4efca4ed05cbdfd1 ("kbuild: modversions for EXPORT_SYMBOL() for asm")
index 13dd42c..926434f 100644 (file)
  */
 #define ARCH_DMA_MINALIGN      (128)
 
+#ifdef CONFIG_KASAN_SW_TAGS
+#define ARCH_SLAB_MINALIGN     (1ULL << KASAN_SHADOW_SCALE_SHIFT)
+#endif
+
 #ifndef __ASSEMBLY__
 
 #include <linux/bitops.h>
index 3dd3d66..4658c93 100644 (file)
@@ -20,9 +20,6 @@ struct dev_archdata {
 #ifdef CONFIG_IOMMU_API
        void *iommu;                    /* private IOMMU data */
 #endif
-#ifdef CONFIG_XEN
-       const struct dma_map_ops *dev_dma_ops;
-#endif
 };
 
 struct pdev_archdata {
index 7732d0b..da3fc73 100644 (file)
@@ -48,6 +48,7 @@
 #define KVM_REQ_SLEEP \
        KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
 #define KVM_REQ_IRQ_PENDING    KVM_ARCH_REQ(1)
+#define KVM_REQ_VCPU_RESET     KVM_ARCH_REQ(2)
 
 DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
 
@@ -208,6 +209,13 @@ struct kvm_cpu_context {
 
 typedef struct kvm_cpu_context kvm_cpu_context_t;
 
+struct vcpu_reset_state {
+       unsigned long   pc;
+       unsigned long   r0;
+       bool            be;
+       bool            reset;
+};
+
 struct kvm_vcpu_arch {
        struct kvm_cpu_context ctxt;
 
@@ -297,6 +305,9 @@ struct kvm_vcpu_arch {
        /* Virtual SError ESR to restore when HCR_EL2.VSE is set */
        u64 vsesr_el2;
 
+       /* Additional reset state */
+       struct vcpu_reset_state reset_state;
+
        /* True when deferrable sysregs are loaded on the physical CPU,
         * see kvm_vcpu_load_sysregs and kvm_vcpu_put_sysregs. */
        bool sysregs_loaded_on_cpu;
index e1ec947..0c65685 100644 (file)
@@ -332,6 +332,17 @@ static inline void *phys_to_virt(phys_addr_t x)
 #define virt_addr_valid(kaddr)         \
        (_virt_addr_is_linear(kaddr) && _virt_addr_valid(kaddr))
 
+/*
+ * Given that the GIC architecture permits ITS implementations that can only be
+ * configured with a LPI table address once, GICv3 systems with many CPUs may
+ * end up reserving a lot of different regions after a kexec for their LPI
+ * tables (one per CPU), as we are forced to reuse the same memory after kexec
+ * (and thus reserve it persistently with EFI beforehand)
+ */
+#if defined(CONFIG_EFI) && defined(CONFIG_ARM_GIC_V3_ITS)
+# define INIT_MEMBLOCK_RESERVED_REGIONS        (INIT_MEMBLOCK_REGIONS + NR_CPUS + 1)
+#endif
+
 #include <asm-generic/memory_model.h>
 
 #endif
index 7689c7a..3e8063f 100644 (file)
@@ -16,6 +16,8 @@
 #ifndef __ASM_MMU_H
 #define __ASM_MMU_H
 
+#include <asm/cputype.h>
+
 #define MMCF_AARCH32   0x1     /* mm context flag for AArch32 executables */
 #define USER_ASID_BIT  48
 #define USER_ASID_FLAG (UL(1) << USER_ASID_BIT)
@@ -44,6 +46,48 @@ static inline bool arm64_kernel_unmapped_at_el0(void)
               cpus_have_const_cap(ARM64_UNMAP_KERNEL_AT_EL0);
 }
 
+static inline bool arm64_kernel_use_ng_mappings(void)
+{
+       bool tx1_bug;
+
+       /* What's a kpti? Use global mappings if we don't know. */
+       if (!IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0))
+               return false;
+
+       /*
+        * Note: this function is called before the CPU capabilities have
+        * been configured, so our early mappings will be global. If we
+        * later determine that kpti is required, then
+        * kpti_install_ng_mappings() will make them non-global.
+        */
+       if (arm64_kernel_unmapped_at_el0())
+               return true;
+
+       if (!IS_ENABLED(CONFIG_RANDOMIZE_BASE))
+               return false;
+
+       /*
+        * KASLR is enabled so we're going to be enabling kpti on non-broken
+        * CPUs regardless of their susceptibility to Meltdown. Rather
+        * than force everybody to go through the G -> nG dance later on,
+        * just put down non-global mappings from the beginning.
+        */
+       if (!IS_ENABLED(CONFIG_CAVIUM_ERRATUM_27456)) {
+               tx1_bug = false;
+#ifndef MODULE
+       } else if (!static_branch_likely(&arm64_const_caps_ready)) {
+               extern const struct midr_range cavium_erratum_27456_cpus[];
+
+               tx1_bug = is_midr_in_range_list(read_cpuid_id(),
+                                               cavium_erratum_27456_cpus);
+#endif
+       } else {
+               tx1_bug = __cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_27456);
+       }
+
+       return !tx1_bug && kaslr_offset() > 0;
+}
+
 typedef void (*bp_hardening_cb_t)(void);
 
 struct bp_hardening_data {
index 78b942c..986e41c 100644 (file)
@@ -37,8 +37,8 @@
 #define _PROT_DEFAULT          (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED)
 #define _PROT_SECT_DEFAULT     (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S)
 
-#define PTE_MAYBE_NG           (arm64_kernel_unmapped_at_el0() ? PTE_NG : 0)
-#define PMD_MAYBE_NG           (arm64_kernel_unmapped_at_el0() ? PMD_SECT_NG : 0)
+#define PTE_MAYBE_NG           (arm64_kernel_use_ng_mappings() ? PTE_NG : 0)
+#define PMD_MAYBE_NG           (arm64_kernel_use_ng_mappings() ? PMD_SECT_NG : 0)
 
 #define PROT_DEFAULT           (_PROT_DEFAULT | PTE_MAYBE_NG)
 #define PROT_SECT_DEFAULT      (_PROT_SECT_DEFAULT | PMD_MAYBE_NG)
index b3ef061..d88e56b 100644 (file)
@@ -1 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_ARM64_XEN_PAGE_COHERENT_H
+#define _ASM_ARM64_XEN_PAGE_COHERENT_H
+
+#include <linux/dma-mapping.h>
+#include <asm/page.h>
 #include <xen/arm/page-coherent.h>
+
+static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
+               dma_addr_t *dma_handle, gfp_t flags, unsigned long attrs)
+{
+       return dma_direct_alloc(hwdev, size, dma_handle, flags, attrs);
+}
+
+static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
+               void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs)
+{
+       dma_direct_free(hwdev, size, cpu_addr, dma_handle, attrs);
+}
+
+static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
+               dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+       unsigned long pfn = PFN_DOWN(handle);
+
+       if (pfn_valid(pfn))
+               dma_direct_sync_single_for_cpu(hwdev, handle, size, dir);
+       else
+               __xen_dma_sync_single_for_cpu(hwdev, handle, size, dir);
+}
+
+static inline void xen_dma_sync_single_for_device(struct device *hwdev,
+               dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+       unsigned long pfn = PFN_DOWN(handle);
+       if (pfn_valid(pfn))
+               dma_direct_sync_single_for_device(hwdev, handle, size, dir);
+       else
+               __xen_dma_sync_single_for_device(hwdev, handle, size, dir);
+}
+
+static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
+            dma_addr_t dev_addr, unsigned long offset, size_t size,
+            enum dma_data_direction dir, unsigned long attrs)
+{
+       unsigned long page_pfn = page_to_xen_pfn(page);
+       unsigned long dev_pfn = XEN_PFN_DOWN(dev_addr);
+       unsigned long compound_pages =
+               (1<<compound_order(page)) * XEN_PFN_PER_PAGE;
+       bool local = (page_pfn <= dev_pfn) &&
+               (dev_pfn - page_pfn < compound_pages);
+
+       if (local)
+               dma_direct_map_page(hwdev, page, offset, size, dir, attrs);
+       else
+               __xen_dma_map_page(hwdev, page, dev_addr, offset, size, dir, attrs);
+}
+
+static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
+               size_t size, enum dma_data_direction dir, unsigned long attrs)
+{
+       unsigned long pfn = PFN_DOWN(handle);
+       /*
+        * Dom0 is mapped 1:1, while the Linux page can be spanned accross
+        * multiple Xen page, it's not possible to have a mix of local and
+        * foreign Xen page. Dom0 is mapped 1:1, so calling pfn_valid on a
+        * foreign mfn will always return false. If the page is local we can
+        * safely call the native dma_ops function, otherwise we call the xen
+        * specific function.
+        */
+       if (pfn_valid(pfn))
+               dma_direct_unmap_page(hwdev, handle, size, dir, attrs);
+       else
+               __xen_dma_unmap_page(hwdev, handle, size, dir, attrs);
+}
+
+#endif /* _ASM_ARM64_XEN_PAGE_COHERENT_H */
index 09ac548..9950bb0 100644 (file)
@@ -553,7 +553,7 @@ static const struct midr_range arm64_repeat_tlbi_cpus[] = {
 #endif
 
 #ifdef CONFIG_CAVIUM_ERRATUM_27456
-static const struct midr_range cavium_erratum_27456_cpus[] = {
+const struct midr_range cavium_erratum_27456_cpus[] = {
        /* Cavium ThunderX, T88 pass 1.x - 2.1 */
        MIDR_RANGE(MIDR_THUNDERX, 0, 0, 1, 1),
        /* Cavium ThunderX, T81 pass 1.0 */
index 4f27239..f6d84e2 100644 (file)
@@ -983,7 +983,7 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
 
        /* Useful for KASLR robustness */
        if (IS_ENABLED(CONFIG_RANDOMIZE_BASE))
-               return true;
+               return kaslr_offset() > 0;
 
        /* Don't force KPTI for CPUs that are not vulnerable */
        if (is_midr_in_range_list(read_cpuid_id(), kpti_safe_list))
@@ -1003,7 +1003,12 @@ kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused)
        static bool kpti_applied = false;
        int cpu = smp_processor_id();
 
-       if (kpti_applied)
+       /*
+        * We don't need to rewrite the page-tables if either we've done
+        * it already or we have KASLR enabled and therefore have not
+        * created any global mappings at all.
+        */
+       if (kpti_applied || kaslr_offset() > 0)
                return;
 
        remap_fn = (void *)__pa_symbol(idmap_kpti_install_ng_mappings);
index c721367..15d79a8 100644 (file)
@@ -475,6 +475,7 @@ ENDPROC(__primary_switched)
 
 ENTRY(kimage_vaddr)
        .quad           _text - TEXT_OFFSET
+EXPORT_SYMBOL(kimage_vaddr)
 
 /*
  * If we're fortunate enough to boot at EL2, ensure that the world is
index 29cdc99..9859e11 100644 (file)
@@ -299,8 +299,10 @@ int swsusp_arch_suspend(void)
                dcache_clean_range(__idmap_text_start, __idmap_text_end);
 
                /* Clean kvm setup code to PoC? */
-               if (el2_reset_needed())
+               if (el2_reset_needed()) {
                        dcache_clean_range(__hyp_idmap_text_start, __hyp_idmap_text_end);
+                       dcache_clean_range(__hyp_text_start, __hyp_text_end);
+               }
 
                /* make the crash dump kernel image protected again */
                crash_post_resume();
index e1261fb..17f325b 100644 (file)
@@ -28,6 +28,8 @@
 #include <asm/virt.h>
 
        .text
+       .pushsection    .hyp.text, "ax"
+
        .align 11
 
 ENTRY(__hyp_stub_vectors)
index f0e6ab8..b09b6f7 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/sched.h>
 #include <linux/types.h>
 
+#include <asm/cacheflush.h>
 #include <asm/fixmap.h>
 #include <asm/kernel-pgtable.h>
 #include <asm/memory.h>
@@ -43,7 +44,7 @@ static __init u64 get_kaslr_seed(void *fdt)
        return ret;
 }
 
-static __init const u8 *get_cmdline(void *fdt)
+static __init const u8 *kaslr_get_cmdline(void *fdt)
 {
        static __initconst const u8 default_cmdline[] = CONFIG_CMDLINE;
 
@@ -87,6 +88,7 @@ u64 __init kaslr_early_init(u64 dt_phys)
         * we end up running with module randomization disabled.
         */
        module_alloc_base = (u64)_etext - MODULES_VSIZE;
+       __flush_dcache_area(&module_alloc_base, sizeof(module_alloc_base));
 
        /*
         * Try to map the FDT early. If this fails, we simply bail,
@@ -109,7 +111,7 @@ u64 __init kaslr_early_init(u64 dt_phys)
         * Check if 'nokaslr' appears on the command line, and
         * return 0 if that is the case.
         */
-       cmdline = get_cmdline(fdt);
+       cmdline = kaslr_get_cmdline(fdt);
        str = strstr(cmdline, "nokaslr");
        if (str == cmdline || (str > cmdline && *(str - 1) == ' '))
                return 0;
@@ -169,5 +171,8 @@ u64 __init kaslr_early_init(u64 dt_phys)
        module_alloc_base += (module_range * (seed & ((1 << 21) - 1))) >> 21;
        module_alloc_base &= PAGE_MASK;
 
+       __flush_dcache_area(&module_alloc_base, sizeof(module_alloc_base));
+       __flush_dcache_area(&memstart_offset_seed, sizeof(memstart_offset_seed));
+
        return offset;
 }
index 10e3386..5887133 100644 (file)
@@ -87,7 +87,9 @@ static int setup_dtb(struct kimage *image,
 
        /* add kaslr-seed */
        ret = fdt_delprop(dtb, off, FDT_PROP_KASLR_SEED);
-       if (ret && (ret != -FDT_ERR_NOTFOUND))
+       if  (ret == -FDT_ERR_NOTFOUND)
+               ret = 0;
+       else if (ret)
                goto out;
 
        if (rng_is_initialized()) {
@@ -118,10 +120,12 @@ static int create_dtb(struct kimage *image,
 {
        void *buf;
        size_t buf_size;
+       size_t cmdline_len;
        int ret;
 
+       cmdline_len = cmdline ? strlen(cmdline) : 0;
        buf_size = fdt_totalsize(initial_boot_params)
-                       + strlen(cmdline) + DTB_EXTRA_SPACE;
+                       + cmdline_len + DTB_EXTRA_SPACE;
 
        for (;;) {
                buf = vmalloc(buf_size);
index 2a5b338..f17afb9 100644 (file)
@@ -478,13 +478,13 @@ bool arch_within_kprobe_blacklist(unsigned long addr)
            addr < (unsigned long)__entry_text_end) ||
            (addr >= (unsigned long)__idmap_text_start &&
            addr < (unsigned long)__idmap_text_end) ||
+           (addr >= (unsigned long)__hyp_text_start &&
+           addr < (unsigned long)__hyp_text_end) ||
            !!search_exception_tables(addr))
                return true;
 
        if (!is_kernel_in_hyp_mode()) {
-               if ((addr >= (unsigned long)__hyp_text_start &&
-                   addr < (unsigned long)__hyp_text_end) ||
-                   (addr >= (unsigned long)__hyp_idmap_text_start &&
+               if ((addr >= (unsigned long)__hyp_idmap_text_start &&
                    addr < (unsigned long)__hyp_idmap_text_end))
                        return true;
        }
index 4b0e123..d09ec76 100644 (file)
@@ -313,7 +313,6 @@ void __init setup_arch(char **cmdline_p)
        arm64_memblock_init();
 
        paging_init();
-       efi_apply_persistent_mem_reservations();
 
        acpi_table_upgrade();
 
index b0b1478..421ebf6 100644 (file)
@@ -23,6 +23,7 @@
 #include <kvm/arm_psci.h>
 
 #include <asm/cpufeature.h>
+#include <asm/kprobes.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_host.h>
@@ -107,6 +108,7 @@ static void activate_traps_vhe(struct kvm_vcpu *vcpu)
 
        write_sysreg(kvm_get_hyp_vector(), vbar_el1);
 }
+NOKPROBE_SYMBOL(activate_traps_vhe);
 
 static void __hyp_text __activate_traps_nvhe(struct kvm_vcpu *vcpu)
 {
@@ -154,6 +156,7 @@ static void deactivate_traps_vhe(void)
        write_sysreg(CPACR_EL1_DEFAULT, cpacr_el1);
        write_sysreg(vectors, vbar_el1);
 }
+NOKPROBE_SYMBOL(deactivate_traps_vhe);
 
 static void __hyp_text __deactivate_traps_nvhe(void)
 {
@@ -513,6 +516,7 @@ int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
 
        return exit_code;
 }
+NOKPROBE_SYMBOL(kvm_vcpu_run_vhe);
 
 /* Switch to the guest for legacy non-VHE systems */
 int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
@@ -620,6 +624,7 @@ static void __hyp_call_panic_vhe(u64 spsr, u64 elr, u64 par,
              read_sysreg_el2(esr),   read_sysreg_el2(far),
              read_sysreg(hpfar_el2), par, vcpu);
 }
+NOKPROBE_SYMBOL(__hyp_call_panic_vhe);
 
 void __hyp_text __noreturn hyp_panic(struct kvm_cpu_context *host_ctxt)
 {
index 68d6f7c..b426e2c 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/compiler.h>
 #include <linux/kvm_host.h>
 
+#include <asm/kprobes.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_hyp.h>
@@ -98,12 +99,14 @@ void sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt)
 {
        __sysreg_save_common_state(ctxt);
 }
+NOKPROBE_SYMBOL(sysreg_save_host_state_vhe);
 
 void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt)
 {
        __sysreg_save_common_state(ctxt);
        __sysreg_save_el2_return_state(ctxt);
 }
+NOKPROBE_SYMBOL(sysreg_save_guest_state_vhe);
 
 static void __hyp_text __sysreg_restore_common_state(struct kvm_cpu_context *ctxt)
 {
@@ -188,12 +191,14 @@ void sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt)
 {
        __sysreg_restore_common_state(ctxt);
 }
+NOKPROBE_SYMBOL(sysreg_restore_host_state_vhe);
 
 void sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt)
 {
        __sysreg_restore_common_state(ctxt);
        __sysreg_restore_el2_return_state(ctxt);
 }
+NOKPROBE_SYMBOL(sysreg_restore_guest_state_vhe);
 
 void __hyp_text __sysreg32_save_state(struct kvm_vcpu *vcpu)
 {
index b72a3dd..f16a5f8 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/kvm_arm.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_coproc.h>
+#include <asm/kvm_emulate.h>
 #include <asm/kvm_mmu.h>
 
 /* Maximum phys_shift supported for any VM on this host */
@@ -105,16 +106,33 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
  * This function finds the right table above and sets the registers on
  * the virtual CPU struct to their architecturally defined reset
  * values.
+ *
+ * Note: This function can be called from two paths: The KVM_ARM_VCPU_INIT
+ * ioctl or as part of handling a request issued by another VCPU in the PSCI
+ * handling code.  In the first case, the VCPU will not be loaded, and in the
+ * second case the VCPU will be loaded.  Because this function operates purely
+ * on the memory-backed valus of system registers, we want to do a full put if
+ * we were loaded (handling a request) and load the values back at the end of
+ * the function.  Otherwise we leave the state alone.  In both cases, we
+ * disable preemption around the vcpu reset as we would otherwise race with
+ * preempt notifiers which also call put/load.
  */
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
 {
        const struct kvm_regs *cpu_reset;
+       int ret = -EINVAL;
+       bool loaded;
+
+       preempt_disable();
+       loaded = (vcpu->cpu != -1);
+       if (loaded)
+               kvm_arch_vcpu_put(vcpu);
 
        switch (vcpu->arch.target) {
        default:
                if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) {
                        if (!cpu_has_32bit_el1())
-                               return -EINVAL;
+                               goto out;
                        cpu_reset = &default_regs_reset32;
                } else {
                        cpu_reset = &default_regs_reset;
@@ -129,6 +147,29 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
        /* Reset system registers */
        kvm_reset_sys_regs(vcpu);
 
+       /*
+        * Additional reset state handling that PSCI may have imposed on us.
+        * Must be done after all the sys_reg reset.
+        */
+       if (vcpu->arch.reset_state.reset) {
+               unsigned long target_pc = vcpu->arch.reset_state.pc;
+
+               /* Gracefully handle Thumb2 entry point */
+               if (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) {
+                       target_pc &= ~1UL;
+                       vcpu_set_thumb(vcpu);
+               }
+
+               /* Propagate caller endianness */
+               if (vcpu->arch.reset_state.be)
+                       kvm_vcpu_set_be(vcpu);
+
+               *vcpu_pc(vcpu) = target_pc;
+               vcpu_set_reg(vcpu, 0, vcpu->arch.reset_state.r0);
+
+               vcpu->arch.reset_state.reset = false;
+       }
+
        /* Reset PMU */
        kvm_pmu_vcpu_reset(vcpu);
 
@@ -137,7 +178,12 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
                vcpu->arch.workaround_flags |= VCPU_WORKAROUND_2_FLAG;
 
        /* Reset timer */
-       return kvm_timer_vcpu_reset(vcpu);
+       ret = kvm_timer_vcpu_reset(vcpu);
+out:
+       if (loaded)
+               kvm_arch_vcpu_load(vcpu, smp_processor_id());
+       preempt_enable();
+       return ret;
 }
 
 void kvm_set_ipa_limit(void)
index e3e3722..c936aa4 100644 (file)
@@ -314,12 +314,29 @@ static bool trap_raz_wi(struct kvm_vcpu *vcpu,
                return read_zero(vcpu, p);
 }
 
-static bool trap_undef(struct kvm_vcpu *vcpu,
-                      struct sys_reg_params *p,
-                      const struct sys_reg_desc *r)
+/*
+ * ARMv8.1 mandates at least a trivial LORegion implementation, where all the
+ * RW registers are RES0 (which we can implement as RAZ/WI). On an ARMv8.0
+ * system, these registers should UNDEF. LORID_EL1 being a RO register, we
+ * treat it separately.
+ */
+static bool trap_loregion(struct kvm_vcpu *vcpu,
+                         struct sys_reg_params *p,
+                         const struct sys_reg_desc *r)
 {
-       kvm_inject_undefined(vcpu);
-       return false;
+       u64 val = read_sanitised_ftr_reg(SYS_ID_AA64MMFR1_EL1);
+       u32 sr = sys_reg((u32)r->Op0, (u32)r->Op1,
+                        (u32)r->CRn, (u32)r->CRm, (u32)r->Op2);
+
+       if (!(val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))) {
+               kvm_inject_undefined(vcpu);
+               return false;
+       }
+
+       if (p->is_write && sr == SYS_LORID_EL1)
+               return write_to_read_only(vcpu, p, r);
+
+       return trap_raz_wi(vcpu, p, r);
 }
 
 static bool trap_oslsr_el1(struct kvm_vcpu *vcpu,
@@ -1048,11 +1065,6 @@ static u64 read_id_reg(struct sys_reg_desc const *r, bool raz)
                if (val & ptrauth_mask)
                        kvm_debug("ptrauth unsupported for guests, suppressing\n");
                val &= ~ptrauth_mask;
-       } else if (id == SYS_ID_AA64MMFR1_EL1) {
-               if (val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))
-                       kvm_debug("LORegions unsupported for guests, suppressing\n");
-
-               val &= ~(0xfUL << ID_AA64MMFR1_LOR_SHIFT);
        }
 
        return val;
@@ -1338,11 +1350,11 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_MAIR_EL1), access_vm_reg, reset_unknown, MAIR_EL1 },
        { SYS_DESC(SYS_AMAIR_EL1), access_vm_reg, reset_amair_el1, AMAIR_EL1 },
 
-       { SYS_DESC(SYS_LORSA_EL1), trap_undef },
-       { SYS_DESC(SYS_LOREA_EL1), trap_undef },
-       { SYS_DESC(SYS_LORN_EL1), trap_undef },
-       { SYS_DESC(SYS_LORC_EL1), trap_undef },
-       { SYS_DESC(SYS_LORID_EL1), trap_undef },
+       { SYS_DESC(SYS_LORSA_EL1), trap_loregion },
+       { SYS_DESC(SYS_LOREA_EL1), trap_loregion },
+       { SYS_DESC(SYS_LORN_EL1), trap_loregion },
+       { SYS_DESC(SYS_LORC_EL1), trap_loregion },
+       { SYS_DESC(SYS_LORID_EL1), trap_loregion },
 
        { SYS_DESC(SYS_VBAR_EL1), NULL, reset_val, VBAR_EL1, 0 },
        { SYS_DESC(SYS_DISR_EL1), NULL, reset_val, DISR_EL1, 0 },
@@ -2596,7 +2608,9 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
        table = get_target_table(vcpu->arch.target, true, &num);
        reset_sys_reg_descs(vcpu, table, num);
 
-       for (num = 1; num < NR_SYS_REGS; num++)
-               if (__vcpu_sys_reg(vcpu, num) == 0x4242424242424242)
-                       panic("Didn't reset __vcpu_sys_reg(%zi)", num);
+       for (num = 1; num < NR_SYS_REGS; num++) {
+               if (WARN(__vcpu_sys_reg(vcpu, num) == 0x4242424242424242,
+                        "Didn't reset __vcpu_sys_reg(%zi)\n", num))
+                       break;
+       }
 }
index fb09084..78c0a72 100644 (file)
@@ -466,9 +466,7 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
        __iommu_setup_dma_ops(dev, dma_base, size, iommu);
 
 #ifdef CONFIG_XEN
-       if (xen_initial_domain()) {
-               dev->archdata.dev_dma_ops = dev->dma_ops;
+       if (xen_initial_domain())
                dev->dma_ops = xen_dma_ops;
-       }
 #endif
 }
index fcb1f2a..99bb8fa 100644 (file)
@@ -286,74 +286,73 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level,
 
 }
 
-static void walk_pte(struct pg_state *st, pmd_t *pmdp, unsigned long start)
+static void walk_pte(struct pg_state *st, pmd_t *pmdp, unsigned long start,
+                    unsigned long end)
 {
-       pte_t *ptep = pte_offset_kernel(pmdp, 0UL);
-       unsigned long addr;
-       unsigned i;
+       unsigned long addr = start;
+       pte_t *ptep = pte_offset_kernel(pmdp, start);
 
-       for (i = 0; i < PTRS_PER_PTE; i++, ptep++) {
-               addr = start + i * PAGE_SIZE;
+       do {
                note_page(st, addr, 4, READ_ONCE(pte_val(*ptep)));
-       }
+       } while (ptep++, addr += PAGE_SIZE, addr != end);
 }
 
-static void walk_pmd(struct pg_state *st, pud_t *pudp, unsigned long start)
+static void walk_pmd(struct pg_state *st, pud_t *pudp, unsigned long start,
+                    unsigned long end)
 {
-       pmd_t *pmdp = pmd_offset(pudp, 0UL);
-       unsigned long addr;
-       unsigned i;
+       unsigned long next, addr = start;
+       pmd_t *pmdp = pmd_offset(pudp, start);
 
-       for (i = 0; i < PTRS_PER_PMD; i++, pmdp++) {
+       do {
                pmd_t pmd = READ_ONCE(*pmdp);
+               next = pmd_addr_end(addr, end);
 
-               addr = start + i * PMD_SIZE;
                if (pmd_none(pmd) || pmd_sect(pmd)) {
                        note_page(st, addr, 3, pmd_val(pmd));
                } else {
                        BUG_ON(pmd_bad(pmd));
-                       walk_pte(st, pmdp, addr);
+                       walk_pte(st, pmdp, addr, next);
                }
-       }
+       } while (pmdp++, addr = next, addr != end);
 }
 
-static void walk_pud(struct pg_state *st, pgd_t *pgdp, unsigned long start)
+static void walk_pud(struct pg_state *st, pgd_t *pgdp, unsigned long start,
+                    unsigned long end)
 {
-       pud_t *pudp = pud_offset(pgdp, 0UL);
-       unsigned long addr;
-       unsigned i;
+       unsigned long next, addr = start;
+       pud_t *pudp = pud_offset(pgdp, start);
 
-       for (i = 0; i < PTRS_PER_PUD; i++, pudp++) {
+       do {
                pud_t pud = READ_ONCE(*pudp);
+               next = pud_addr_end(addr, end);
 
-               addr = start + i * PUD_SIZE;
                if (pud_none(pud) || pud_sect(pud)) {
                        note_page(st, addr, 2, pud_val(pud));
                } else {
                        BUG_ON(pud_bad(pud));
-                       walk_pmd(st, pudp, addr);
+                       walk_pmd(st, pudp, addr, next);
                }
-       }
+       } while (pudp++, addr = next, addr != end);
 }
 
 static void walk_pgd(struct pg_state *st, struct mm_struct *mm,
                     unsigned long start)
 {
-       pgd_t *pgdp = pgd_offset(mm, 0UL);
-       unsigned i;
-       unsigned long addr;
+       unsigned long end = (start < TASK_SIZE_64) ? TASK_SIZE_64 : 0;
+       unsigned long next, addr = start;
+       pgd_t *pgdp = pgd_offset(mm, start);
 
-       for (i = 0; i < PTRS_PER_PGD; i++, pgdp++) {
+       do {
                pgd_t pgd = READ_ONCE(*pgdp);
+               next = pgd_addr_end(addr, end);
 
-               addr = start + i * PGDIR_SIZE;
                if (pgd_none(pgd)) {
                        note_page(st, addr, 1, pgd_val(pgd));
                } else {
                        BUG_ON(pgd_bad(pgd));
-                       walk_pud(st, pgdp, addr);
+                       walk_pud(st, pgdp, addr, next);
                }
-       }
+       } while (pgdp++, addr = next, addr != end);
 }
 
 void ptdump_walk_pgd(struct seq_file *m, struct ptdump_info *info)
index 30695a8..5c9073b 100644 (file)
@@ -33,7 +33,11 @@ void sync_icache_aliases(void *kaddr, unsigned long len)
                __clean_dcache_area_pou(kaddr, len);
                __flush_icache_all();
        } else {
-               flush_icache_range(addr, addr + len);
+               /*
+                * Don't issue kick_all_cpus_sync() after I-cache invalidation
+                * for user mappings.
+                */
+               __flush_icache_range(addr, addr + len);
        }
 }
 
index 33a2c94..63b4a17 100644 (file)
@@ -30,6 +30,7 @@ generic-y += pgalloc.h
 generic-y += preempt.h
 generic-y += segment.h
 generic-y += serial.h
+generic-y += shmparam.h
 generic-y += tlbflush.h
 generic-y += topology.h
 generic-y += trace_clock.h
index ecae6b3..c1dfa9c 100644 (file)
@@ -15,6 +15,31 @@ extern void iounmap(void *addr);
 extern int remap_area_pages(unsigned long address, phys_addr_t phys_addr,
                size_t size, unsigned long flags);
 
+/*
+ * I/O memory access primitives. Reads are ordered relative to any
+ * following Normal memory access. Writes are ordered relative to any prior
+ * Normal memory access.
+ *
+ * For CACHEV1 (807, 810), store instruction could fast retire, so we need
+ * another mb() to prevent st fast retire.
+ *
+ * For CACHEV2 (860), store instruction with PAGE_ATTR_NO_BUFFERABLE won't
+ * fast retire.
+ */
+#define readb(c)               ({ u8  __v = readb_relaxed(c); rmb(); __v; })
+#define readw(c)               ({ u16 __v = readw_relaxed(c); rmb(); __v; })
+#define readl(c)               ({ u32 __v = readl_relaxed(c); rmb(); __v; })
+
+#ifdef CONFIG_CPU_HAS_CACHEV2
+#define writeb(v,c)            ({ wmb(); writeb_relaxed((v),(c)); })
+#define writew(v,c)            ({ wmb(); writew_relaxed((v),(c)); })
+#define writel(v,c)            ({ wmb(); writel_relaxed((v),(c)); })
+#else
+#define writeb(v,c)            ({ wmb(); writeb_relaxed((v),(c)); mb(); })
+#define writew(v,c)            ({ wmb(); writew_relaxed((v),(c)); mb(); })
+#define writel(v,c)            ({ wmb(); writel_relaxed((v),(c)); mb(); })
+#endif
+
 #define ioremap_nocache(phy, sz)       ioremap(phy, sz)
 #define ioremap_wc ioremap_nocache
 #define ioremap_wt ioremap_nocache
index bf4f4a0..d213bb4 100644 (file)
@@ -24,41 +24,34 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
 
 extern void pgd_init(unsigned long *p);
 
-static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
-                                       unsigned long address)
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
 {
        pte_t *pte;
-       unsigned long *kaddr, i;
+       unsigned long i;
 
-       pte = (pte_t *) __get_free_pages(GFP_KERNEL | __GFP_RETRY_MAYFAIL,
-                                        PTE_ORDER);
-       kaddr = (unsigned long *)pte;
-       if (address & 0x80000000)
-               for (i = 0; i < (PAGE_SIZE/4); i++)
-                       *(kaddr + i) = 0x1;
-       else
-               clear_page(kaddr);
+       pte = (pte_t *) __get_free_page(GFP_KERNEL);
+       if (!pte)
+               return NULL;
+
+       for (i = 0; i < PAGE_SIZE/sizeof(pte_t); i++)
+               (pte + i)->pte_low = _PAGE_GLOBAL;
 
        return pte;
 }
 
-static inline struct page *pte_alloc_one(struct mm_struct *mm,
-                                               unsigned long address)
+static inline struct page *pte_alloc_one(struct mm_struct *mm)
 {
        struct page *pte;
-       unsigned long *kaddr, i;
-
-       pte = alloc_pages(GFP_KERNEL | __GFP_RETRY_MAYFAIL, PTE_ORDER);
-       if (pte) {
-               kaddr = kmap_atomic(pte);
-               if (address & 0x80000000) {
-                       for (i = 0; i < (PAGE_SIZE/4); i++)
-                               *(kaddr + i) = 0x1;
-               } else
-                       clear_page(kaddr);
-               kunmap_atomic(kaddr);
-               pgtable_page_ctor(pte);
+
+       pte = alloc_pages(GFP_KERNEL | __GFP_ZERO, 0);
+       if (!pte)
+               return NULL;
+
+       if (!pgtable_page_ctor(pte)) {
+               __free_page(pte);
+               return NULL;
        }
+
        return pte;
 }
 
index edfcbb2..dcea277 100644 (file)
@@ -45,8 +45,8 @@
        ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset_t(address))
 #define pmd_page(pmd)  (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
 #define pte_clear(mm, addr, ptep)      set_pte((ptep), \
-                       (((unsigned int)addr&0x80000000)?__pte(1):__pte(0)))
-#define pte_none(pte)  (!(pte_val(pte)&0xfffffffe))
+       (((unsigned int) addr & PAGE_OFFSET) ? __pte(_PAGE_GLOBAL) : __pte(0)))
+#define pte_none(pte)          (!(pte_val(pte) & ~_PAGE_GLOBAL))
 #define pte_present(pte)       (pte_val(pte) & _PAGE_PRESENT)
 #define pte_pfn(x)     ((unsigned long)((x).pte_low >> PAGE_SHIFT))
 #define pfn_pte(pfn, prot) __pte(((unsigned long long)(pfn) << PAGE_SHIFT) \
@@ -241,6 +241,11 @@ static inline pte_t pte_mkyoung(pte_t pte)
 
 #define pgd_index(address)     ((address) >> PGDIR_SHIFT)
 
+#define __HAVE_PHYS_MEM_ACCESS_PROT
+struct file;
+extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+                                    unsigned long size, pgprot_t vma_prot);
+
 /*
  * Macro to make mark a page protection value as "uncacheable".  Note
  * that "protection" is really a misnomer here as the protection value
index 8f45481..21e0bd5 100644 (file)
@@ -49,7 +49,7 @@ struct thread_struct {
 };
 
 #define INIT_THREAD  { \
-       .ksp = (unsigned long) init_thread_union.stack + THREAD_SIZE, \
+       .ksp = sizeof(init_stack) + (unsigned long) &init_stack, \
        .sr = DEFAULT_PSR_VALUE, \
 }
 
@@ -95,7 +95,7 @@ unsigned long get_wchan(struct task_struct *p);
 #define KSTK_ESP(tsk)          (task_pt_regs(tsk)->usp)
 
 #define task_pt_regs(p) \
-       ((struct pt_regs *)(THREAD_SIZE + p->stack) - 1)
+       ((struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1)
 
 #define cpu_relax() barrier()
 
index 659253e..d67f977 100644 (file)
@@ -38,7 +38,11 @@ void show_stack(struct task_struct *task, unsigned long *stack)
                if (task)
                        stack = (unsigned long *)thread_saved_fp(task);
                else
+#ifdef CONFIG_STACKTRACE
+                       asm volatile("mov %0, r8\n":"=r"(stack)::"memory");
+#else
                        stack = (unsigned long *)&stack;
+#endif
        }
 
        show_trace(stack);
index 65abab0..b5ad7d9 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/spinlock.h>
 #include <asm/pgtable.h>
 
-#if defined(__CSKYABIV2__)
+#ifdef CONFIG_CPU_CK810
 #define IS_BSR32(hi16, lo16)           (((hi16) & 0xFC00) == 0xE000)
 #define IS_JSRI32(hi16, lo16)          ((hi16) == 0xEAE0)
 
        *(uint16_t *)(addr) = 0xE8Fa;           \
        *((uint16_t *)(addr) + 1) = 0x0000;     \
 } while (0)
+
+static void jsri_2_lrw_jsr(uint32_t *location)
+{
+       uint16_t *location_tmp = (uint16_t *)location;
+
+       if (IS_BSR32(*location_tmp, *(location_tmp + 1)))
+               return;
+
+       if (IS_JSRI32(*location_tmp, *(location_tmp + 1))) {
+               /* jsri 0x...  --> lrw r26, 0x... */
+               CHANGE_JSRI_TO_LRW(location);
+               /* lsli r0, r0 --> jsr r26 */
+               SET_JSR32_R26(location + 1);
+       }
+}
+#else
+static void inline jsri_2_lrw_jsr(uint32_t *location)
+{
+       return;
+}
 #endif
 
 int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
@@ -35,9 +55,6 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
        Elf32_Sym       *sym;
        uint32_t        *location;
        short           *temp;
-#if defined(__CSKYABIV2__)
-       uint16_t        *location_tmp;
-#endif
 
        for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
                /* This is where to make the change */
@@ -59,18 +76,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
                case R_CSKY_PCRELJSR_IMM11BY2:
                        break;
                case R_CSKY_PCRELJSR_IMM26BY2:
-#if defined(__CSKYABIV2__)
-                       location_tmp = (uint16_t *)location;
-                       if (IS_BSR32(*location_tmp, *(location_tmp + 1)))
-                               break;
-
-                       if (IS_JSRI32(*location_tmp, *(location_tmp + 1))) {
-                               /* jsri 0x...  --> lrw r26, 0x... */
-                               CHANGE_JSRI_TO_LRW(location);
-                               /* lsli r0, r0 --> jsr r26 */
-                               SET_JSR32_R26(location + 1);
-                       }
-#endif
+                       jsri_2_lrw_jsr(location);
                        break;
                case R_CSKY_ADDR_HI16:
                        temp = ((short  *)location) + 1;
index 57f1afe..f2f12ff 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/ptrace.h>
 #include <linux/regset.h>
 #include <linux/sched.h>
+#include <linux/sched/task_stack.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
 #include <linux/uaccess.h>
@@ -159,7 +160,7 @@ static int fpr_set(struct task_struct *target,
 static const struct user_regset csky_regsets[] = {
        [REGSET_GPR] = {
                .core_note_type = NT_PRSTATUS,
-               .n = ELF_NGREG,
+               .n = sizeof(struct pt_regs) / sizeof(u32),
                .size = sizeof(u32),
                .align = sizeof(u32),
                .get = &gpr_get,
index ddc4dd7..b07a534 100644 (file)
@@ -160,7 +160,8 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
 {
        unsigned long mask = 1 << cpu;
 
-       secondary_stack = (unsigned int)tidle->stack + THREAD_SIZE - 8;
+       secondary_stack =
+               (unsigned int) task_stack_page(tidle) + THREAD_SIZE - 8;
        secondary_hint = mfcr("cr31");
        secondary_ccr  = mfcr("cr18");
 
index cb7c03e..8473b6b 100644 (file)
@@ -46,3 +46,17 @@ void iounmap(void __iomem *addr)
        vunmap((void *)((unsigned long)addr & PAGE_MASK));
 }
 EXPORT_SYMBOL(iounmap);
+
+pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+                             unsigned long size, pgprot_t vma_prot)
+{
+       if (!pfn_valid(pfn)) {
+               vma_prot.pgprot |= _PAGE_SO;
+               return pgprot_noncached(vma_prot);
+       } else if (file->f_flags & O_SYNC) {
+               return pgprot_noncached(vma_prot);
+       }
+
+       return vma_prot;
+}
+EXPORT_SYMBOL(phys_mem_access_prot);
index 4003ddc..f801f37 100644 (file)
@@ -37,8 +37,6 @@ libs-y        += arch/$(ARCH)/lib/
 
 boot := arch/h8300/boot
 
-archmrproper:
-
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
 
index cd400d3..961c1dc 100644 (file)
@@ -40,6 +40,7 @@ generic-y += preempt.h
 generic-y += scatterlist.h
 generic-y += sections.h
 generic-y += serial.h
+generic-y += shmparam.h
 generic-y += sizes.h
 generic-y += spinlock.h
 generic-y += timex.h
index 47c4da3..b25fd42 100644 (file)
@@ -30,6 +30,7 @@ generic-y += rwsem.h
 generic-y += sections.h
 generic-y += segment.h
 generic-y += serial.h
+generic-y += shmparam.h
 generic-y += sizes.h
 generic-y += topology.h
 generic-y += trace_clock.h
index 320d86f..171290f 100644 (file)
@@ -16,8 +16,6 @@ KBUILD_DEFCONFIG := generic_defconfig
 NM := $(CROSS_COMPILE)nm -B
 READELF := $(CROSS_COMPILE)readelf
 
-export AWK
-
 CHECKFLAGS     += -D__ia64=1 -D__ia64__=1 -D_LP64 -D__LP64__
 
 OBJCOPYFLAGS   := --strip-all
index 3804935..40712e4 100644 (file)
@@ -155,18 +155,22 @@ out:
 static int __init nfhd_init(void)
 {
        u32 blocks, bsize;
+       int ret;
        int i;
 
        nfhd_id = nf_get_id("XHDI");
        if (!nfhd_id)
                return -ENODEV;
 
-       major_num = register_blkdev(major_num, "nfhd");
-       if (major_num <= 0) {
+       ret = register_blkdev(major_num, "nfhd");
+       if (ret < 0) {
                pr_warn("nfhd: unable to get major number\n");
-               return major_num;
+               return ret;
        }
 
+       if (!major_num)
+               major_num = ret;
+
        for (i = NFHD_DEV_OFFSET; i < 24; i++) {
                if (nfhd_get_capacity(i, 0, &blocks, &bsize))
                        continue;
index 9f1dd26..95f8f63 100644 (file)
@@ -20,6 +20,7 @@ generic-y += mm-arch-hooks.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += sections.h
+generic-y += shmparam.h
 generic-y += spinlock.h
 generic-y += topology.h
 generic-y += trace_clock.h
index 9c7d1d2..791cc8d 100644 (file)
@@ -26,6 +26,7 @@ generic-y += parport.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += serial.h
+generic-y += shmparam.h
 generic-y += syscalls.h
 generic-y += topology.h
 generic-y += trace_clock.h
index 7872907..a84c24d 100644 (file)
@@ -1403,6 +1403,21 @@ config LOONGSON3_ENHANCEMENT
          please say 'N' here. If you want a high-performance kernel to run on
          new Loongson 3 machines only, please say 'Y' here.
 
+config CPU_LOONGSON3_WORKAROUNDS
+       bool "Old Loongson 3 LLSC Workarounds"
+       default y if SMP
+       depends on CPU_LOONGSON3
+       help
+         Loongson 3 processors have the llsc issues which require workarounds.
+         Without workarounds the system may hang unexpectedly.
+
+         Newer Loongson 3 will fix these issues and no workarounds are needed.
+         The workarounds have no significant side effect on them but may
+         decrease the performance of the system so this option should be
+         disabled unless the kernel is intended to be run on old systems.
+
+         If unsure, please say Y.
+
 config CPU_LOONGSON2E
        bool "Loongson 2E"
        depends on SYS_HAS_CPU_LOONGSON2E
@@ -3155,6 +3170,7 @@ config MIPS32_O32
 config MIPS32_N32
        bool "Kernel support for n32 binaries"
        depends on 64BIT
+       select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
        select COMPAT
        select MIPS32_COMPAT
        select SYSVIPC_COMPAT if SYSVIPC
index 6054d49..fe37735 100644 (file)
@@ -173,6 +173,31 @@ void __init plat_mem_setup(void)
        pm_power_off = bcm47xx_machine_halt;
 }
 
+#ifdef CONFIG_BCM47XX_BCMA
+static struct device * __init bcm47xx_setup_device(void)
+{
+       struct device *dev;
+       int err;
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return NULL;
+
+       err = dev_set_name(dev, "bcm47xx_soc");
+       if (err) {
+               pr_err("Failed to set SoC device name: %d\n", err);
+               kfree(dev);
+               return NULL;
+       }
+
+       err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
+       if (err)
+               pr_err("Failed to set SoC DMA mask: %d\n", err);
+
+       return dev;
+}
+#endif
+
 /*
  * This finishes bus initialization doing things that were not possible without
  * kmalloc. Make sure to call it late enough (after mm_init).
@@ -183,6 +208,10 @@ void __init bcm47xx_bus_setup(void)
        if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) {
                int err;
 
+               bcm47xx_bus.bcma.dev = bcm47xx_setup_device();
+               if (!bcm47xx_bus.bcma.dev)
+                       panic("Failed to setup SoC device\n");
+
                err = bcma_host_soc_init(&bcm47xx_bus.bcma);
                if (err)
                        panic("Failed to initialize BCMA bus (err %d)", err);
@@ -235,6 +264,8 @@ static int __init bcm47xx_register_bus_complete(void)
 #endif
 #ifdef CONFIG_BCM47XX_BCMA
        case BCM47XX_BUS_TYPE_BCMA:
+               if (device_register(bcm47xx_bus.bcma.dev))
+                       pr_err("Failed to register SoC device\n");
                bcma_bus_register(&bcm47xx_bus.bcma.bus);
                break;
 #endif
index 50cff3c..4f7b1fa 100644 (file)
@@ -76,7 +76,7 @@
        status = "okay";
 
        pinctrl-names = "default";
-       pinctrl-0 = <&pins_uart2>;
+       pinctrl-0 = <&pins_uart3>;
 };
 
 &uart4 {
                bias-disable;
        };
 
-       pins_uart2: uart2 {
-               function = "uart2";
-               groups = "uart2-data", "uart2-hwflow";
+       pins_uart3: uart3 {
+               function = "uart3";
+               groups = "uart3-data", "uart3-hwflow";
                bias-disable;
        };
 
index 6fb16fd..2beb78a 100644 (file)
                #dma-cells = <2>;
 
                interrupt-parent = <&intc>;
-               interrupts = <29>;
+               interrupts = <20>;
 
                clocks = <&cgu JZ4740_CLK_DMA>;
 
index 2152b7b..cc8dbea 100644 (file)
                interrupts = <0>;
        };
 
-       axi_i2c: i2c@10A00000 {
+       axi_i2c: i2c@10a00000 {
            compatible = "xlnx,xps-iic-2.00.a";
            interrupt-parent = <&axi_intc>;
            interrupts = <4>;
-           reg = < 0x10A00000 0x10000 >;
+           reg = < 0x10a00000 0x10000 >;
            clocks = <&ext>;
            xlnx,clk-freq = <0x5f5e100>;
            xlnx,family = "Artix7";
            #address-cells = <1>;
            #size-cells = <0>;
 
-           ad7420@4B {
+           ad7420@4b {
                compatible = "adi,adt7420";
-               reg = <0x4B>;
+               reg = <0x4b>;
            };
        } ;
 };
index 2c79ab5..8bf43c5 100644 (file)
@@ -98,7 +98,7 @@ static void octeon_kexec_smp_down(void *ignored)
        "       sync                                            \n"
        "       synci   ($0)                                    \n");
 
-       relocated_kexec_smp_wait(NULL);
+       kexec_reboot();
 }
 #endif
 
index 4e4ec77..6f981af 100644 (file)
@@ -66,6 +66,7 @@ CONFIG_SERIAL_8250_CONSOLE=y
 # CONFIG_SERIAL_8250_PCI is not set
 CONFIG_SERIAL_8250_NR_UARTS=1
 CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_AR933X=y
 CONFIG_SERIAL_AR933X_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
index 43fcd35..9409629 100644 (file)
@@ -58,6 +58,7 @@ static __inline__ void atomic_##op(int i, atomic_t * v)                             \
        if (kernel_uses_llsc) {                                               \
                int temp;                                                     \
                                                                              \
+               loongson_llsc_mb();                                           \
                __asm__ __volatile__(                                         \
                "       .set    push                                    \n"   \
                "       .set    "MIPS_ISA_LEVEL"                        \n"   \
@@ -85,6 +86,7 @@ static __inline__ int atomic_##op##_return_relaxed(int i, atomic_t * v)             \
        if (kernel_uses_llsc) {                                               \
                int temp;                                                     \
                                                                              \
+               loongson_llsc_mb();                                           \
                __asm__ __volatile__(                                         \
                "       .set    push                                    \n"   \
                "       .set    "MIPS_ISA_LEVEL"                        \n"   \
@@ -118,6 +120,7 @@ static __inline__ int atomic_fetch_##op##_relaxed(int i, atomic_t * v)            \
        if (kernel_uses_llsc) {                                               \
                int temp;                                                     \
                                                                              \
+               loongson_llsc_mb();                                           \
                __asm__ __volatile__(                                         \
                "       .set    push                                    \n"   \
                "       .set    "MIPS_ISA_LEVEL"                        \n"   \
@@ -256,6 +259,7 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v)                      \
        if (kernel_uses_llsc) {                                               \
                long temp;                                                    \
                                                                              \
+               loongson_llsc_mb();                                           \
                __asm__ __volatile__(                                         \
                "       .set    push                                    \n"   \
                "       .set    "MIPS_ISA_LEVEL"                        \n"   \
@@ -283,6 +287,7 @@ static __inline__ long atomic64_##op##_return_relaxed(long i, atomic64_t * v) \
        if (kernel_uses_llsc) {                                               \
                long temp;                                                    \
                                                                              \
+               loongson_llsc_mb();                                           \
                __asm__ __volatile__(                                         \
                "       .set    push                                    \n"   \
                "       .set    "MIPS_ISA_LEVEL"                        \n"   \
@@ -316,6 +321,7 @@ static __inline__ long atomic64_fetch_##op##_relaxed(long i, atomic64_t * v)  \
        if (kernel_uses_llsc) {                                               \
                long temp;                                                    \
                                                                              \
+               loongson_llsc_mb();                                           \
                __asm__ __volatile__(                                         \
                "       .set    push                                    \n"   \
                "       .set    "MIPS_ISA_LEVEL"                        \n"   \
index a5eb1bb..b7f6ac5 100644 (file)
 #define __smp_mb__before_atomic()      __smp_mb__before_llsc()
 #define __smp_mb__after_atomic()       smp_llsc_mb()
 
+/*
+ * Some Loongson 3 CPUs have a bug wherein execution of a memory access (load,
+ * store or pref) in between an ll & sc can cause the sc instruction to
+ * erroneously succeed, breaking atomicity. Whilst it's unusual to write code
+ * containing such sequences, this bug bites harder than we might otherwise
+ * expect due to reordering & speculation:
+ *
+ * 1) A memory access appearing prior to the ll in program order may actually
+ *    be executed after the ll - this is the reordering case.
+ *
+ *    In order to avoid this we need to place a memory barrier (ie. a sync
+ *    instruction) prior to every ll instruction, in between it & any earlier
+ *    memory access instructions. Many of these cases are already covered by
+ *    smp_mb__before_llsc() but for the remaining cases, typically ones in
+ *    which multiple CPUs may operate on a memory location but ordering is not
+ *    usually guaranteed, we use loongson_llsc_mb() below.
+ *
+ *    This reordering case is fixed by 3A R2 CPUs, ie. 3A2000 models and later.
+ *
+ * 2) If a conditional branch exists between an ll & sc with a target outside
+ *    of the ll-sc loop, for example an exit upon value mismatch in cmpxchg()
+ *    or similar, then misprediction of the branch may allow speculative
+ *    execution of memory accesses from outside of the ll-sc loop.
+ *
+ *    In order to avoid this we need a memory barrier (ie. a sync instruction)
+ *    at each affected branch target, for which we also use loongson_llsc_mb()
+ *    defined below.
+ *
+ *    This case affects all current Loongson 3 CPUs.
+ */
+#ifdef CONFIG_CPU_LOONGSON3_WORKAROUNDS /* Loongson-3's LLSC workaround */
+#define loongson_llsc_mb()     __asm__ __volatile__(__WEAK_LLSC_MB : : :"memory")
+#else
+#define loongson_llsc_mb()     do { } while (0)
+#endif
+
 #include <asm-generic/barrier.h>
 
 #endif /* __ASM_BARRIER_H */
index c467595..830c93a 100644 (file)
@@ -69,6 +69,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
                : "ir" (1UL << bit), GCC_OFF_SMALL_ASM() (*m));
 #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
        } else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
+               loongson_llsc_mb();
                do {
                        __asm__ __volatile__(
                        "       " __LL "%0, %1          # set_bit       \n"
@@ -79,6 +80,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
                } while (unlikely(!temp));
 #endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
        } else if (kernel_uses_llsc) {
+               loongson_llsc_mb();
                do {
                        __asm__ __volatile__(
                        "       .set    push                            \n"
@@ -123,6 +125,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
                : "ir" (~(1UL << bit)));
 #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
        } else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
+               loongson_llsc_mb();
                do {
                        __asm__ __volatile__(
                        "       " __LL "%0, %1          # clear_bit     \n"
@@ -133,6 +136,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
                } while (unlikely(!temp));
 #endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
        } else if (kernel_uses_llsc) {
+               loongson_llsc_mb();
                do {
                        __asm__ __volatile__(
                        "       .set    push                            \n"
@@ -193,6 +197,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
                unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
                unsigned long temp;
 
+               loongson_llsc_mb();
                do {
                        __asm__ __volatile__(
                        "       .set    push                            \n"
index c14d798..b83b039 100644 (file)
@@ -50,6 +50,7 @@
                  "i" (-EFAULT)                                         \
                : "memory");                                            \
        } else if (cpu_has_llsc) {                                      \
+               loongson_llsc_mb();                                     \
                __asm__ __volatile__(                                   \
                "       .set    push                            \n"     \
                "       .set    noat                            \n"     \
@@ -163,6 +164,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
                  "i" (-EFAULT)
                : "memory");
        } else if (cpu_has_llsc) {
+               loongson_llsc_mb();
                __asm__ __volatile__(
                "# futex_atomic_cmpxchg_inatomic                        \n"
                "       .set    push                                    \n"
@@ -192,6 +194,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
                : GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
                  "i" (-EFAULT)
                : "memory");
+               loongson_llsc_mb();
        } else
                return -ENOSYS;
 
index c6b63a4..6dd8ad2 100644 (file)
@@ -18,8 +18,6 @@
 #define INT_NUM_EXTRA_START            (INT_NUM_IM4_IRL0 + 32)
 #define INT_NUM_IM_OFFSET              (INT_NUM_IM1_IRL0 - INT_NUM_IM0_IRL0)
 
-#define MIPS_CPU_TIMER_IRQ                     7
-
 #define MAX_IM                 5
 
 #endif /* _FALCON_IRQ__ */
index 1410763..0b42421 100644 (file)
@@ -19,8 +19,6 @@
 
 #define LTQ_DMA_CH0_INT                (INT_NUM_IM2_IRL0)
 
-#define MIPS_CPU_TIMER_IRQ     7
-
 #define MAX_IM                 5
 
 #endif
index 57933fc..910851c 100644 (file)
@@ -228,6 +228,7 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
                        : [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp)
                        : [global] "r" (page_global));
                } else if (kernel_uses_llsc) {
+                       loongson_llsc_mb();
                        __asm__ __volatile__ (
                        "       .set    push                            \n"
                        "       .set    "MIPS_ISA_ARCH_LEVEL"           \n"
@@ -242,6 +243,7 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
                        "       .set    pop                             \n"
                        : [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp)
                        : [global] "r" (page_global));
+                       loongson_llsc_mb();
                }
 #else /* !CONFIG_SMP */
                if (pte_none(*buddy))
index 6256d35..bedb504 100644 (file)
@@ -74,14 +74,15 @@ static int __init vdma_init(void)
                                                    get_order(VDMA_PGTBL_SIZE));
        BUG_ON(!pgtbl);
        dma_cache_wback_inv((unsigned long)pgtbl, VDMA_PGTBL_SIZE);
-       pgtbl = (VDMA_PGTBL_ENTRY *)KSEG1ADDR(pgtbl);
+       pgtbl = (VDMA_PGTBL_ENTRY *)CKSEG1ADDR((unsigned long)pgtbl);
 
        /*
         * Clear the R4030 translation table
         */
        vdma_pgtbl_init();
 
-       r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE, CPHYSADDR(pgtbl));
+       r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE,
+                         CPHYSADDR((unsigned long)pgtbl));
        r4030_write_reg32(JAZZ_R4030_TRSTBL_LIM, VDMA_PGTBL_SIZE);
        r4030_write_reg32(JAZZ_R4030_TRSTBL_INV, 0);
 
index 8f5bd04..7f3f136 100644 (file)
@@ -457,5 +457,5 @@ void mips_cm_error_report(void)
        }
 
        /* reprime cause register */
-       write_gcr_error_cause(0);
+       write_gcr_error_cause(cm_error);
 }
index 6829a06..339870e 100644 (file)
@@ -371,7 +371,7 @@ static inline int is_sp_move_ins(union mips_instruction *ip, int *frame_size)
 static int get_frame_info(struct mips_frame_info *info)
 {
        bool is_mmips = IS_ENABLED(CONFIG_CPU_MICROMIPS);
-       union mips_instruction insn, *ip, *ip_end;
+       union mips_instruction insn, *ip;
        const unsigned int max_insns = 128;
        unsigned int last_insn_size = 0;
        unsigned int i;
@@ -384,10 +384,9 @@ static int get_frame_info(struct mips_frame_info *info)
        if (!ip)
                goto err;
 
-       ip_end = (void *)ip + info->func_size;
-
-       for (i = 0; i < max_insns && ip < ip_end; i++) {
+       for (i = 0; i < max_insns; i++) {
                ip = (void *)ip + last_insn_size;
+
                if (is_mmips && mm_insn_16bit(ip->halfword[0])) {
                        insn.word = ip->halfword[0] << 16;
                        last_insn_size = 2;
index f0bc331..6549499 100644 (file)
@@ -224,9 +224,11 @@ static struct irq_chip ltq_eiu_type = {
        .irq_set_type = ltq_eiu_settype,
 };
 
-static void ltq_hw_irqdispatch(int module)
+static void ltq_hw_irq_handler(struct irq_desc *desc)
 {
+       int module = irq_desc_get_irq(desc) - 2;
        u32 irq;
+       int hwirq;
 
        irq = ltq_icu_r32(module, LTQ_ICU_IM0_IOSR);
        if (irq == 0)
@@ -237,7 +239,8 @@ static void ltq_hw_irqdispatch(int module)
         * other bits might be bogus
         */
        irq = __fls(irq);
-       do_IRQ((int)irq + MIPS_CPU_IRQ_CASCADE + (INT_NUM_IM_OFFSET * module));
+       hwirq = irq + MIPS_CPU_IRQ_CASCADE + (INT_NUM_IM_OFFSET * module);
+       generic_handle_irq(irq_linear_revmap(ltq_domain, hwirq));
 
        /* if this is a EBU irq, we need to ack it or get a deadlock */
        if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT)
@@ -245,49 +248,6 @@ static void ltq_hw_irqdispatch(int module)
                        LTQ_EBU_PCC_ISTAT);
 }
 
-#define DEFINE_HWx_IRQDISPATCH(x)                                      \
-       static void ltq_hw ## x ## _irqdispatch(void)                   \
-       {                                                               \
-               ltq_hw_irqdispatch(x);                                  \
-       }
-DEFINE_HWx_IRQDISPATCH(0)
-DEFINE_HWx_IRQDISPATCH(1)
-DEFINE_HWx_IRQDISPATCH(2)
-DEFINE_HWx_IRQDISPATCH(3)
-DEFINE_HWx_IRQDISPATCH(4)
-
-#if MIPS_CPU_TIMER_IRQ == 7
-static void ltq_hw5_irqdispatch(void)
-{
-       do_IRQ(MIPS_CPU_TIMER_IRQ);
-}
-#else
-DEFINE_HWx_IRQDISPATCH(5)
-#endif
-
-static void ltq_hw_irq_handler(struct irq_desc *desc)
-{
-       ltq_hw_irqdispatch(irq_desc_get_irq(desc) - 2);
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
-       unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
-       int irq;
-
-       if (!pending) {
-               spurious_interrupt();
-               return;
-       }
-
-       pending >>= CAUSEB_IP;
-       while (pending) {
-               irq = fls(pending) - 1;
-               do_IRQ(MIPS_CPU_IRQ_BASE + irq);
-               pending &= ~BIT(irq);
-       }
-}
-
 static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
 {
        struct irq_chip *chip = &ltq_irq_type;
@@ -343,38 +303,13 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
        for (i = 0; i < MAX_IM; i++)
                irq_set_chained_handler(i + 2, ltq_hw_irq_handler);
 
-       if (cpu_has_vint) {
-               pr_info("Setting up vectored interrupts\n");
-               set_vi_handler(2, ltq_hw0_irqdispatch);
-               set_vi_handler(3, ltq_hw1_irqdispatch);
-               set_vi_handler(4, ltq_hw2_irqdispatch);
-               set_vi_handler(5, ltq_hw3_irqdispatch);
-               set_vi_handler(6, ltq_hw4_irqdispatch);
-               set_vi_handler(7, ltq_hw5_irqdispatch);
-       }
-
        ltq_domain = irq_domain_add_linear(node,
                (MAX_IM * INT_NUM_IM_OFFSET) + MIPS_CPU_IRQ_CASCADE,
                &irq_domain_ops, 0);
 
-#ifndef CONFIG_MIPS_MT_SMP
-       set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 |
-               IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
-#else
-       set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ0 | IE_IRQ1 |
-               IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
-#endif
-
        /* tell oprofile which irq to use */
        ltq_perfcount_irq = irq_create_mapping(ltq_domain, LTQ_PERF_IRQ);
 
-       /*
-        * if the timer irq is not one of the mips irqs we need to
-        * create a mapping
-        */
-       if (MIPS_CPU_TIMER_IRQ != 7)
-               irq_create_mapping(ltq_domain, MIPS_CPU_TIMER_IRQ);
-
        /* the external interrupts are optional and xway only */
        eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu-xway");
        if (eiu_node && !of_address_to_resource(eiu_node, 0, &res)) {
@@ -411,7 +346,7 @@ EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
 
 unsigned int get_c0_compare_int(void)
 {
-       return MIPS_CPU_TIMER_IRQ;
+       return CP0_LEGACY_COMPARE_IRQ;
 }
 
 static struct of_device_id __initdata of_irq_ids[] = {
index 982859f..5e6a1a4 100644 (file)
@@ -129,9 +129,9 @@ ltq_dma_alloc(struct ltq_dma_channel *ch)
        unsigned long flags;
 
        ch->desc = 0;
-       ch->desc_base = dma_zalloc_coherent(ch->dev,
-                               LTQ_DESC_NUM * LTQ_DESC_SIZE,
-                               &ch->phys, GFP_ATOMIC);
+       ch->desc_base = dma_alloc_coherent(ch->dev,
+                                          LTQ_DESC_NUM * LTQ_DESC_SIZE,
+                                          &ch->phys, GFP_ATOMIC);
 
        spin_lock_irqsave(&ltq_dma_lock, flags);
        ltq_dma_w32(ch->nr, LTQ_DMA_CS);
index 0fce460..c1a4d4d 100644 (file)
@@ -23,6 +23,29 @@ ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS
 endif
 
 cflags-$(CONFIG_CPU_LOONGSON3) += -Wa,--trap
+
+#
+# Some versions of binutils, not currently mainline as of 2019/02/04, support
+# an -mfix-loongson3-llsc flag which emits a sync prior to each ll instruction
+# to work around a CPU bug (see loongson_llsc_mb() in asm/barrier.h for a
+# description).
+#
+# We disable this in order to prevent the assembler meddling with the
+# instruction that labels refer to, ie. if we label an ll instruction:
+#
+# 1: ll v0, 0(a0)
+#
+# ...then with the assembler fix applied the label may actually point at a sync
+# instruction inserted by the assembler, and if we were using the label in an
+# exception table the table would no longer contain the address of the ll
+# instruction.
+#
+# Avoid this by explicitly disabling that assembler behaviour. If upstream
+# binutils does not merge support for the flag then we can revisit & remove
+# this later - for now it ensures vendor toolchains don't cause problems.
+#
+cflags-$(CONFIG_CPU_LOONGSON3) += $(call as-option,-Wa$(comma)-mno-fix-loongson3-llsc,)
+
 #
 # binutils from v2.25 on and gcc starting from v4.9.0 treat -march=loongson3a
 # as MIPS64 R2; older versions as just R1.  This leaves the possibility open
index a60715e..b26892c 100644 (file)
@@ -59,7 +59,12 @@ static void loongson_poweroff(void)
 {
 #ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
        mach_prepare_shutdown();
-       unreachable();
+
+       /*
+        * It needs a wait loop here, but mips/kernel/reset.c already calls
+        * a generic delay loop, machine_hang(), so simply return.
+        */
+       return;
 #else
        void (*fw_poweroff)(void) = (void *)loongson_sysconf.poweroff_addr;
 
index 37b1cb2..65b6e85 100644 (file)
@@ -932,6 +932,8 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
                 * to mimic that here by taking a load/istream page
                 * fault.
                 */
+               if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
+                       uasm_i_sync(p, 0);
                UASM_i_LA(p, ptr, (unsigned long)tlb_do_page_fault_0);
                uasm_i_jr(p, ptr);
 
@@ -1646,6 +1648,8 @@ static void
 iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr)
 {
 #ifdef CONFIG_SMP
+       if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
+               uasm_i_sync(p, 0);
 # ifdef CONFIG_PHYS_ADDR_T_64BIT
        if (cpu_has_64bits)
                uasm_i_lld(p, pte, 0, ptr);
@@ -2259,6 +2263,8 @@ static void build_r4000_tlb_load_handler(void)
 #endif
 
        uasm_l_nopage_tlbl(&l, p);
+       if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
+               uasm_i_sync(&p, 0);
        build_restore_work_registers(&p);
 #ifdef CONFIG_CPU_MICROMIPS
        if ((unsigned long)tlb_do_page_fault_0 & 1) {
@@ -2313,6 +2319,8 @@ static void build_r4000_tlb_store_handler(void)
 #endif
 
        uasm_l_nopage_tlbs(&l, p);
+       if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
+               uasm_i_sync(&p, 0);
        build_restore_work_registers(&p);
 #ifdef CONFIG_CPU_MICROMIPS
        if ((unsigned long)tlb_do_page_fault_1 & 1) {
@@ -2368,6 +2376,8 @@ static void build_r4000_tlb_modify_handler(void)
 #endif
 
        uasm_l_nopage_tlbm(&l, p);
+       if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
+               uasm_i_sync(&p, 0);
        build_restore_work_registers(&p);
 #ifdef CONFIG_CPU_MICROMIPS
        if ((unsigned long)tlb_do_page_fault_1 & 1) {
index 2a5bb84..288b58b 100644 (file)
@@ -369,7 +369,9 @@ int __init octeon_msi_initialize(void)
        int irq;
        struct irq_chip *msi;
 
-       if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE) {
+       if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_INVALID) {
+               return 0;
+       } else if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE) {
                msi_rcv_reg[0] = CVMX_PEXP_NPEI_MSI_RCV0;
                msi_rcv_reg[1] = CVMX_PEXP_NPEI_MSI_RCV1;
                msi_rcv_reg[2] = CVMX_PEXP_NPEI_MSI_RCV2;
index 5017d58..fc29b85 100644 (file)
@@ -568,6 +568,11 @@ static int __init octeon_pci_setup(void)
        if (octeon_has_feature(OCTEON_FEATURE_PCIE))
                return 0;
 
+       if (!octeon_is_pci_host()) {
+               pr_notice("Not in host mode, PCI Controller not initialized\n");
+               return 0;
+       }
+
        /* Point pcibios_map_irq() to the PCI version of it */
        octeon_pcibios_map_irq = octeon_pci_pcibios_map_irq;
 
@@ -579,11 +584,6 @@ static int __init octeon_pci_setup(void)
        else
                octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_BIG;
 
-       if (!octeon_is_pci_host()) {
-               pr_notice("Not in host mode, PCI Controller not initialized\n");
-               return 0;
-       }
-
        /* PCI I/O and PCI MEM values */
        set_io_port_base(OCTEON_PCI_IOSPACE_BASE);
        ioport_resource.start = 0;
index f6fd340..0ede4de 100644 (file)
@@ -8,6 +8,7 @@ ccflags-vdso := \
        $(filter -E%,$(KBUILD_CFLAGS)) \
        $(filter -mmicromips,$(KBUILD_CFLAGS)) \
        $(filter -march=%,$(KBUILD_CFLAGS)) \
+       $(filter -m%-float,$(KBUILD_CFLAGS)) \
        -D__VDSO__
 
 ifdef CONFIG_CC_IS_CLANG
@@ -129,7 +130,7 @@ $(obj)/%-o32.o: $(src)/%.c FORCE
        $(call cmd,force_checksrc)
        $(call if_changed_rule,cc_o_c)
 
-$(obj)/vdso-o32.lds: KBUILD_CPPFLAGS := -mabi=32
+$(obj)/vdso-o32.lds: KBUILD_CPPFLAGS := $(ccflags-vdso) -mabi=32
 $(obj)/vdso-o32.lds: $(src)/vdso.lds.S FORCE
        $(call if_changed_dep,cpp_lds_S)
 
@@ -169,7 +170,7 @@ $(obj)/%-n32.o: $(src)/%.c FORCE
        $(call cmd,force_checksrc)
        $(call if_changed_rule,cc_o_c)
 
-$(obj)/vdso-n32.lds: KBUILD_CPPFLAGS := -mabi=n32
+$(obj)/vdso-n32.lds: KBUILD_CPPFLAGS := $(ccflags-vdso) -mabi=n32
 $(obj)/vdso-n32.lds: $(src)/vdso.lds.S FORCE
        $(call if_changed_dep,cpp_lds_S)
 
index 0a935c1..ac34828 100644 (file)
@@ -3,9 +3,6 @@ OBJCOPYFLAGS    := -O binary -R .note -R .note.gnu.build-id -R .comment -S
 
 KBUILD_DEFCONFIG := defconfig
 
-comma = ,
-
-
 ifdef CONFIG_FUNCTION_TRACER
 arch-y += -malways-save-lp -mno-relax
 endif
@@ -54,8 +51,6 @@ endif
 boot := arch/nds32/boot
 core-y += $(boot)/dts/
 
-.PHONY: FORCE
-
 Image: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
@@ -68,9 +63,6 @@ prepare: vdso_prepare
 vdso_prepare: prepare0
        $(Q)$(MAKE) $(build)=arch/nds32/kernel/vdso include/generated/vdso-offsets.h
 
-CLEAN_FILES += include/asm-nds32/constants.h*
-
-# We use MRPROPER_FILES and CLEAN_FILES now
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
 
index 70e06d3..bf10141 100644 (file)
@@ -20,7 +20,6 @@
 KBUILD_DEFCONFIG := or1ksim_defconfig
 
 OBJCOPYFLAGS    := -O binary -R .note -R .comment -S
-LDFLAGS_vmlinux :=
 LIBGCC                 := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
 
 KBUILD_CFLAGS  += -pipe -ffixed-r10 -D__linux__
@@ -50,5 +49,3 @@ else
 BUILTIN_DTB := n
 endif
 core-$(BUILTIN_DTB) += arch/openrisc/boot/dts/
-
-all: vmlinux
index eb87cd8..1f04844 100644 (file)
@@ -34,6 +34,7 @@ generic-y += qrwlock_types.h
 generic-y += qrwlock.h
 generic-y += sections.h
 generic-y += segment.h
+generic-y += shmparam.h
 generic-y += string.h
 generic-y += switch_to.h
 generic-y += topology.h
index bc8191a..a44682c 100644 (file)
 /* Ensure that addr is below task's addr_limit */
 #define __addr_ok(addr) ((unsigned long) addr < get_fs())
 
-#define access_ok(addr, size) \
-       __range_ok((unsigned long)addr, (unsigned long)size)
+#define access_ok(addr, size)                                          \
+({                                                                     \
+       unsigned long __ao_addr = (unsigned long)(addr);                \
+       unsigned long __ao_size = (unsigned long)(size);                \
+       __range_ok(__ao_addr, __ao_size);                               \
+})
 
 /*
  * These are the main single-value transfer routines.  They automatically
index 2e6ada2..d8c8d7c 100644 (file)
@@ -904,7 +904,7 @@ static inline int pud_none(pud_t pud)
 
 static inline int pud_present(pud_t pud)
 {
-       return (pud_raw(pud) & cpu_to_be64(_PAGE_PRESENT));
+       return !!(pud_raw(pud) & cpu_to_be64(_PAGE_PRESENT));
 }
 
 extern struct page *pud_page(pud_t pud);
@@ -951,7 +951,7 @@ static inline int pgd_none(pgd_t pgd)
 
 static inline int pgd_present(pgd_t pgd)
 {
-       return (pgd_raw(pgd) & cpu_to_be64(_PAGE_PRESENT));
+       return !!(pgd_raw(pgd) & cpu_to_be64(_PAGE_PRESENT));
 }
 
 static inline pte_t pgd_pte(pgd_t pgd)
@@ -1258,21 +1258,13 @@ extern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
 
 #define pmd_move_must_withdraw pmd_move_must_withdraw
 struct spinlock;
-static inline int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
-                                        struct spinlock *old_pmd_ptl,
-                                        struct vm_area_struct *vma)
-{
-       if (radix_enabled())
-               return false;
-       /*
-        * Archs like ppc64 use pgtable to store per pmd
-        * specific information. So when we switch the pmd,
-        * we should also withdraw and deposit the pgtable
-        */
-       return true;
-}
-
-
+extern int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
+                                 struct spinlock *old_pmd_ptl,
+                                 struct vm_area_struct *vma);
+/*
+ * Hash translation mode use the deposited table to store hash pte
+ * slot information.
+ */
 #define arch_needs_pgtable_deposit arch_needs_pgtable_deposit
 static inline bool arch_needs_pgtable_deposit(void)
 {
index ff91192..f599064 100644 (file)
@@ -47,6 +47,7 @@ enum perf_event_powerpc_regs {
        PERF_REG_POWERPC_DAR,
        PERF_REG_POWERPC_DSISR,
        PERF_REG_POWERPC_SIER,
+       PERF_REG_POWERPC_MMCRA,
        PERF_REG_POWERPC_MAX,
 };
 #endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */
index 57deb1e..20cc816 100644 (file)
@@ -852,11 +852,12 @@ start_here:
 
        /* set up the PTE pointers for the Abatron bdiGDB.
        */
-       tovirt(r6,r6)
        lis     r5, abatron_pteptrs@h
        ori     r5, r5, abatron_pteptrs@l
        stw     r5, 0xf0(0)     /* Must match your Abatron config file */
        tophys(r5,r5)
+       lis     r6, swapper_pg_dir@h
+       ori     r6, r6, swapper_pg_dir@l
        stw     r6, 0(r5)
 
 /* Now turn on the MMU for real! */
index bd5e683..6794466 100644 (file)
@@ -755,11 +755,12 @@ SYSCALL_DEFINE0(rt_sigreturn)
                if (restore_tm_sigcontexts(current, &uc->uc_mcontext,
                                           &uc_transact->uc_mcontext))
                        goto badframe;
-       }
+       } else
 #endif
-       /* Fall through, for non-TM restore */
-       if (!MSR_TM_ACTIVE(msr)) {
+       {
                /*
+                * Fall through, for non-TM restore
+                *
                 * Unset MSR[TS] on the thread regs since MSR from user
                 * context does not have MSR active, and recheckpoint was
                 * not called since restore_tm_sigcontexts() was not called
index 29746dc..517662a 100644 (file)
@@ -967,13 +967,6 @@ out:
 }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 
-#if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_PPC64)
-unsigned long __init arch_syscall_addr(int nr)
-{
-       return sys_call_table[nr*2];
-}
-#endif /* CONFIG_FTRACE_SYSCALLS && CONFIG_PPC64 */
-
 #ifdef PPC64_ELF_ABI_v1
 char *arch_ftrace_match_adjust(char *str, const char *search)
 {
index f3c31f5..ecd3156 100644 (file)
@@ -400,3 +400,25 @@ void arch_report_meminfo(struct seq_file *m)
                   atomic_long_read(&direct_pages_count[MMU_PAGE_1G]) << 20);
 }
 #endif /* CONFIG_PROC_FS */
+
+/*
+ * For hash translation mode, we use the deposited table to store hash slot
+ * information and they are stored at PTRS_PER_PMD offset from related pmd
+ * location. Hence a pmd move requires deposit and withdraw.
+ *
+ * For radix translation with split pmd ptl, we store the deposited table in the
+ * pmd page. Hence if we have different pmd page we need to withdraw during pmd
+ * move.
+ *
+ * With hash we use deposited table always irrespective of anon or not.
+ * With radix we use deposited table only for anonymous mapping.
+ */
+int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
+                          struct spinlock *old_pmd_ptl,
+                          struct vm_area_struct *vma)
+{
+       if (radix_enabled())
+               return (new_pmd_ptl != old_pmd_ptl) && vma_is_anonymous(vma);
+
+       return true;
+}
index 5c36b3a..3349f3f 100644 (file)
@@ -70,6 +70,7 @@ static unsigned int pt_regs_offset[PERF_REG_POWERPC_MAX] = {
        PT_REGS_OFFSET(PERF_REG_POWERPC_DAR, dar),
        PT_REGS_OFFSET(PERF_REG_POWERPC_DSISR, dsisr),
        PT_REGS_OFFSET(PERF_REG_POWERPC_SIER, dar),
+       PT_REGS_OFFSET(PERF_REG_POWERPC_MMCRA, dsisr),
 };
 
 u64 perf_reg_value(struct pt_regs *regs, int idx)
@@ -83,6 +84,11 @@ u64 perf_reg_value(struct pt_regs *regs, int idx)
            !is_sier_available()))
                return 0;
 
+       if (idx == PERF_REG_POWERPC_MMCRA &&
+          (IS_ENABLED(CONFIG_FSL_EMB_PERF_EVENT) ||
+           IS_ENABLED(CONFIG_PPC32)))
+               return 0;
+
        return regs_get_register(regs, pt_regs_offset[idx]);
 }
 
index a1aaa15..f0e488d 100644 (file)
@@ -237,12 +237,12 @@ static int ocm_debugfs_show(struct seq_file *m, void *v)
                        continue;
 
                seq_printf(m, "PPC4XX OCM   : %d\n", ocm->index);
-               seq_printf(m, "PhysAddr     : %pa[p]\n", &(ocm->phys));
+               seq_printf(m, "PhysAddr     : %pa\n", &(ocm->phys));
                seq_printf(m, "MemTotal     : %d Bytes\n", ocm->memtotal);
                seq_printf(m, "MemTotal(NC) : %d Bytes\n", ocm->nc.memtotal);
                seq_printf(m, "MemTotal(C)  : %d Bytes\n\n", ocm->c.memtotal);
 
-               seq_printf(m, "NC.PhysAddr  : %pa[p]\n", &(ocm->nc.phys));
+               seq_printf(m, "NC.PhysAddr  : %pa\n", &(ocm->nc.phys));
                seq_printf(m, "NC.VirtAddr  : 0x%p\n", ocm->nc.virt);
                seq_printf(m, "NC.MemTotal  : %d Bytes\n", ocm->nc.memtotal);
                seq_printf(m, "NC.MemFree   : %d Bytes\n", ocm->nc.memfree);
@@ -252,7 +252,7 @@ static int ocm_debugfs_show(struct seq_file *m, void *v)
                                                        blk->size, blk->owner);
                }
 
-               seq_printf(m, "\nC.PhysAddr   : %pa[p]\n", &(ocm->c.phys));
+               seq_printf(m, "\nC.PhysAddr   : %pa\n", &(ocm->c.phys));
                seq_printf(m, "C.VirtAddr   : 0x%p\n", ocm->c.virt);
                seq_printf(m, "C.MemTotal   : %d Bytes\n", ocm->c.memtotal);
                seq_printf(m, "C.MemFree    : %d Bytes\n", ocm->c.memfree);
index e66644e..9438fa0 100644 (file)
@@ -538,8 +538,7 @@ static void __init chrp_init_IRQ(void)
        /* see if there is a keyboard in the device tree
           with a parent of type "adb" */
        for_each_node_by_name(kbd, "keyboard")
-               if (kbd->parent && kbd->parent->type
-                   && strcmp(kbd->parent->type, "adb") == 0)
+               if (of_node_is_type(kbd->parent, "adb"))
                        break;
        of_node_put(kbd);
        if (kbd)
index d18d164..bdf9b71 100644 (file)
@@ -255,7 +255,7 @@ int pasemi_dma_alloc_ring(struct pasemi_dmachan *chan, int ring_size)
 
        chan->ring_size = ring_size;
 
-       chan->ring_virt = dma_zalloc_coherent(&dma_pdev->dev,
+       chan->ring_virt = dma_alloc_coherent(&dma_pdev->dev,
                                             ring_size * sizeof(u64),
                                             &chan->ring_dma, GFP_KERNEL);
 
index d7f742e..3f58c7d 100644 (file)
@@ -564,7 +564,7 @@ struct iommu_table_group *pnv_try_setup_npu_table_group(struct pnv_ioda_pe *pe)
                }
        } else {
                /* Create a group for 1 GPU and attached NPUs for POWER8 */
-               pe->npucomp = kzalloc(sizeof(pe->npucomp), GFP_KERNEL);
+               pe->npucomp = kzalloc(sizeof(*pe->npucomp), GFP_KERNEL);
                table_group = &pe->npucomp->table_group;
                table_group->ops = &pnv_npu_peers_ops;
                iommu_register_group(table_group, hose->global_number,
index 1d6406a..7db3119 100644 (file)
@@ -2681,7 +2681,8 @@ static void pnv_pci_ioda_setup_iommu_api(void)
        list_for_each_entry(hose, &hose_list, list_node) {
                phb = hose->private_data;
 
-               if (phb->type == PNV_PHB_NPU_NVLINK)
+               if (phb->type == PNV_PHB_NPU_NVLINK ||
+                   phb->type == PNV_PHB_NPU_OCAPI)
                        continue;
 
                list_for_each_entry(pe, &phb->ioda.pe_list, list) {
index 7d6457a..bba281b 100644 (file)
@@ -43,6 +43,7 @@ static int drc_pmem_bind(struct papr_scm_priv *p)
 {
        unsigned long ret[PLPAR_HCALL_BUFSIZE];
        uint64_t rc, token;
+       uint64_t saved = 0;
 
        /*
         * When the hypervisor cannot map all the requested memory in a single
@@ -56,6 +57,8 @@ static int drc_pmem_bind(struct papr_scm_priv *p)
                rc = plpar_hcall(H_SCM_BIND_MEM, ret, p->drc_index, 0,
                                p->blocks, BIND_ANY_ADDR, token);
                token = ret[0];
+               if (!saved)
+                       saved = ret[1];
                cond_resched();
        } while (rc == H_BUSY);
 
@@ -64,7 +67,7 @@ static int drc_pmem_bind(struct papr_scm_priv *p)
                return -ENXIO;
        }
 
-       p->bound_addr = ret[1];
+       p->bound_addr = saved;
 
        dev_dbg(&p->pdev->dev, "bound drc %x to %pR\n", p->drc_index, &p->res);
 
index 7725825..37a77e5 100644 (file)
@@ -264,7 +264,9 @@ void __init pSeries_final_fixup(void)
                        if (!of_device_is_compatible(nvdn->parent,
                                                "ibm,power9-npu"))
                                continue;
+#ifdef CONFIG_PPC_POWERNV
                        WARN_ON_ONCE(pnv_npu2_init(hose));
+#endif
                        break;
                }
        }
index 8b0ebf3..ebed46f 100644 (file)
@@ -756,9 +756,10 @@ fsl_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
        }
 
        /* Initialize outbound message descriptor ring */
-       rmu->msg_tx_ring.virt = dma_zalloc_coherent(priv->dev,
-                               rmu->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
-                               &rmu->msg_tx_ring.phys, GFP_KERNEL);
+       rmu->msg_tx_ring.virt = dma_alloc_coherent(priv->dev,
+                                                  rmu->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
+                                                  &rmu->msg_tx_ring.phys,
+                                                  GFP_KERNEL);
        if (!rmu->msg_tx_ring.virt) {
                rc = -ENOMEM;
                goto out_dma;
index e0d7d61..515fc3c 100644 (file)
@@ -28,11 +28,13 @@ config RISCV
        select GENERIC_STRNLEN_USER
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_ATOMIC64 if !64BIT || !RISCV_ISA_A
+       select HAVE_ARCH_AUDITSYSCALL
        select HAVE_MEMBLOCK_NODE_MAP
        select HAVE_DMA_CONTIGUOUS
        select HAVE_FUTEX_CMPXCHG if FUTEX
        select HAVE_GENERIC_DMA_COHERENT
        select HAVE_PERF_EVENTS
+       select HAVE_SYSCALL_TRACEPOINTS
        select IRQ_DOMAIN
        select RISCV_ISA_A if SMP
        select SPARSE_IRQ
@@ -40,6 +42,7 @@ config RISCV
        select HAVE_ARCH_TRACEHOOK
        select HAVE_PCI
        select MODULES_USE_ELF_RELA if MODULES
+       select MODULE_SECTIONS if MODULES
        select THREAD_INFO_IN_TASK
        select PCI_DOMAINS_GENERIC if PCI
        select PCI_MSI if PCI
@@ -100,7 +103,7 @@ choice
        prompt "Base ISA"
        default ARCH_RV64I
        help
-         This selects the base ISA that this kernel will traget and must match
+         This selects the base ISA that this kernel will target and must match
          the target platform.
 
 config ARCH_RV32I
@@ -152,7 +155,6 @@ choice
                bool "2GiB"
        config MAXPHYSMEM_128GB
                depends on 64BIT && CMODEL_MEDANY
-               select MODULE_SECTIONS if MODULES
                bool "128GiB"
 endchoice
 
index f399659..2fd3461 100644 (file)
@@ -13,8 +13,6 @@ CONFIG_BLK_DEV_INITRD=y
 CONFIG_EXPERT=y
 CONFIG_BPF_SYSCALL=y
 CONFIG_SMP=y
-CONFIG_PCI=y
-CONFIG_PCIE_XILINX=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_NET=y
@@ -28,6 +26,10 @@ CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 CONFIG_NETLINK_DIAG=y
+CONFIG_PCI=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCI_HOST_GENERIC=y
+CONFIG_PCIE_XILINX=y
 CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_VIRTIO_BLK=y
@@ -63,7 +65,6 @@ CONFIG_USB_STORAGE=y
 CONFIG_USB_UAS=y
 CONFIG_VIRTIO_MMIO=y
 CONFIG_SIFIVE_PLIC=y
-CONFIG_RAS=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_AUTOFS4_FS=y
@@ -77,5 +78,6 @@ CONFIG_NFS_V4_1=y
 CONFIG_NFS_V4_2=y
 CONFIG_ROOT_NFS=y
 CONFIG_CRYPTO_USER_API_HASH=y
+CONFIG_CRYPTO_DEV_VIRTIO=y
 CONFIG_PRINTK_TIME=y
 # CONFIG_RCU_TRACE is not set
index cd2af4b..46202da 100644 (file)
@@ -9,12 +9,12 @@
 #define MODULE_ARCH_VERMAGIC    "riscv"
 
 struct module;
-u64 module_emit_got_entry(struct module *mod, u64 val);
-u64 module_emit_plt_entry(struct module *mod, u64 val);
+unsigned long module_emit_got_entry(struct module *mod, unsigned long val);
+unsigned long module_emit_plt_entry(struct module *mod, unsigned long val);
 
 #ifdef CONFIG_MODULE_SECTIONS
 struct mod_section {
-       struct elf64_shdr *shdr;
+       Elf_Shdr *shdr;
        int num_entries;
        int max_entries;
 };
@@ -26,18 +26,18 @@ struct mod_arch_specific {
 };
 
 struct got_entry {
-       u64 symbol_addr;        /* the real variable address */
+       unsigned long symbol_addr;      /* the real variable address */
 };
 
-static inline struct got_entry emit_got_entry(u64 val)
+static inline struct got_entry emit_got_entry(unsigned long val)
 {
        return (struct got_entry) {val};
 }
 
-static inline struct got_entry *get_got_entry(u64 val,
+static inline struct got_entry *get_got_entry(unsigned long val,
                                              const struct mod_section *sec)
 {
-       struct got_entry *got = (struct got_entry *)sec->shdr->sh_addr;
+       struct got_entry *got = (struct got_entry *)(sec->shdr->sh_addr);
        int i;
        for (i = 0; i < sec->num_entries; i++) {
                if (got[i].symbol_addr == val)
@@ -62,7 +62,9 @@ struct plt_entry {
 #define REG_T0     0x5
 #define REG_T1     0x6
 
-static inline struct plt_entry emit_plt_entry(u64 val, u64 plt, u64 got_plt)
+static inline struct plt_entry emit_plt_entry(unsigned long val,
+                                             unsigned long plt,
+                                             unsigned long got_plt)
 {
        /*
         * U-Type encoding:
@@ -76,7 +78,7 @@ static inline struct plt_entry emit_plt_entry(u64 val, u64 plt, u64 got_plt)
         * +------------+------------+--------+----------+----------+
         *
         */
-       u64 offset = got_plt - plt;
+       unsigned long offset = got_plt - plt;
        u32 hi20 = (offset + 0x800) & 0xfffff000;
        u32 lo12 = (offset - hi20);
        return (struct plt_entry) {
@@ -86,7 +88,7 @@ static inline struct plt_entry emit_plt_entry(u64 val, u64 plt, u64 got_plt)
        };
 }
 
-static inline int get_got_plt_idx(u64 val, const struct mod_section *sec)
+static inline int get_got_plt_idx(unsigned long val, const struct mod_section *sec)
 {
        struct got_entry *got_plt = (struct got_entry *)sec->shdr->sh_addr;
        int i;
@@ -97,9 +99,9 @@ static inline int get_got_plt_idx(u64 val, const struct mod_section *sec)
        return -1;
 }
 
-static inline struct plt_entry *get_plt_entry(u64 val,
-                                     const struct mod_section *sec_plt,
-                                     const struct mod_section *sec_got_plt)
+static inline struct plt_entry *get_plt_entry(unsigned long val,
+                                             const struct mod_section *sec_plt,
+                                             const struct mod_section *sec_got_plt)
 {
        struct plt_entry *plt = (struct plt_entry *)sec_plt->shdr->sh_addr;
        int got_plt_idx = get_got_plt_idx(val, sec_got_plt);
index 06cfbb3..2a546a5 100644 (file)
@@ -80,7 +80,7 @@ typedef struct page *pgtable_t;
 #define __pgd(x)       ((pgd_t) { (x) })
 #define __pgprot(x)    ((pgprot_t) { (x) })
 
-#ifdef CONFIG_64BITS
+#ifdef CONFIG_64BIT
 #define PTE_FMT "%016lx"
 #else
 #define PTE_FMT "%08lx"
index 2fa2942..470755c 100644 (file)
 #define _PAGE_SPECIAL   _PAGE_SOFT
 #define _PAGE_TABLE     _PAGE_PRESENT
 
+/*
+ * _PAGE_PROT_NONE is set on not-present pages (and ignored by the hardware) to
+ * distinguish them from swapped out pages
+ */
+#define _PAGE_PROT_NONE _PAGE_READ
+
 #define _PAGE_PFN_SHIFT 10
 
 /* Set of bits to preserve across pte_modify() */
index 1630196..a8179a8 100644 (file)
@@ -44,7 +44,7 @@
 /* Page protection bits */
 #define _PAGE_BASE     (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER)
 
-#define PAGE_NONE              __pgprot(0)
+#define PAGE_NONE              __pgprot(_PAGE_PROT_NONE)
 #define PAGE_READ              __pgprot(_PAGE_BASE | _PAGE_READ)
 #define PAGE_WRITE             __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_WRITE)
 #define PAGE_EXEC              __pgprot(_PAGE_BASE | _PAGE_EXEC)
@@ -98,7 +98,7 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 
 static inline int pmd_present(pmd_t pmd)
 {
-       return (pmd_val(pmd) & _PAGE_PRESENT);
+       return (pmd_val(pmd) & (_PAGE_PRESENT | _PAGE_PROT_NONE));
 }
 
 static inline int pmd_none(pmd_t pmd)
@@ -178,7 +178,7 @@ static inline pte_t *pte_offset_kernel(pmd_t *pmd, unsigned long addr)
 
 static inline int pte_present(pte_t pte)
 {
-       return (pte_val(pte) & _PAGE_PRESENT);
+       return (pte_val(pte) & (_PAGE_PRESENT | _PAGE_PROT_NONE));
 }
 
 static inline int pte_none(pte_t pte)
@@ -380,7 +380,7 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
  *
  * Format of swap PTE:
  *     bit            0:       _PAGE_PRESENT (zero)
- *     bit            1:       reserved for future use (zero)
+ *     bit            1:       _PAGE_PROT_NONE (zero)
  *     bits      2 to 6:       swap type
  *     bits 7 to XLEN-1:       swap offset
  */
index 0531f49..ce70bce 100644 (file)
@@ -22,7 +22,7 @@
  * This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#define TASK_UNMAPPED_BASE     PAGE_ALIGN(TASK_SIZE >> 1)
+#define TASK_UNMAPPED_BASE     PAGE_ALIGN(TASK_SIZE / 3)
 
 #define STACK_TOP              TASK_SIZE
 #define STACK_TOP_MAX          STACK_TOP
index bbe1862..d35ec2f 100644 (file)
@@ -113,6 +113,11 @@ static inline void frame_pointer_set(struct pt_regs *regs,
        SET_FP(regs, val);
 }
 
+static inline unsigned long regs_return_value(struct pt_regs *regs)
+{
+       return regs->a0;
+}
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_RISCV_PTRACE_H */
index 8d25f89..bba3da6 100644 (file)
@@ -18,6 +18,7 @@
 #ifndef _ASM_RISCV_SYSCALL_H
 #define _ASM_RISCV_SYSCALL_H
 
+#include <uapi/linux/audit.h>
 #include <linux/sched.h>
 #include <linux/err.h>
 
@@ -99,4 +100,13 @@ static inline void syscall_set_arguments(struct task_struct *task,
        memcpy(&regs->a1 + i * sizeof(regs->a1), args, n * sizeof(regs->a0));
 }
 
+static inline int syscall_get_arch(void)
+{
+#ifdef CONFIG_64BIT
+       return AUDIT_ARCH_RISCV64;
+#else
+       return AUDIT_ARCH_RISCV32;
+#endif
+}
+
 #endif /* _ASM_RISCV_SYSCALL_H */
index f8fa1cd..1c9cc83 100644 (file)
@@ -80,13 +80,19 @@ struct thread_info {
 #define TIF_RESTORE_SIGMASK    4       /* restore signal mask in do_signal() */
 #define TIF_MEMDIE             5       /* is terminating due to OOM killer */
 #define TIF_SYSCALL_TRACEPOINT  6       /* syscall tracepoint instrumentation */
+#define TIF_SYSCALL_AUDIT      7       /* syscall auditing */
 
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
+#define _TIF_SYSCALL_TRACEPOINT        (1 << TIF_SYSCALL_TRACEPOINT)
+#define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 
 #define _TIF_WORK_MASK \
        (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED)
 
+#define _TIF_SYSCALL_WORK \
+       (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT)
+
 #endif /* _ASM_RISCV_THREAD_INFO_H */
index fef96f1..073ee80 100644 (file)
@@ -19,3 +19,5 @@
 #define __ARCH_WANT_SYS_CLONE
 
 #include <uapi/asm/unistd.h>
+
+#define NR_syscalls (__NR_syscalls)
index 6a92a2f..dac9834 100644 (file)
@@ -39,6 +39,7 @@ void asm_offsets(void)
        OFFSET(TASK_STACK, task_struct, stack);
        OFFSET(TASK_TI, task_struct, thread_info);
        OFFSET(TASK_TI_FLAGS, task_struct, thread_info.flags);
+       OFFSET(TASK_TI_PREEMPT_COUNT, task_struct, thread_info.preempt_count);
        OFFSET(TASK_TI_KERNEL_SP, task_struct, thread_info.kernel_sp);
        OFFSET(TASK_TI_USER_SP, task_struct, thread_info.user_sp);
        OFFSET(TASK_TI_CPU, task_struct, thread_info.cpu);
index 13d4826..fd9b57c 100644 (file)
@@ -144,6 +144,10 @@ _save_context:
        REG_L x2,  PT_SP(sp)
        .endm
 
+#if !IS_ENABLED(CONFIG_PREEMPT)
+.set resume_kernel, restore_all
+#endif
+
 ENTRY(handle_exception)
        SAVE_ALL
 
@@ -201,7 +205,7 @@ handle_syscall:
        REG_S s2, PT_SEPC(sp)
        /* Trace syscalls, but only if requested by the user. */
        REG_L t0, TASK_TI_FLAGS(tp)
-       andi t0, t0, _TIF_SYSCALL_TRACE
+       andi t0, t0, _TIF_SYSCALL_WORK
        bnez t0, handle_syscall_trace_enter
 check_syscall_nr:
        /* Check to make sure we don't jump to a bogus syscall number. */
@@ -221,14 +225,14 @@ ret_from_syscall:
        REG_S a0, PT_A0(sp)
        /* Trace syscalls, but only if requested by the user. */
        REG_L t0, TASK_TI_FLAGS(tp)
-       andi t0, t0, _TIF_SYSCALL_TRACE
+       andi t0, t0, _TIF_SYSCALL_WORK
        bnez t0, handle_syscall_trace_exit
 
 ret_from_exception:
        REG_L s0, PT_SSTATUS(sp)
        csrc sstatus, SR_SIE
        andi s0, s0, SR_SPP
-       bnez s0, restore_all
+       bnez s0, resume_kernel
 
 resume_userspace:
        /* Interrupts must be disabled here so flags are checked atomically */
@@ -250,6 +254,18 @@ restore_all:
        RESTORE_ALL
        sret
 
+#if IS_ENABLED(CONFIG_PREEMPT)
+resume_kernel:
+       REG_L s0, TASK_TI_PREEMPT_COUNT(tp)
+       bnez s0, restore_all
+need_resched:
+       REG_L s0, TASK_TI_FLAGS(tp)
+       andi s0, s0, _TIF_NEED_RESCHED
+       beqz s0, restore_all
+       call preempt_schedule_irq
+       j need_resched
+#endif
+
 work_pending:
        /* Enter slow path for supplementary processing */
        la ra, ret_from_exception
index bbbd26e..c9ae483 100644 (file)
@@ -9,14 +9,14 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 
-u64 module_emit_got_entry(struct module *mod, u64 val)
+unsigned long module_emit_got_entry(struct module *mod, unsigned long val)
 {
        struct mod_section *got_sec = &mod->arch.got;
        int i = got_sec->num_entries;
        struct got_entry *got = get_got_entry(val, got_sec);
 
        if (got)
-               return (u64)got;
+               return (unsigned long)got;
 
        /* There is no duplicate entry, create a new one */
        got = (struct got_entry *)got_sec->shdr->sh_addr;
@@ -25,10 +25,10 @@ u64 module_emit_got_entry(struct module *mod, u64 val)
        got_sec->num_entries++;
        BUG_ON(got_sec->num_entries > got_sec->max_entries);
 
-       return (u64)&got[i];
+       return (unsigned long)&got[i];
 }
 
-u64 module_emit_plt_entry(struct module *mod, u64 val)
+unsigned long module_emit_plt_entry(struct module *mod, unsigned long val)
 {
        struct mod_section *got_plt_sec = &mod->arch.got_plt;
        struct got_entry *got_plt;
@@ -37,27 +37,29 @@ u64 module_emit_plt_entry(struct module *mod, u64 val)
        int i = plt_sec->num_entries;
 
        if (plt)
-               return (u64)plt;
+               return (unsigned long)plt;
 
        /* There is no duplicate entry, create a new one */
        got_plt = (struct got_entry *)got_plt_sec->shdr->sh_addr;
        got_plt[i] = emit_got_entry(val);
        plt = (struct plt_entry *)plt_sec->shdr->sh_addr;
-       plt[i] = emit_plt_entry(val, (u64)&plt[i], (u64)&got_plt[i]);
+       plt[i] = emit_plt_entry(val,
+                               (unsigned long)&plt[i],
+                               (unsigned long)&got_plt[i]);
 
        plt_sec->num_entries++;
        got_plt_sec->num_entries++;
        BUG_ON(plt_sec->num_entries > plt_sec->max_entries);
 
-       return (u64)&plt[i];
+       return (unsigned long)&plt[i];
 }
 
-static int is_rela_equal(const Elf64_Rela *x, const Elf64_Rela *y)
+static int is_rela_equal(const Elf_Rela *x, const Elf_Rela *y)
 {
        return x->r_info == y->r_info && x->r_addend == y->r_addend;
 }
 
-static bool duplicate_rela(const Elf64_Rela *rela, int idx)
+static bool duplicate_rela(const Elf_Rela *rela, int idx)
 {
        int i;
        for (i = 0; i < idx; i++) {
@@ -67,13 +69,13 @@ static bool duplicate_rela(const Elf64_Rela *rela, int idx)
        return false;
 }
 
-static void count_max_entries(Elf64_Rela *relas, int num,
+static void count_max_entries(Elf_Rela *relas, int num,
                              unsigned int *plts, unsigned int *gots)
 {
        unsigned int type, i;
 
        for (i = 0; i < num; i++) {
-               type = ELF64_R_TYPE(relas[i].r_info);
+               type = ELF_RISCV_R_TYPE(relas[i].r_info);
                if (type == R_RISCV_CALL_PLT) {
                        if (!duplicate_rela(relas, i))
                                (*plts)++;
@@ -118,9 +120,9 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
 
        /* Calculate the maxinum number of entries */
        for (i = 0; i < ehdr->e_shnum; i++) {
-               Elf64_Rela *relas = (void *)ehdr + sechdrs[i].sh_offset;
-               int num_rela = sechdrs[i].sh_size / sizeof(Elf64_Rela);
-               Elf64_Shdr *dst_sec = sechdrs + sechdrs[i].sh_info;
+               Elf_Rela *relas = (void *)ehdr + sechdrs[i].sh_offset;
+               int num_rela = sechdrs[i].sh_size / sizeof(Elf_Rela);
+               Elf_Shdr *dst_sec = sechdrs + sechdrs[i].sh_info;
 
                if (sechdrs[i].sh_type != SHT_RELA)
                        continue;
index 60f1e02..2ae5e02 100644 (file)
 #include <asm/ptrace.h>
 #include <asm/syscall.h>
 #include <asm/thread_info.h>
+#include <linux/audit.h>
 #include <linux/ptrace.h>
 #include <linux/elf.h>
 #include <linux/regset.h>
 #include <linux/sched.h>
 #include <linux/sched/task_stack.h>
 #include <linux/tracehook.h>
+
+#define CREATE_TRACE_POINTS
 #include <trace/events/syscalls.h>
 
 enum riscv_regset {
@@ -163,15 +166,19 @@ void do_syscall_trace_enter(struct pt_regs *regs)
        if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
                trace_sys_enter(regs, syscall_get_nr(current, regs));
 #endif
+
+       audit_syscall_entry(regs->a7, regs->a0, regs->a1, regs->a2, regs->a3);
 }
 
 void do_syscall_trace_exit(struct pt_regs *regs)
 {
+       audit_syscall_exit(regs);
+
        if (test_thread_flag(TIF_SYSCALL_TRACE))
                tracehook_report_syscall_exit(regs, 0);
 
 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
        if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
-               trace_sys_exit(regs, regs->regs[0]);
+               trace_sys_exit(regs, regs_return_value(regs));
 #endif
 }
index fc8006a..7756431 100644 (file)
@@ -149,7 +149,14 @@ asmlinkage void __init setup_vm(void)
 
 void __init parse_dtb(unsigned int hartid, void *dtb)
 {
-       early_init_dt_scan(__va(dtb));
+       if (!early_init_dt_scan(__va(dtb)))
+               return;
+
+       pr_err("No DTB passed to the kernel\n");
+#ifdef CONFIG_CMDLINE_FORCE
+       strlcpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
+       pr_info("Forcing kernel command line to: %s\n", boot_command_line);
+#endif
 }
 
 static void __init setup_bootmem(void)
@@ -174,7 +181,7 @@ static void __init setup_bootmem(void)
        BUG_ON(mem_size == 0);
 
        set_max_mapnr(PFN_DOWN(mem_size));
-       max_low_pfn = memblock_end_of_DRAM();
+       max_low_pfn = PFN_DOWN(memblock_end_of_DRAM());
 
 #ifdef CONFIG_BLK_DEV_INITRD
        setup_initrd();
index 57b1383..246635e 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/smp.h>
 #include <linux/sched.h>
 #include <linux/seq_file.h>
+#include <linux/delay.h>
 
 #include <asm/sbi.h>
 #include <asm/tlbflush.h>
@@ -31,6 +32,7 @@
 enum ipi_message_type {
        IPI_RESCHEDULE,
        IPI_CALL_FUNC,
+       IPI_CPU_STOP,
        IPI_MAX
 };
 
@@ -66,6 +68,13 @@ int setup_profiling_timer(unsigned int multiplier)
        return -EINVAL;
 }
 
+static void ipi_stop(void)
+{
+       set_cpu_online(smp_processor_id(), false);
+       while (1)
+               wait_for_interrupt();
+}
+
 void riscv_software_interrupt(void)
 {
        unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits;
@@ -94,6 +103,11 @@ void riscv_software_interrupt(void)
                        generic_smp_call_function_interrupt();
                }
 
+               if (ops & (1 << IPI_CPU_STOP)) {
+                       stats[IPI_CPU_STOP]++;
+                       ipi_stop();
+               }
+
                BUG_ON((ops >> IPI_MAX) != 0);
 
                /* Order data access and bit testing. */
@@ -121,6 +135,7 @@ send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation)
 static const char * const ipi_names[] = {
        [IPI_RESCHEDULE]        = "Rescheduling interrupts",
        [IPI_CALL_FUNC]         = "Function call interrupts",
+       [IPI_CPU_STOP]          = "CPU stop interrupts",
 };
 
 void show_ipi_stats(struct seq_file *p, int prec)
@@ -146,15 +161,29 @@ void arch_send_call_function_single_ipi(int cpu)
        send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC);
 }
 
-static void ipi_stop(void *unused)
-{
-       while (1)
-               wait_for_interrupt();
-}
-
 void smp_send_stop(void)
 {
-       on_each_cpu(ipi_stop, NULL, 1);
+       unsigned long timeout;
+
+       if (num_online_cpus() > 1) {
+               cpumask_t mask;
+
+               cpumask_copy(&mask, cpu_online_mask);
+               cpumask_clear_cpu(smp_processor_id(), &mask);
+
+               if (system_state <= SYSTEM_RUNNING)
+                       pr_crit("SMP: stopping secondary CPUs\n");
+               send_ipi_message(&mask, IPI_CPU_STOP);
+       }
+
+       /* Wait up to one second for other CPUs to stop */
+       timeout = USEC_PER_SEC;
+       while (num_online_cpus() > 1 && timeout--)
+               udelay(1);
+
+       if (num_online_cpus() > 1)
+               pr_warn("SMP: failed to stop secondary CPUs %*pbl\n",
+                          cpumask_pr_args(cpu_online_mask));
 }
 
 void smp_send_reschedule(int cpu)
index fc185ec..18cda0e 100644 (file)
@@ -57,15 +57,12 @@ void __init setup_smp(void)
 
        while ((dn = of_find_node_by_type(dn, "cpu"))) {
                hart = riscv_of_processor_hartid(dn);
-               if (hart < 0) {
-                       of_node_put(dn);
+               if (hart < 0)
                        continue;
-               }
 
                if (hart == cpuid_to_hartid_map(0)) {
                        BUG_ON(found_boot_cpu);
                        found_boot_cpu = 1;
-                       of_node_put(dn);
                        continue;
                }
 
@@ -73,7 +70,6 @@ void __init setup_smp(void)
                set_cpu_possible(cpuid, true);
                set_cpu_present(cpuid, true);
                cpuid++;
-               of_node_put(dn);
        }
 
        BUG_ON(!found_boot_cpu);
index 1d9bfaf..658ebf6 100644 (file)
@@ -28,7 +28,8 @@ static void __init zone_sizes_init(void)
        unsigned long max_zone_pfns[MAX_NR_ZONES] = { 0, };
 
 #ifdef CONFIG_ZONE_DMA32
-       max_zone_pfns[ZONE_DMA32] = PFN_DOWN(min(4UL * SZ_1G, max_low_pfn));
+       max_zone_pfns[ZONE_DMA32] = PFN_DOWN(min(4UL * SZ_1G,
+                       (unsigned long) PFN_PHYS(max_low_pfn)));
 #endif
        max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
 
index ccbb53e..8d04e6f 100644 (file)
@@ -25,7 +25,7 @@ static inline int init_new_context(struct task_struct *tsk,
        atomic_set(&mm->context.flush_count, 0);
        mm->context.gmap_asce = 0;
        mm->context.flush_mm = 0;
-       mm->context.compat_mm = 0;
+       mm->context.compat_mm = test_thread_flag(TIF_31BIT);
 #ifdef CONFIG_PGSTE
        mm->context.alloc_pgste = page_table_allocate_pgste ||
                test_thread_flag(TIF_PGSTE) ||
@@ -90,8 +90,6 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 {
        int cpu = smp_processor_id();
 
-       if (prev == next)
-               return;
        S390_lowcore.user_asce = next->context.asce;
        cpumask_set_cpu(cpu, &next->context.cpu_attach_mask);
        /* Clear previous user-ASCE from CR1 and CR7 */
@@ -103,7 +101,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
                __ctl_load(S390_lowcore.vdso_asce, 7, 7);
                clear_cpu_flag(CIF_ASCE_SECONDARY);
        }
-       cpumask_clear_cpu(cpu, &prev->context.cpu_attach_mask);
+       if (prev != next)
+               cpumask_clear_cpu(cpu, &prev->context.cpu_attach_mask);
 }
 
 #define finish_arch_post_lock_switch finish_arch_post_lock_switch
index af5c2b3..a8c7789 100644 (file)
@@ -63,10 +63,10 @@ static noinline __init void detect_machine_type(void)
        if (stsi(vmms, 3, 2, 2) || !vmms->count)
                return;
 
-       /* Running under KVM? If not we assume z/VM */
+       /* Detect known hypervisors */
        if (!memcmp(vmms->vm[0].cpi, "\xd2\xe5\xd4", 3))
                S390_lowcore.machine_flags |= MACHINE_FLAG_KVM;
-       else
+       else if (!memcmp(vmms->vm[0].cpi, "\xa9\x61\xe5\xd4", 4))
                S390_lowcore.machine_flags |= MACHINE_FLAG_VM;
 }
 
index 72dd23e..7ed90a7 100644 (file)
@@ -1006,6 +1006,8 @@ void __init setup_arch(char **cmdline_p)
                pr_info("Linux is running under KVM in 64-bit mode\n");
        else if (MACHINE_IS_LPAR)
                pr_info("Linux is running natively in 64-bit mode\n");
+       else
+               pr_info("Linux is running as a guest in 64-bit mode\n");
 
        /* Have one command line that is parsed and saved in /proc/cmdline */
        /* boot_command_line has been already set up in early.c */
index f82b3d3..b198ece 100644 (file)
@@ -381,8 +381,13 @@ void smp_call_online_cpu(void (*func)(void *), void *data)
  */
 void smp_call_ipl_cpu(void (*func)(void *), void *data)
 {
+       struct lowcore *lc = pcpu_devices->lowcore;
+
+       if (pcpu_devices[0].address == stap())
+               lc = &S390_lowcore;
+
        pcpu_delegate(&pcpu_devices[0], func, data,
-                     pcpu_devices->lowcore->nodat_stack);
+                     lc->nodat_stack);
 }
 
 int smp_find_processor_id(u16 address)
@@ -1166,7 +1171,11 @@ static ssize_t __ref rescan_store(struct device *dev,
 {
        int rc;
 
+       rc = lock_device_hotplug_sysfs();
+       if (rc)
+               return rc;
        rc = smp_rescan_cpus();
+       unlock_device_hotplug();
        return rc ? rc : count;
 }
 static DEVICE_ATTR_WO(rescan);
index 537f97f..b6796e6 100644 (file)
        .section .text
 ENTRY(swsusp_arch_suspend)
        lg      %r1,__LC_NODAT_STACK
-       aghi    %r1,-STACK_FRAME_OVERHEAD
        stmg    %r6,%r15,__SF_GPRS(%r1)
+       aghi    %r1,-STACK_FRAME_OVERHEAD
        stg     %r15,__SF_BACKCHAIN(%r1)
-       lgr     %r1,%r15
+       lgr     %r15,%r1
 
        /* Store FPU registers */
        brasl   %r14,save_fpu_regs
index ebe748a..4ff3548 100644 (file)
@@ -224,10 +224,9 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 
        vdso_pages = vdso64_pages;
 #ifdef CONFIG_COMPAT
-       if (is_compat_task()) {
+       mm->context.compat_mm = is_compat_task();
+       if (mm->context.compat_mm)
                vdso_pages = vdso32_pages;
-               mm->context.compat_mm = 1;
-       }
 #endif
        /*
         * vDSO has a problem and was disabled, just don't "enable" it for
index a966d7b..4266a4d 100644 (file)
@@ -382,7 +382,9 @@ static void zpci_irq_handler(struct airq_struct *airq)
                        if (ai == -1UL)
                                break;
                        inc_irq_stat(IRQIO_MSI);
+                       airq_iv_lock(aibv, ai);
                        generic_handle_irq(airq_iv_get_data(aibv, ai));
+                       airq_iv_unlock(aibv, ai);
                }
        }
 }
@@ -408,7 +410,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
        zdev->aisb = aisb;
 
        /* Create adapter interrupt vector */
-       zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA);
+       zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | AIRQ_IV_BITLOCK);
        if (!zdev->aibv)
                return -ENOMEM;
 
index 1372553..1d1544b 100644 (file)
@@ -28,6 +28,7 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += segment.h
 generic-y += serial.h
+generic-y += shmparam.h
 generic-y += sizes.h
 generic-y += syscalls.h
 generic-y += topology.h
index 6185d4f..6826143 100644 (file)
@@ -198,7 +198,7 @@ config X86
        select IRQ_FORCED_THREADING
        select NEED_SG_DMA_LENGTH
        select PCI_DOMAINS                      if PCI
-       select PCI_LOCKLESS_CONFIG
+       select PCI_LOCKLESS_CONFIG              if PCI
        select PERF_EVENTS
        select RTC_LIB
        select RTC_MC146818_LIB
@@ -446,12 +446,12 @@ config RETPOLINE
          branches. Requires a compiler with -mindirect-branch=thunk-extern
          support for full protection. The kernel may run slower.
 
-config RESCTRL
-       bool "Resource Control support"
+config X86_CPU_RESCTRL
+       bool "x86 CPU resource control support"
        depends on X86 && (CPU_SUP_INTEL || CPU_SUP_AMD)
        select KERNFS
        help
-         Enable Resource Control support.
+         Enable x86 CPU resource control support.
 
          Provide support for the allocation and monitoring of system resources
          usage by the CPU.
@@ -617,7 +617,7 @@ config X86_INTEL_QUARK
 
 config X86_INTEL_LPSS
        bool "Intel Low Power Subsystem Support"
-       depends on X86 && ACPI
+       depends on X86 && ACPI && PCI
        select COMMON_CLK
        select PINCTRL
        select IOSF_MBI
index 6403789..f62e347 100644 (file)
@@ -600,6 +600,16 @@ ENTRY(trampoline_32bit_src)
        leal    TRAMPOLINE_32BIT_PGTABLE_OFFSET(%ecx), %eax
        movl    %eax, %cr3
 3:
+       /* Set EFER.LME=1 as a precaution in case hypervsior pulls the rug */
+       pushl   %ecx
+       pushl   %edx
+       movl    $MSR_EFER, %ecx
+       rdmsr
+       btsl    $_EFER_LME, %eax
+       wrmsr
+       popl    %edx
+       popl    %ecx
+
        /* Enable PAE and LA57 (if required) paging modes */
        movl    $X86_CR4_PAE, %eax
        cmpl    $0, %edx
index 91f7563..6ff7e81 100644 (file)
@@ -6,7 +6,7 @@
 #define TRAMPOLINE_32BIT_PGTABLE_OFFSET        0
 
 #define TRAMPOLINE_32BIT_CODE_OFFSET   PAGE_SIZE
-#define TRAMPOLINE_32BIT_CODE_SIZE     0x60
+#define TRAMPOLINE_32BIT_CODE_SIZE     0x70
 
 #define TRAMPOLINE_32BIT_STACK_END     TRAMPOLINE_32BIT_SIZE
 
index 8eaf895..3991377 100644 (file)
@@ -361,7 +361,8 @@ ENTRY(entry_INT80_compat)
 
        /* Need to switch before accessing the thread stack. */
        SWITCH_TO_KERNEL_CR3 scratch_reg=%rdi
-       movq    %rsp, %rdi
+       /* In the Xen PV case we already run on the thread stack. */
+       ALTERNATIVE "movq %rsp, %rdi", "jmp .Lint80_keep_stack", X86_FEATURE_XENPV
        movq    PER_CPU_VAR(cpu_current_top_of_stack), %rsp
 
        pushq   6*8(%rdi)               /* regs->ss */
@@ -370,8 +371,9 @@ ENTRY(entry_INT80_compat)
        pushq   3*8(%rdi)               /* regs->cs */
        pushq   2*8(%rdi)               /* regs->ip */
        pushq   1*8(%rdi)               /* regs->orig_ax */
-
        pushq   (%rdi)                  /* pt_regs->di */
+.Lint80_keep_stack:
+
        pushq   %rsi                    /* pt_regs->si */
        xorl    %esi, %esi              /* nospec   si */
        pushq   %rdx                    /* pt_regs->dx */
index 374a197..b684f02 100644 (file)
@@ -2278,6 +2278,19 @@ void perf_check_microcode(void)
                x86_pmu.check_microcode();
 }
 
+static int x86_pmu_check_period(struct perf_event *event, u64 value)
+{
+       if (x86_pmu.check_period && x86_pmu.check_period(event, value))
+               return -EINVAL;
+
+       if (value && x86_pmu.limit_period) {
+               if (x86_pmu.limit_period(event, value) > value)
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
 static struct pmu pmu = {
        .pmu_enable             = x86_pmu_enable,
        .pmu_disable            = x86_pmu_disable,
@@ -2302,6 +2315,7 @@ static struct pmu pmu = {
        .event_idx              = x86_pmu_event_idx,
        .sched_task             = x86_pmu_sched_task,
        .task_ctx_size          = sizeof(struct x86_perf_task_context),
+       .check_period           = x86_pmu_check_period,
 };
 
 void arch_perf_update_userpage(struct perf_event *event,
index 40e12cf..730978d 100644 (file)
@@ -3559,6 +3559,14 @@ static void free_excl_cntrs(int cpu)
 
 static void intel_pmu_cpu_dying(int cpu)
 {
+       fini_debug_store_on_cpu(cpu);
+
+       if (x86_pmu.counter_freezing)
+               disable_counter_freeze();
+}
+
+static void intel_pmu_cpu_dead(int cpu)
+{
        struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
        struct intel_shared_regs *pc;
 
@@ -3570,11 +3578,6 @@ static void intel_pmu_cpu_dying(int cpu)
        }
 
        free_excl_cntrs(cpu);
-
-       fini_debug_store_on_cpu(cpu);
-
-       if (x86_pmu.counter_freezing)
-               disable_counter_freeze();
 }
 
 static void intel_pmu_sched_task(struct perf_event_context *ctx,
@@ -3584,6 +3587,11 @@ static void intel_pmu_sched_task(struct perf_event_context *ctx,
        intel_pmu_lbr_sched_task(ctx, sched_in);
 }
 
+static int intel_pmu_check_period(struct perf_event *event, u64 value)
+{
+       return intel_pmu_has_bts_period(event, value) ? -EINVAL : 0;
+}
+
 PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63");
 
 PMU_FORMAT_ATTR(ldlat, "config1:0-15");
@@ -3663,6 +3671,9 @@ static __initconst const struct x86_pmu core_pmu = {
        .cpu_prepare            = intel_pmu_cpu_prepare,
        .cpu_starting           = intel_pmu_cpu_starting,
        .cpu_dying              = intel_pmu_cpu_dying,
+       .cpu_dead               = intel_pmu_cpu_dead,
+
+       .check_period           = intel_pmu_check_period,
 };
 
 static struct attribute *intel_pmu_attrs[];
@@ -3703,8 +3714,12 @@ static __initconst const struct x86_pmu intel_pmu = {
        .cpu_prepare            = intel_pmu_cpu_prepare,
        .cpu_starting           = intel_pmu_cpu_starting,
        .cpu_dying              = intel_pmu_cpu_dying,
+       .cpu_dead               = intel_pmu_cpu_dead,
+
        .guest_get_msrs         = intel_guest_get_msrs,
        .sched_task             = intel_pmu_sched_task,
+
+       .check_period           = intel_pmu_check_period,
 };
 
 static __init void intel_clovertown_quirk(void)
index c07bee3..b10e043 100644 (file)
@@ -1222,6 +1222,8 @@ static struct pci_driver snbep_uncore_pci_driver = {
        .id_table       = snbep_uncore_pci_ids,
 };
 
+#define NODE_ID_MASK   0x7
+
 /*
  * build pci bus to socket mapping
  */
@@ -1243,7 +1245,7 @@ static int snbep_pci2phy_map_init(int devid, int nodeid_loc, int idmap_loc, bool
                err = pci_read_config_dword(ubox_dev, nodeid_loc, &config);
                if (err)
                        break;
-               nodeid = config;
+               nodeid = config & NODE_ID_MASK;
                /* get the Node ID mapping */
                err = pci_read_config_dword(ubox_dev, idmap_loc, &config);
                if (err)
index 78d7b70..d46fd67 100644 (file)
@@ -646,6 +646,11 @@ struct x86_pmu {
         * Intel host/guest support (KVM)
         */
        struct perf_guest_switch_msr *(*guest_get_msrs)(int *nr);
+
+       /*
+        * Check period value for PERF_EVENT_IOC_PERIOD ioctl.
+        */
+       int (*check_period) (struct perf_event *event, u64 period);
 };
 
 struct x86_perf_task_context {
@@ -857,7 +862,7 @@ static inline int amd_pmu_init(void)
 
 #ifdef CONFIG_CPU_SUP_INTEL
 
-static inline bool intel_pmu_has_bts(struct perf_event *event)
+static inline bool intel_pmu_has_bts_period(struct perf_event *event, u64 period)
 {
        struct hw_perf_event *hwc = &event->hw;
        unsigned int hw_event, bts_event;
@@ -868,7 +873,14 @@ static inline bool intel_pmu_has_bts(struct perf_event *event)
        hw_event = hwc->config & INTEL_ARCH_EVENT_MASK;
        bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS);
 
-       return hw_event == bts_event && hwc->sample_period == 1;
+       return hw_event == bts_event && period == 1;
+}
+
+static inline bool intel_pmu_has_bts(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       return intel_pmu_has_bts_period(event, hwc->sample_period);
 }
 
 int intel_pmu_save_and_restart(struct perf_event *event);
index f65b78d..7dbbe9f 100644 (file)
@@ -51,7 +51,7 @@ static unsigned long get_dr(int n)
 /*
  * fill in the user structure for a core dump..
  */
-static void dump_thread32(struct pt_regs *regs, struct user32 *dump)
+static void fill_dump(struct pt_regs *regs, struct user32 *dump)
 {
        u32 fs, gs;
        memset(dump, 0, sizeof(*dump));
@@ -157,10 +157,12 @@ static int aout_core_dump(struct coredump_params *cprm)
        fs = get_fs();
        set_fs(KERNEL_DS);
        has_dumped = 1;
+
+       fill_dump(cprm->regs, &dump);
+
        strncpy(dump.u_comm, current->comm, sizeof(current->comm));
        dump.u_ar0 = offsetof(struct user32, regs);
        dump.signal = cprm->siginfo->si_signo;
-       dump_thread32(cprm->regs, &dump);
 
        /*
         * If the size of the dump file exceeds the rlimit, then see
index 0dd6b0f..9f15384 100644 (file)
@@ -6,7 +6,7 @@
  * "Big Core" Processors (Branded as Core, Xeon, etc...)
  *
  * The "_X" parts are generally the EP and EX Xeons, or the
- * "Extreme" ones, like Broadwell-E.
+ * "Extreme" ones, like Broadwell-E, or Atom microserver.
  *
  * While adding a new CPUID for a new microarchitecture, add a new
  * group to keep logically sorted out in chronological order. Within
@@ -52,6 +52,8 @@
 
 #define INTEL_FAM6_CANNONLAKE_MOBILE   0x66
 
+#define INTEL_FAM6_ICELAKE_MOBILE      0x7E
+
 /* "Small Core" Processors (Atom) */
 
 #define INTEL_FAM6_ATOM_BONNELL                0x1C /* Diamondville, Pineview */
@@ -71,6 +73,7 @@
 #define INTEL_FAM6_ATOM_GOLDMONT       0x5C /* Apollo Lake */
 #define INTEL_FAM6_ATOM_GOLDMONT_X     0x5F /* Denverton */
 #define INTEL_FAM6_ATOM_GOLDMONT_PLUS  0x7A /* Gemini Lake */
+#define INTEL_FAM6_ATOM_TREMONT_X      0x86 /* Jacobsville */
 
 /* Xeon Phi */
 
index 0ca5061..19d18fa 100644 (file)
@@ -178,6 +178,10 @@ static inline void switch_ldt(struct mm_struct *prev, struct mm_struct *next)
 
 void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk);
 
+/*
+ * Init a new mm.  Used on mm copies, like at fork()
+ * and on mm's that are brand-new, like at execve().
+ */
 static inline int init_new_context(struct task_struct *tsk,
                                   struct mm_struct *mm)
 {
@@ -228,8 +232,22 @@ do {                                               \
 } while (0)
 #endif
 
+static inline void arch_dup_pkeys(struct mm_struct *oldmm,
+                                 struct mm_struct *mm)
+{
+#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
+       if (!cpu_feature_enabled(X86_FEATURE_OSPKE))
+               return;
+
+       /* Duplicate the oldmm pkey state in mm: */
+       mm->context.pkey_allocation_map = oldmm->context.pkey_allocation_map;
+       mm->context.execute_only_pkey   = oldmm->context.execute_only_pkey;
+#endif
+}
+
 static inline int arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
 {
+       arch_dup_pkeys(oldmm, mm);
        paravirt_arch_dup_mmap(oldmm, mm);
        return ldt_dup_context(oldmm, mm);
 }
index 8f65728..0ce558a 100644 (file)
@@ -7,7 +7,11 @@
 #endif
 
 #ifdef CONFIG_KASAN
+#ifdef CONFIG_KASAN_EXTRA
+#define KASAN_STACK_ORDER 2
+#else
 #define KASAN_STACK_ORDER 1
+#endif
 #else
 #define KASAN_STACK_ORDER 0
 #endif
index 40616e8..2779ace 100644 (file)
@@ -1065,7 +1065,7 @@ static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr,
 static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
                              pmd_t *pmdp, pmd_t pmd)
 {
-       native_set_pmd(pmdp, pmd);
+       set_pmd(pmdp, pmd);
 }
 
 static inline void set_pud_at(struct mm_struct *mm, unsigned long addr,
index 54990fe..f6b7fe2 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef _ASM_X86_RESCTRL_SCHED_H
 #define _ASM_X86_RESCTRL_SCHED_H
 
-#ifdef CONFIG_RESCTRL
+#ifdef CONFIG_X86_CPU_RESCTRL
 
 #include <linux/sched.h>
 #include <linux/jump_label.h>
@@ -88,6 +88,6 @@ static inline void resctrl_sched_in(void)
 
 static inline void resctrl_sched_in(void) {}
 
-#endif /* CONFIG_RESCTRL */
+#endif /* CONFIG_X86_CPU_RESCTRL */
 
 #endif /* _ASM_X86_RESCTRL_SCHED_H */
index a77445d..780f2b4 100644 (file)
@@ -711,7 +711,7 @@ static __must_check inline bool user_access_begin(const void __user *ptr, size_t
 {
        if (unlikely(!access_ok(ptr,len)))
                return 0;
-       __uaccess_begin();
+       __uaccess_begin_nospec();
        return 1;
 }
 #define user_access_begin(a,b) user_access_begin(a,b)
index e652a7c..3f697a9 100644 (file)
@@ -48,7 +48,8 @@ enum {
        BIOS_STATUS_SUCCESS             =  0,
        BIOS_STATUS_UNIMPLEMENTED       = -ENOSYS,
        BIOS_STATUS_EINVAL              = -EINVAL,
-       BIOS_STATUS_UNAVAIL             = -EBUSY
+       BIOS_STATUS_UNAVAIL             = -EBUSY,
+       BIOS_STATUS_ABORT               = -EINTR,
 };
 
 /* Address map parameters */
@@ -167,4 +168,9 @@ extern long system_serial_number;
 
 extern struct kobject *sgi_uv_kobj;    /* /sys/firmware/sgi_uv */
 
+/*
+ * EFI runtime lock; cf. firmware/efi/runtime-wrappers.c for details
+ */
+extern struct semaphore __efi_uv_runtime_lock;
+
 #endif /* _ASM_X86_UV_BIOS_H */
index ac78f90..cfd24f9 100644 (file)
@@ -39,7 +39,7 @@ obj-$(CONFIG_CPU_SUP_UMC_32)          += umc.o
 obj-$(CONFIG_X86_MCE)                  += mce/
 obj-$(CONFIG_MTRR)                     += mtrr/
 obj-$(CONFIG_MICROCODE)                        += microcode/
-obj-$(CONFIG_RESCTRL)                  += resctrl/
+obj-$(CONFIG_X86_CPU_RESCTRL)          += resctrl/
 
 obj-$(CONFIG_X86_LOCAL_APIC)           += perfctr-watchdog.o
 
index 8654b8b..01874d5 100644 (file)
@@ -71,7 +71,7 @@ void __init check_bugs(void)
         * identify_boot_cpu() initialized SMT support information, let the
         * core code know.
         */
-       cpu_smt_check_topology_early();
+       cpu_smt_check_topology();
 
        if (!IS_ENABLED(CONFIG_SMP)) {
                pr_info("CPU: ");
@@ -215,7 +215,7 @@ static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
 static enum spectre_v2_user_mitigation spectre_v2_user __ro_after_init =
        SPECTRE_V2_USER_NONE;
 
-#ifdef RETPOLINE
+#ifdef CONFIG_RETPOLINE
 static bool spectre_v2_bad_module;
 
 bool retpoline_module_ok(bool has_retpoline)
index 672c722..6ce290c 100644 (file)
@@ -784,6 +784,7 @@ static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp,
                        quirk_no_way_out(i, m, regs);
 
                if (mce_severity(m, mca_cfg.tolerant, &tmp, true) >= MCE_PANIC_SEVERITY) {
+                       m->bank = i;
                        mce_read_aux(m, i);
                        *msg = tmp;
                        return 1;
index 51adde0..e1f3ba1 100644 (file)
@@ -855,7 +855,7 @@ load_microcode_amd(bool save, u8 family, const u8 *data, size_t size)
        if (!p) {
                return ret;
        } else {
-               if (boot_cpu_data.microcode == p->patch_id)
+               if (boot_cpu_data.microcode >= p->patch_id)
                        return ret;
 
                ret = UCODE_NEW;
index 6895049..4a06c37 100644 (file)
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_RESCTRL)  += core.o rdtgroup.o monitor.o
-obj-$(CONFIG_RESCTRL)  += ctrlmondata.o pseudo_lock.o
+obj-$(CONFIG_X86_CPU_RESCTRL)  += core.o rdtgroup.o monitor.o
+obj-$(CONFIG_X86_CPU_RESCTRL)  += ctrlmondata.o pseudo_lock.o
 CFLAGS_pseudo_lock.o = -I$(src)
index c8b07d8..17ffc86 100644 (file)
@@ -470,6 +470,7 @@ int crash_load_segments(struct kimage *image)
 
        kbuf.memsz = kbuf.bufsz;
        kbuf.buf_align = ELF_CORE_HEADER_ALIGN;
+       kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
        ret = kexec_add_buffer(&kbuf);
        if (ret) {
                vfree((void *)image->arch.elf_headers);
index b0acb22..dfd3aca 100644 (file)
 
 #define HPET_MASK                      CLOCKSOURCE_MASK(32)
 
-/* FSEC = 10^-15
-   NSEC = 10^-9 */
-#define FSEC_PER_NSEC                  1000000L
-
 #define HPET_DEV_USED_BIT              2
 #define HPET_DEV_USED                  (1 << HPET_DEV_USED_BIT)
 #define HPET_DEV_VALID                 0x8
index 278cd07..53917a3 100644 (file)
@@ -167,6 +167,9 @@ setup_efi_state(struct boot_params *params, unsigned long params_load_addr,
        struct efi_info *current_ei = &boot_params.efi_info;
        struct efi_info *ei = &params->efi_info;
 
+       if (!efi_enabled(EFI_RUNTIME_SERVICES))
+               return 0;
+
        if (!current_ei->efi_memmap_size)
                return 0;
 
@@ -434,6 +437,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
        kbuf.memsz = PAGE_ALIGN(header->init_size);
        kbuf.buf_align = header->kernel_alignment;
        kbuf.buf_min = MIN_KERNEL_LOAD_ADDR;
+       kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
        ret = kexec_add_buffer(&kbuf);
        if (ret)
                goto out_free_params;
@@ -448,6 +452,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
                kbuf.bufsz = kbuf.memsz = initrd_len;
                kbuf.buf_align = PAGE_SIZE;
                kbuf.buf_min = MIN_INITRD_LOAD_ADDR;
+               kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
                ret = kexec_add_buffer(&kbuf);
                if (ret)
                        goto out_free_params;
index ba4bfb7..5c93a65 100644 (file)
@@ -457,6 +457,7 @@ static void __send_ipi_mask(const struct cpumask *mask, int vector)
 #else
        u64 ipi_bitmap = 0;
 #endif
+       long ret;
 
        if (cpumask_empty(mask))
                return;
@@ -482,8 +483,9 @@ static void __send_ipi_mask(const struct cpumask *mask, int vector)
                } else if (apic_id < min + KVM_IPI_CLUSTER_SIZE) {
                        max = apic_id < max ? max : apic_id;
                } else {
-                       kvm_hypercall4(KVM_HC_SEND_IPI, (unsigned long)ipi_bitmap,
+                       ret = kvm_hypercall4(KVM_HC_SEND_IPI, (unsigned long)ipi_bitmap,
                                (unsigned long)(ipi_bitmap >> BITS_PER_LONG), min, icr);
+                       WARN_ONCE(ret < 0, "KVM: failed to send PV IPI: %ld", ret);
                        min = max = apic_id;
                        ipi_bitmap = 0;
                }
@@ -491,8 +493,9 @@ static void __send_ipi_mask(const struct cpumask *mask, int vector)
        }
 
        if (ipi_bitmap) {
-               kvm_hypercall4(KVM_HC_SEND_IPI, (unsigned long)ipi_bitmap,
+               ret = kvm_hypercall4(KVM_HC_SEND_IPI, (unsigned long)ipi_bitmap,
                        (unsigned long)(ipi_bitmap >> BITS_PER_LONG), min, icr);
+               WARN_ONCE(ret < 0, "KVM: failed to send PV IPI: %ld", ret);
        }
 
        local_irq_restore(flags);
index e9f777b..3fae238 100644 (file)
@@ -297,15 +297,16 @@ static int __init tsc_setup(char *str)
 
 __setup("tsc=", tsc_setup);
 
-#define MAX_RETRIES     5
-#define SMI_TRESHOLD    50000
+#define MAX_RETRIES            5
+#define TSC_DEFAULT_THRESHOLD  0x20000
 
 /*
- * Read TSC and the reference counters. Take care of SMI disturbance
+ * Read TSC and the reference counters. Take care of any disturbances
  */
 static u64 tsc_read_refs(u64 *p, int hpet)
 {
        u64 t1, t2;
+       u64 thresh = tsc_khz ? tsc_khz >> 5 : TSC_DEFAULT_THRESHOLD;
        int i;
 
        for (i = 0; i < MAX_RETRIES; i++) {
@@ -315,7 +316,7 @@ static u64 tsc_read_refs(u64 *p, int hpet)
                else
                        *p = acpi_pm_read_early();
                t2 = get_cycles();
-               if ((t2 - t1) < SMI_TRESHOLD)
+               if ((t2 - t1) < thresh)
                        return t2;
        }
        return ULLONG_MAX;
@@ -703,15 +704,15 @@ static unsigned long pit_hpet_ptimer_calibrate_cpu(void)
         * zero. In each wait loop iteration we read the TSC and check
         * the delta to the previous read. We keep track of the min
         * and max values of that delta. The delta is mostly defined
-        * by the IO time of the PIT access, so we can detect when a
-        * SMI/SMM disturbance happened between the two reads. If the
+        * by the IO time of the PIT access, so we can detect when
+        * any disturbance happened between the two reads. If the
         * maximum time is significantly larger than the minimum time,
         * then we discard the result and have another try.
         *
         * 2) Reference counter. If available we use the HPET or the
         * PMTIMER as a reference to check the sanity of that value.
         * We use separate TSC readouts and check inside of the
-        * reference read for a SMI/SMM disturbance. We dicard
+        * reference read for any possible disturbance. We dicard
         * disturbed values here as well. We do that around the PIT
         * calibration delay loop as we have to wait for a certain
         * amount of time anyway.
@@ -744,7 +745,7 @@ static unsigned long pit_hpet_ptimer_calibrate_cpu(void)
                if (ref1 == ref2)
                        continue;
 
-               /* Check, whether the sampling was disturbed by an SMI */
+               /* Check, whether the sampling was disturbed */
                if (tsc1 == ULLONG_MAX || tsc2 == ULLONG_MAX)
                        continue;
 
@@ -1268,7 +1269,7 @@ static DECLARE_DELAYED_WORK(tsc_irqwork, tsc_refine_calibration_work);
  */
 static void tsc_refine_calibration_work(struct work_struct *work)
 {
-       static u64 tsc_start = -1, ref_start;
+       static u64 tsc_start = ULLONG_MAX, ref_start;
        static int hpet;
        u64 tsc_stop, ref_stop, delta;
        unsigned long freq;
@@ -1283,14 +1284,15 @@ static void tsc_refine_calibration_work(struct work_struct *work)
         * delayed the first time we expire. So set the workqueue
         * again once we know timers are working.
         */
-       if (tsc_start == -1) {
+       if (tsc_start == ULLONG_MAX) {
+restart:
                /*
                 * Only set hpet once, to avoid mixing hardware
                 * if the hpet becomes enabled later.
                 */
                hpet = is_hpet_enabled();
-               schedule_delayed_work(&tsc_irqwork, HZ);
                tsc_start = tsc_read_refs(&ref_start, hpet);
+               schedule_delayed_work(&tsc_irqwork, HZ);
                return;
        }
 
@@ -1300,9 +1302,9 @@ static void tsc_refine_calibration_work(struct work_struct *work)
        if (ref_start == ref_stop)
                goto out;
 
-       /* Check, whether the sampling was disturbed by an SMI */
-       if (tsc_start == ULLONG_MAX || tsc_stop == ULLONG_MAX)
-               goto out;
+       /* Check, whether the sampling was disturbed */
+       if (tsc_stop == ULLONG_MAX)
+               goto restart;
 
        delta = tsc_stop - tsc_start;
        delta *= 1000000LL;
index 69b3a7c..31ecf7a 100644 (file)
@@ -2,10 +2,6 @@
 
 ccflags-y += -Iarch/x86/kvm
 
-CFLAGS_x86.o := -I.
-CFLAGS_svm.o := -I.
-CFLAGS_vmx.o := -I.
-
 KVM := ../../../virt/kvm
 
 kvm-y                  += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \
index c90a535..89d20ed 100644 (file)
@@ -1636,7 +1636,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
                ret = kvm_hvcall_signal_event(vcpu, fast, ingpa);
                if (ret != HV_STATUS_INVALID_PORT_ID)
                        break;
-               /* maybe userspace knows this conn_id: fall through */
+               /* fall through - maybe userspace knows this conn_id. */
        case HVCALL_POST_MESSAGE:
                /* don't bother userspace if it has no way to handle it */
                if (unlikely(rep || !vcpu_to_synic(vcpu)->active)) {
@@ -1832,7 +1832,6 @@ int kvm_vcpu_ioctl_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
                        ent->eax |= HV_X64_MSR_VP_INDEX_AVAILABLE;
                        ent->eax |= HV_X64_MSR_RESET_AVAILABLE;
                        ent->eax |= HV_MSR_REFERENCE_TSC_AVAILABLE;
-                       ent->eax |= HV_X64_MSR_GUEST_IDLE_AVAILABLE;
                        ent->eax |= HV_X64_ACCESS_FREQUENCY_MSRS;
                        ent->eax |= HV_X64_ACCESS_REENLIGHTENMENT;
 
@@ -1848,11 +1847,11 @@ int kvm_vcpu_ioctl_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
                case HYPERV_CPUID_ENLIGHTMENT_INFO:
                        ent->eax |= HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED;
                        ent->eax |= HV_X64_APIC_ACCESS_RECOMMENDED;
-                       ent->eax |= HV_X64_SYSTEM_RESET_RECOMMENDED;
                        ent->eax |= HV_X64_RELAXED_TIMING_RECOMMENDED;
                        ent->eax |= HV_X64_CLUSTER_IPI_RECOMMENDED;
                        ent->eax |= HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED;
-                       ent->eax |= HV_X64_ENLIGHTENED_VMCS_RECOMMENDED;
+                       if (evmcs_ver)
+                               ent->eax |= HV_X64_ENLIGHTENED_VMCS_RECOMMENDED;
 
                        /*
                         * Default number of spinlock retry attempts, matches
index 9f089e2..4b6c2da 100644 (file)
@@ -1035,6 +1035,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
        switch (delivery_mode) {
        case APIC_DM_LOWEST:
                vcpu->arch.apic_arb_prio++;
+               /* fall through */
        case APIC_DM_FIXED:
                if (unlikely(trig_mode && !level))
                        break;
@@ -1874,6 +1875,7 @@ int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 
        case APIC_LVT0:
                apic_manage_nmi_watchdog(apic, val);
+               /* fall through */
        case APIC_LVTTHMR:
        case APIC_LVTPC:
        case APIC_LVT1:
index ce770b4..da9c423 100644 (file)
@@ -4371,6 +4371,7 @@ __reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
                        rsvd_bits(maxphyaddr, 51);
                rsvd_check->rsvd_bits_mask[1][4] =
                        rsvd_check->rsvd_bits_mask[0][4];
+               /* fall through */
        case PT64_ROOT_4LEVEL:
                rsvd_check->rsvd_bits_mask[0][3] = exb_bit_rsvd |
                        nonleaf_bit8_rsvd | rsvd_bits(7, 7) |
index 307e5bd..f13a3a2 100644 (file)
@@ -3414,6 +3414,14 @@ static int nested_svm_vmexit(struct vcpu_svm *svm)
        kvm_mmu_reset_context(&svm->vcpu);
        kvm_mmu_load(&svm->vcpu);
 
+       /*
+        * Drop what we picked up for L2 via svm_complete_interrupts() so it
+        * doesn't end up in L1.
+        */
+       svm->vcpu.arch.nmi_injected = false;
+       kvm_clear_exception_queue(&svm->vcpu);
+       kvm_clear_interrupt_queue(&svm->vcpu);
+
        return 0;
 }
 
@@ -4395,7 +4403,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
        case MSR_IA32_APICBASE:
                if (kvm_vcpu_apicv_active(vcpu))
                        avic_update_vapic_bar(to_svm(vcpu), data);
-               /* Follow through */
+               /* Fall through */
        default:
                return kvm_set_msr_common(vcpu, msr);
        }
@@ -4504,28 +4512,19 @@ static int avic_incomplete_ipi_interception(struct vcpu_svm *svm)
                kvm_lapic_reg_write(apic, APIC_ICR, icrl);
                break;
        case AVIC_IPI_FAILURE_TARGET_NOT_RUNNING: {
-               int i;
-               struct kvm_vcpu *vcpu;
-               struct kvm *kvm = svm->vcpu.kvm;
                struct kvm_lapic *apic = svm->vcpu.arch.apic;
 
                /*
-                * At this point, we expect that the AVIC HW has already
-                * set the appropriate IRR bits on the valid target
-                * vcpus. So, we just need to kick the appropriate vcpu.
+                * Update ICR high and low, then emulate sending IPI,
+                * which is handled when writing APIC_ICR.
                 */
-               kvm_for_each_vcpu(i, vcpu, kvm) {
-                       bool m = kvm_apic_match_dest(vcpu, apic,
-                                                    icrl & KVM_APIC_SHORT_MASK,
-                                                    GET_APIC_DEST_FIELD(icrh),
-                                                    icrl & KVM_APIC_DEST_MASK);
-
-                       if (m && !avic_vcpu_is_running(vcpu))
-                               kvm_vcpu_wake_up(vcpu);
-               }
+               kvm_lapic_reg_write(apic, APIC_ICR2, icrh);
+               kvm_lapic_reg_write(apic, APIC_ICR, icrl);
                break;
        }
        case AVIC_IPI_FAILURE_INVALID_TARGET:
+               WARN_ONCE(1, "Invalid IPI target: index=%u, vcpu=%d, icr=%#0x:%#0x\n",
+                         index, svm->vcpu.vcpu_id, icrh, icrl);
                break;
        case AVIC_IPI_FAILURE_INVALID_BACKING_PAGE:
                WARN_ONCE(1, "Invalid backing page\n");
@@ -6278,6 +6277,9 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp)
        int asid, ret;
 
        ret = -EBUSY;
+       if (unlikely(sev->active))
+               return ret;
+
        asid = sev_asid_new();
        if (asid < 0)
                return ret;
index 705f40a..6432d08 100644 (file)
@@ -1465,7 +1465,7 @@ TRACE_EVENT(kvm_hv_send_ipi_ex,
 #endif /* _TRACE_KVM_H */
 
 #undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH arch/x86/kvm
+#define TRACE_INCLUDE_PATH ../../arch/x86/kvm
 #undef TRACE_INCLUDE_FILE
 #define TRACE_INCLUDE_FILE trace
 
index 95bc224..5466c6d 100644 (file)
@@ -332,16 +332,17 @@ int nested_enable_evmcs(struct kvm_vcpu *vcpu,
                        uint16_t *vmcs_version)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
+       bool evmcs_already_enabled = vmx->nested.enlightened_vmcs_enabled;
+
+       vmx->nested.enlightened_vmcs_enabled = true;
 
        if (vmcs_version)
                *vmcs_version = nested_get_evmcs_version(vcpu);
 
        /* We don't support disabling the feature for simplicity. */
-       if (vmx->nested.enlightened_vmcs_enabled)
+       if (evmcs_already_enabled)
                return 0;
 
-       vmx->nested.enlightened_vmcs_enabled = true;
-
        vmx->nested.msrs.pinbased_ctls_high &= ~EVMCS1_UNSUPPORTED_PINCTRL;
        vmx->nested.msrs.entry_ctls_high &= ~EVMCS1_UNSUPPORTED_VMENTRY_CTRL;
        vmx->nested.msrs.exit_ctls_high &= ~EVMCS1_UNSUPPORTED_VMEXIT_CTRL;
index 3170e29..d737a51 100644 (file)
@@ -55,7 +55,7 @@ static u16 shadow_read_write_fields[] = {
 static int max_shadow_read_write_fields =
        ARRAY_SIZE(shadow_read_write_fields);
 
-void init_vmcs_shadow_fields(void)
+static void init_vmcs_shadow_fields(void)
 {
        int i, j;
 
@@ -211,6 +211,7 @@ static void free_nested(struct kvm_vcpu *vcpu)
        if (!vmx->nested.vmxon && !vmx->nested.smm.vmxon)
                return;
 
+       hrtimer_cancel(&vmx->nested.preemption_timer);
        vmx->nested.vmxon = false;
        vmx->nested.smm.vmxon = false;
        free_vpid(vmx->nested.vpid02);
@@ -2472,6 +2473,10 @@ static int nested_check_vm_execution_controls(struct kvm_vcpu *vcpu,
            (nested_cpu_has_vpid(vmcs12) && !vmcs12->virtual_processor_id))
                return -EINVAL;
 
+       if (!nested_cpu_has_preemption_timer(vmcs12) &&
+           nested_cpu_has_save_preemption_timer(vmcs12))
+               return -EINVAL;
+
        if (nested_cpu_has_ept(vmcs12) &&
            !valid_ept_address(vcpu, vmcs12->ept_pointer))
                return -EINVAL;
@@ -4140,11 +4145,11 @@ static int enter_vmx_operation(struct kvm_vcpu *vcpu)
        if (r < 0)
                goto out_vmcs02;
 
-       vmx->nested.cached_vmcs12 = kmalloc(VMCS12_SIZE, GFP_KERNEL);
+       vmx->nested.cached_vmcs12 = kzalloc(VMCS12_SIZE, GFP_KERNEL);
        if (!vmx->nested.cached_vmcs12)
                goto out_cached_vmcs12;
 
-       vmx->nested.cached_shadow_vmcs12 = kmalloc(VMCS12_SIZE, GFP_KERNEL);
+       vmx->nested.cached_shadow_vmcs12 = kzalloc(VMCS12_SIZE, GFP_KERNEL);
        if (!vmx->nested.cached_shadow_vmcs12)
                goto out_cached_shadow_vmcs12;
 
@@ -4540,9 +4545,8 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu)
                         * given physical address won't match the required
                         * VMCS12_REVISION identifier.
                         */
-                       nested_vmx_failValid(vcpu,
+                       return nested_vmx_failValid(vcpu,
                                VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID);
-                       return kvm_skip_emulated_instruction(vcpu);
                }
                new_vmcs12 = kmap(page);
                if (new_vmcs12->hdr.revision_id != VMCS12_REVISION ||
@@ -5264,13 +5268,17 @@ static int vmx_get_nested_state(struct kvm_vcpu *vcpu,
                        copy_shadow_to_vmcs12(vmx);
        }
 
-       if (copy_to_user(user_kvm_nested_state->data, vmcs12, sizeof(*vmcs12)))
+       /*
+        * Copy over the full allocated size of vmcs12 rather than just the size
+        * of the struct.
+        */
+       if (copy_to_user(user_kvm_nested_state->data, vmcs12, VMCS12_SIZE))
                return -EFAULT;
 
        if (nested_cpu_has_shadow_vmcs(vmcs12) &&
            vmcs12->vmcs_link_pointer != -1ull) {
                if (copy_to_user(user_kvm_nested_state->data + VMCS12_SIZE,
-                                get_shadow_vmcs12(vcpu), sizeof(*vmcs12)))
+                                get_shadow_vmcs12(vcpu), VMCS12_SIZE))
                        return -EFAULT;
        }
 
@@ -5553,9 +5561,11 @@ void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps,
         * secondary cpu-based controls.  Do not include those that
         * depend on CPUID bits, they are added later by vmx_cpuid_update.
         */
-       rdmsr(MSR_IA32_VMX_PROCBASED_CTLS2,
-               msrs->secondary_ctls_low,
-               msrs->secondary_ctls_high);
+       if (msrs->procbased_ctls_high & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS)
+               rdmsr(MSR_IA32_VMX_PROCBASED_CTLS2,
+                     msrs->secondary_ctls_low,
+                     msrs->secondary_ctls_high);
+
        msrs->secondary_ctls_low = 0;
        msrs->secondary_ctls_high &=
                SECONDARY_EXEC_DESC |
index 4d39f73..30a6bcd 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/mod_devicetable.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
+#include <linux/sched/smt.h>
 #include <linux/slab.h>
 #include <linux/tboot.h>
 #include <linux/trace_events.h>
@@ -423,7 +424,7 @@ static void check_ept_pointer_match(struct kvm *kvm)
        to_kvm_vmx(kvm)->ept_pointers_match = EPT_POINTERS_MATCH;
 }
 
-int kvm_fill_hv_flush_list_func(struct hv_guest_mapping_flush_list *flush,
+static int kvm_fill_hv_flush_list_func(struct hv_guest_mapping_flush_list *flush,
                void *data)
 {
        struct kvm_tlb_range *range = data;
@@ -453,7 +454,7 @@ static int hv_remote_flush_tlb_with_range(struct kvm *kvm,
                struct kvm_tlb_range *range)
 {
        struct kvm_vcpu *vcpu;
-       int ret = -ENOTSUPP, i;
+       int ret = 0, i;
 
        spin_lock(&to_kvm_vmx(kvm)->ept_pointer_lock);
 
@@ -862,7 +863,8 @@ static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr,
        if (!entry_only)
                j = find_msr(&m->host, msr);
 
-       if (i == NR_AUTOLOAD_MSRS || j == NR_AUTOLOAD_MSRS) {
+       if ((i < 0 && m->guest.nr == NR_AUTOLOAD_MSRS) ||
+               (j < 0 &&  m->host.nr == NR_AUTOLOAD_MSRS)) {
                printk_once(KERN_WARNING "Not enough msr switch entries. "
                                "Can't add msr %x\n", msr);
                return;
@@ -1192,21 +1194,6 @@ static void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
        if (!pi_test_sn(pi_desc) && vcpu->cpu == cpu)
                return;
 
-       /*
-        * First handle the simple case where no cmpxchg is necessary; just
-        * allow posting non-urgent interrupts.
-        *
-        * If the 'nv' field is POSTED_INTR_WAKEUP_VECTOR, do not change
-        * PI.NDST: pi_post_block will do it for us and the wakeup_handler
-        * expects the VCPU to be on the blocked_vcpu_list that matches
-        * PI.NDST.
-        */
-       if (pi_desc->nv == POSTED_INTR_WAKEUP_VECTOR ||
-           vcpu->cpu == cpu) {
-               pi_clear_sn(pi_desc);
-               return;
-       }
-
        /* The full case.  */
        do {
                old.control = new.control = pi_desc->control;
@@ -1221,6 +1208,17 @@ static void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
                new.sn = 0;
        } while (cmpxchg64(&pi_desc->control, old.control,
                           new.control) != old.control);
+
+       /*
+        * Clear SN before reading the bitmap.  The VT-d firmware
+        * writes the bitmap and reads SN atomically (5.2.3 in the
+        * spec), so it doesn't really have a memory barrier that
+        * pairs with this, but we cannot do that and we need one.
+        */
+       smp_mb__after_atomic();
+
+       if (!bitmap_empty((unsigned long *)pi_desc->pir, NR_VECTORS))
+               pi_set_on(pi_desc);
 }
 
 /*
@@ -1773,7 +1771,7 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                if (!msr_info->host_initiated &&
                    !guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP))
                        return 1;
-               /* Otherwise falls through */
+               /* Else, falls through */
        default:
                msr = find_msr_entry(vmx, msr_info->index);
                if (msr) {
@@ -2014,7 +2012,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                /* Check reserved bit, higher 32 bits should be zero */
                if ((data >> 32) != 0)
                        return 1;
-               /* Otherwise falls through */
+               /* Else, falls through */
        default:
                msr = find_msr_entry(vmx, msr_index);
                if (msr) {
@@ -2344,7 +2342,7 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
                case 37: /* AAT100 */
                case 44: /* BC86,AAY89,BD102 */
                case 46: /* BA97 */
-                       _vmexit_control &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
+                       _vmentry_control &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
                        _vmexit_control &= ~VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL;
                        pr_warn_once("kvm: VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL "
                                        "does not work properly. Using workaround\n");
@@ -6362,72 +6360,9 @@ static void vmx_update_hv_timer(struct kvm_vcpu *vcpu)
        vmx->loaded_vmcs->hv_timer_armed = false;
 }
 
-static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
+static void __vmx_vcpu_run(struct kvm_vcpu *vcpu, struct vcpu_vmx *vmx)
 {
-       struct vcpu_vmx *vmx = to_vmx(vcpu);
-       unsigned long cr3, cr4, evmcs_rsp;
-
-       /* Record the guest's net vcpu time for enforced NMI injections. */
-       if (unlikely(!enable_vnmi &&
-                    vmx->loaded_vmcs->soft_vnmi_blocked))
-               vmx->loaded_vmcs->entry_time = ktime_get();
-
-       /* Don't enter VMX if guest state is invalid, let the exit handler
-          start emulation until we arrive back to a valid state */
-       if (vmx->emulation_required)
-               return;
-
-       if (vmx->ple_window_dirty) {
-               vmx->ple_window_dirty = false;
-               vmcs_write32(PLE_WINDOW, vmx->ple_window);
-       }
-
-       if (vmx->nested.need_vmcs12_sync)
-               nested_sync_from_vmcs12(vcpu);
-
-       if (test_bit(VCPU_REGS_RSP, (unsigned long *)&vcpu->arch.regs_dirty))
-               vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]);
-       if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty))
-               vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]);
-
-       cr3 = __get_current_cr3_fast();
-       if (unlikely(cr3 != vmx->loaded_vmcs->host_state.cr3)) {
-               vmcs_writel(HOST_CR3, cr3);
-               vmx->loaded_vmcs->host_state.cr3 = cr3;
-       }
-
-       cr4 = cr4_read_shadow();
-       if (unlikely(cr4 != vmx->loaded_vmcs->host_state.cr4)) {
-               vmcs_writel(HOST_CR4, cr4);
-               vmx->loaded_vmcs->host_state.cr4 = cr4;
-       }
-
-       /* When single-stepping over STI and MOV SS, we must clear the
-        * corresponding interruptibility bits in the guest state. Otherwise
-        * vmentry fails as it then expects bit 14 (BS) in pending debug
-        * exceptions being set, but that's not correct for the guest debugging
-        * case. */
-       if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
-               vmx_set_interrupt_shadow(vcpu, 0);
-
-       if (static_cpu_has(X86_FEATURE_PKU) &&
-           kvm_read_cr4_bits(vcpu, X86_CR4_PKE) &&
-           vcpu->arch.pkru != vmx->host_pkru)
-               __write_pkru(vcpu->arch.pkru);
-
-       pt_guest_enter(vmx);
-
-       atomic_switch_perf_msrs(vmx);
-
-       vmx_update_hv_timer(vcpu);
-
-       /*
-        * If this vCPU has touched SPEC_CTRL, restore the guest's value if
-        * it's non-zero. Since vmentry is serialising on affected CPUs, there
-        * is no need to worry about the conditional branch over the wrmsr
-        * being speculatively taken.
-        */
-       x86_spec_ctrl_set_guest(vmx->spec_ctrl, 0);
+       unsigned long evmcs_rsp;
 
        vmx->__launched = vmx->loaded_vmcs->launched;
 
@@ -6567,6 +6502,77 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
                , "eax", "ebx", "edi"
 #endif
              );
+}
+STACK_FRAME_NON_STANDARD(__vmx_vcpu_run);
+
+static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
+{
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+       unsigned long cr3, cr4;
+
+       /* Record the guest's net vcpu time for enforced NMI injections. */
+       if (unlikely(!enable_vnmi &&
+                    vmx->loaded_vmcs->soft_vnmi_blocked))
+               vmx->loaded_vmcs->entry_time = ktime_get();
+
+       /* Don't enter VMX if guest state is invalid, let the exit handler
+          start emulation until we arrive back to a valid state */
+       if (vmx->emulation_required)
+               return;
+
+       if (vmx->ple_window_dirty) {
+               vmx->ple_window_dirty = false;
+               vmcs_write32(PLE_WINDOW, vmx->ple_window);
+       }
+
+       if (vmx->nested.need_vmcs12_sync)
+               nested_sync_from_vmcs12(vcpu);
+
+       if (test_bit(VCPU_REGS_RSP, (unsigned long *)&vcpu->arch.regs_dirty))
+               vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]);
+       if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty))
+               vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]);
+
+       cr3 = __get_current_cr3_fast();
+       if (unlikely(cr3 != vmx->loaded_vmcs->host_state.cr3)) {
+               vmcs_writel(HOST_CR3, cr3);
+               vmx->loaded_vmcs->host_state.cr3 = cr3;
+       }
+
+       cr4 = cr4_read_shadow();
+       if (unlikely(cr4 != vmx->loaded_vmcs->host_state.cr4)) {
+               vmcs_writel(HOST_CR4, cr4);
+               vmx->loaded_vmcs->host_state.cr4 = cr4;
+       }
+
+       /* When single-stepping over STI and MOV SS, we must clear the
+        * corresponding interruptibility bits in the guest state. Otherwise
+        * vmentry fails as it then expects bit 14 (BS) in pending debug
+        * exceptions being set, but that's not correct for the guest debugging
+        * case. */
+       if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
+               vmx_set_interrupt_shadow(vcpu, 0);
+
+       if (static_cpu_has(X86_FEATURE_PKU) &&
+           kvm_read_cr4_bits(vcpu, X86_CR4_PKE) &&
+           vcpu->arch.pkru != vmx->host_pkru)
+               __write_pkru(vcpu->arch.pkru);
+
+       pt_guest_enter(vmx);
+
+       atomic_switch_perf_msrs(vmx);
+
+       vmx_update_hv_timer(vcpu);
+
+       /*
+        * If this vCPU has touched SPEC_CTRL, restore the guest's value if
+        * it's non-zero. Since vmentry is serialising on affected CPUs, there
+        * is no need to worry about the conditional branch over the wrmsr
+        * being speculatively taken.
+        */
+       x86_spec_ctrl_set_guest(vmx->spec_ctrl, 0);
+
+       __vmx_vcpu_run(vcpu, vmx);
 
        /*
         * We do not use IBRS in the kernel. If this vCPU has used the
@@ -6648,7 +6654,6 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
        vmx_recover_nmi_blocking(vmx);
        vmx_complete_interrupts(vmx);
 }
-STACK_FRAME_NON_STANDARD(vmx_vcpu_run);
 
 static struct kvm *vmx_vm_alloc(void)
 {
@@ -6816,7 +6821,7 @@ static int vmx_vm_init(struct kvm *kvm)
                         * Warn upon starting the first VM in a potentially
                         * insecure environment.
                         */
-                       if (cpu_smt_control == CPU_SMT_ENABLED)
+                       if (sched_smt_active())
                                pr_warn_once(L1TF_MSG_SMT);
                        if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_NEVER)
                                pr_warn_once(L1TF_MSG_L1D);
@@ -7044,7 +7049,7 @@ static void update_intel_pt_cfg(struct kvm_vcpu *vcpu)
 
        /* unmask address range configure area */
        for (i = 0; i < vmx->pt_desc.addr_range; i++)
-               vmx->pt_desc.ctl_bitmask &= ~(0xf << (32 + i * 4));
+               vmx->pt_desc.ctl_bitmask &= ~(0xfULL << (32 + i * 4));
 }
 
 static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
index 9932895..0ac0a64 100644 (file)
@@ -337,16 +337,16 @@ static inline int pi_test_and_set_pir(int vector, struct pi_desc *pi_desc)
        return test_and_set_bit(vector, (unsigned long *)pi_desc->pir);
 }
 
-static inline void pi_clear_sn(struct pi_desc *pi_desc)
+static inline void pi_set_sn(struct pi_desc *pi_desc)
 {
-       return clear_bit(POSTED_INTR_SN,
+       return set_bit(POSTED_INTR_SN,
                        (unsigned long *)&pi_desc->control);
 }
 
-static inline void pi_set_sn(struct pi_desc *pi_desc)
+static inline void pi_set_on(struct pi_desc *pi_desc)
 {
-       return set_bit(POSTED_INTR_SN,
-                       (unsigned long *)&pi_desc->control);
+       set_bit(POSTED_INTR_ON,
+               (unsigned long *)&pi_desc->control);
 }
 
 static inline void pi_clear_on(struct pi_desc *pi_desc)
index 02c8e09..941f932 100644 (file)
@@ -3834,6 +3834,8 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
        case KVM_CAP_HYPERV_SYNIC2:
                if (cap->args[0])
                        return -EINVAL;
+               /* fall through */
+
        case KVM_CAP_HYPERV_SYNIC:
                if (!irqchip_in_kernel(vcpu->kvm))
                        return -EINVAL;
@@ -5114,6 +5116,13 @@ int kvm_read_guest_virt(struct kvm_vcpu *vcpu,
 {
        u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
 
+       /*
+        * 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_read_guest_virt_helper(addr, val, bytes, vcpu, access,
                                          exception);
 }
@@ -6480,8 +6489,7 @@ restart:
                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 || (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)))
+               if (r == EMULATE_DONE && ctxt->tf)
                        kvm_vcpu_do_singlestep(vcpu, &r);
                if (!ctxt->have_exception ||
                    exception_type(ctxt->exception.vector) == EXCPT_TRAP)
@@ -7093,10 +7101,10 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
        case KVM_HC_CLOCK_PAIRING:
                ret = kvm_pv_clock_pairing(vcpu, a0, a1);
                break;
+#endif
        case KVM_HC_SEND_IPI:
                ret = kvm_pv_send_ipi(vcpu->kvm, a0, a1, a2, a3, op_64_bit);
                break;
-#endif
        default:
                ret = -KVM_ENOSYS;
                break;
@@ -7793,7 +7801,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
         * 1) We should set ->mode before checking ->requests.  Please see
         * the comment in kvm_vcpu_exiting_guest_mode().
         *
-        * 2) For APICv, we should set ->mode before checking PIR.ON.  This
+        * 2) For APICv, we should set ->mode before checking PID.ON. This
         * pairs with the memory barrier implicit in pi_test_and_set_on
         * (see vmx_deliver_posted_interrupt).
         *
@@ -7937,6 +7945,7 @@ static inline int vcpu_block(struct kvm *kvm, struct kvm_vcpu *vcpu)
                vcpu->arch.pv.pv_unhalted = false;
                vcpu->arch.mp_state =
                        KVM_MP_STATE_RUNNABLE;
+               /* fall through */
        case KVM_MP_STATE_RUNNABLE:
                vcpu->arch.apf.halted = false;
                break;
index 6689467..df50451 100644 (file)
@@ -2,8 +2,11 @@
 #include <linux/module.h>
 #include <linux/io.h>
 
+#define movs(type,to,from) \
+       asm volatile("movs" type:"=&D" (to), "=&S" (from):"0" (to), "1" (from):"memory")
+
 /* Originally from i386/string.h */
-static __always_inline void __iomem_memcpy(void *to, const void *from, size_t n)
+static __always_inline void rep_movs(void *to, const void *from, size_t n)
 {
        unsigned long d0, d1, d2;
        asm volatile("rep ; movsl\n\t"
@@ -21,13 +24,37 @@ static __always_inline void __iomem_memcpy(void *to, const void *from, size_t n)
 
 void memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
 {
-       __iomem_memcpy(to, (const void *)from, n);
+       if (unlikely(!n))
+               return;
+
+       /* Align any unaligned source IO */
+       if (unlikely(1 & (unsigned long)from)) {
+               movs("b", to, from);
+               n--;
+       }
+       if (n > 1 && unlikely(2 & (unsigned long)from)) {
+               movs("w", to, from);
+               n-=2;
+       }
+       rep_movs(to, (const void *)from, n);
 }
 EXPORT_SYMBOL(memcpy_fromio);
 
 void memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
 {
-       __iomem_memcpy((void *)to, (const void *) from, n);
+       if (unlikely(!n))
+               return;
+
+       /* Align any unaligned destination IO */
+       if (unlikely(1 & (unsigned long)to)) {
+               movs("b", to, from);
+               n--;
+       }
+       if (n > 1 && unlikely(2 & (unsigned long)to)) {
+               movs("w", to, from);
+               n-=2;
+       }
+       rep_movs((void *)to, (const void *) from, n);
 }
 EXPORT_SYMBOL(memcpy_toio);
 
index 79778ab..a536651 100644 (file)
@@ -36,8 +36,8 @@ static inline u16 i8254(void)
        u16 status, timer;
 
        do {
-               outb(I8254_PORT_CONTROL,
-                    I8254_CMD_READBACK | I8254_SELECT_COUNTER0);
+               outb(I8254_CMD_READBACK | I8254_SELECT_COUNTER0,
+                    I8254_PORT_CONTROL);
                status = inb(I8254_PORT_COUNTER0);
                timer  = inb(I8254_PORT_COUNTER0);
                timer |= inb(I8254_PORT_COUNTER0) << 8;
index 2ff25ad..9d5c75f 100644 (file)
@@ -595,7 +595,7 @@ static void show_ldttss(const struct desc_ptr *gdt, const char *name, u16 index)
                return;
        }
 
-       addr = desc.base0 | (desc.base1 << 16) | (desc.base2 << 24);
+       addr = desc.base0 | (desc.base1 << 16) | ((unsigned long)desc.base2 << 24);
 #ifdef CONFIG_X86_64
        addr |= ((u64)desc.base3 << 32);
 #endif
index a19ef1a..4aa9b14 100644 (file)
@@ -158,8 +158,8 @@ static void __init sme_populate_pgd(struct sme_populate_pgd_data *ppd)
        pmd = pmd_offset(pud, ppd->vaddr);
        if (pmd_none(*pmd)) {
                pte = ppd->pgtable_area;
-               memset(pte, 0, sizeof(pte) * PTRS_PER_PTE);
-               ppd->pgtable_area += sizeof(pte) * PTRS_PER_PTE;
+               memset(pte, 0, sizeof(*pte) * PTRS_PER_PTE);
+               ppd->pgtable_area += sizeof(*pte) * PTRS_PER_PTE;
                set_pmd(pmd, __pmd(PMD_FLAGS | __pa(pte)));
        }
 
index 4f89723..14e6119 100644 (file)
@@ -230,6 +230,29 @@ static bool __cpa_pfn_in_highmap(unsigned long pfn)
 
 #endif
 
+/*
+ * See set_mce_nospec().
+ *
+ * Machine check recovery code needs to change cache mode of poisoned pages to
+ * UC to avoid speculative access logging another error. But passing the
+ * address of the 1:1 mapping to set_memory_uc() is a fine way to encourage a
+ * speculative access. So we cheat and flip the top bit of the address. This
+ * works fine for the code that updates the page tables. But at the end of the
+ * process we need to flush the TLB and cache and the non-canonical address
+ * causes a #GP fault when used by the INVLPG and CLFLUSH instructions.
+ *
+ * But in the common case we already have a canonical address. This code
+ * will fix the top bit if needed and is a no-op otherwise.
+ */
+static inline unsigned long fix_addr(unsigned long addr)
+{
+#ifdef CONFIG_X86_64
+       return (long)(addr << 1) >> 1;
+#else
+       return addr;
+#endif
+}
+
 static unsigned long __cpa_addr(struct cpa_data *cpa, unsigned long idx)
 {
        if (cpa->flags & CPA_PAGES_ARRAY) {
@@ -313,7 +336,7 @@ void __cpa_flush_tlb(void *data)
        unsigned int i;
 
        for (i = 0; i < cpa->numpages; i++)
-               __flush_tlb_one_kernel(__cpa_addr(cpa, i));
+               __flush_tlb_one_kernel(fix_addr(__cpa_addr(cpa, i)));
 }
 
 static void cpa_flush(struct cpa_data *data, int cache)
@@ -347,7 +370,7 @@ static void cpa_flush(struct cpa_data *data, int cache)
                 * Only flush present addresses:
                 */
                if (pte && (pte_val(*pte) & _PAGE_PRESENT))
-                       clflush_cache_range_opt((void *)addr, PAGE_SIZE);
+                       clflush_cache_range_opt((void *)fix_addr(addr), PAGE_SIZE);
        }
        mb();
 }
@@ -1627,29 +1650,6 @@ out:
        return ret;
 }
 
-/*
- * Machine check recovery code needs to change cache mode of poisoned
- * pages to UC to avoid speculative access logging another error. But
- * passing the address of the 1:1 mapping to set_memory_uc() is a fine
- * way to encourage a speculative access. So we cheat and flip the top
- * bit of the address. This works fine for the code that updates the
- * page tables. But at the end of the process we need to flush the cache
- * and the non-canonical address causes a #GP fault when used by the
- * CLFLUSH instruction.
- *
- * But in the common case we already have a canonical address. This code
- * will fix the top bit if needed and is a no-op otherwise.
- */
-static inline unsigned long make_addr_canonical_again(unsigned long addr)
-{
-#ifdef CONFIG_X86_64
-       return (long)(addr << 1) >> 1;
-#else
-       return addr;
-#endif
-}
-
-
 static int change_page_attr_set_clr(unsigned long *addr, int numpages,
                                    pgprot_t mask_set, pgprot_t mask_clr,
                                    int force_split, int in_flag,
index 4a6a5a2..eb33432 100644 (file)
@@ -29,7 +29,8 @@
 
 struct uv_systab *uv_systab;
 
-s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
+static s64 __uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
+                       u64 a4, u64 a5)
 {
        struct uv_systab *tab = uv_systab;
        s64 ret;
@@ -51,6 +52,19 @@ s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
 
        return ret;
 }
+
+s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
+{
+       s64 ret;
+
+       if (down_interruptible(&__efi_uv_runtime_lock))
+               return BIOS_STATUS_ABORT;
+
+       ret = __uv_bios_call(which, a1, a2, a3, a4, a5);
+       up(&__efi_uv_runtime_lock);
+
+       return ret;
+}
 EXPORT_SYMBOL_GPL(uv_bios_call);
 
 s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
@@ -59,10 +73,15 @@ s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
        unsigned long bios_flags;
        s64 ret;
 
+       if (down_interruptible(&__efi_uv_runtime_lock))
+               return BIOS_STATUS_ABORT;
+
        local_irq_save(bios_flags);
-       ret = uv_bios_call(which, a1, a2, a3, a4, a5);
+       ret = __uv_bios_call(which, a1, a2, a3, a4, a5);
        local_irq_restore(bios_flags);
 
+       up(&__efi_uv_runtime_lock);
+
        return ret;
 }
 
index 2f6787f..c54a493 100644 (file)
@@ -898,10 +898,7 @@ static u64 xen_read_msr_safe(unsigned int msr, int *err)
        val = native_read_msr_safe(msr, err);
        switch (msr) {
        case MSR_IA32_APICBASE:
-#ifdef CONFIG_X86_X2APIC
-               if (!(cpuid_ecx(1) & (1 << (X86_FEATURE_X2APIC & 31))))
-#endif
-                       val &= ~X2APIC_ENABLE;
+               val &= ~X2APIC_ENABLE;
                break;
        }
        return val;
index 72bf446..6e29794 100644 (file)
@@ -361,8 +361,6 @@ void xen_timer_resume(void)
 {
        int cpu;
 
-       pvclock_resume();
-
        if (xen_clockevent != &xen_vcpuop_clockevent)
                return;
 
@@ -379,12 +377,15 @@ static const struct pv_time_ops xen_time_ops __initconst = {
 };
 
 static struct pvclock_vsyscall_time_info *xen_clock __read_mostly;
+static u64 xen_clock_value_saved;
 
 void xen_save_time_memory_area(void)
 {
        struct vcpu_register_time_memory_area t;
        int ret;
 
+       xen_clock_value_saved = xen_clocksource_read() - xen_sched_clock_offset;
+
        if (!xen_clock)
                return;
 
@@ -404,7 +405,7 @@ void xen_restore_time_memory_area(void)
        int ret;
 
        if (!xen_clock)
-               return;
+               goto out;
 
        t.addr.v = &xen_clock->pvti;
 
@@ -421,6 +422,11 @@ void xen_restore_time_memory_area(void)
        if (ret != 0)
                pr_notice("Cannot restore secondary vcpu_time_info (err %d)",
                          ret);
+
+out:
+       /* Need pvclock_resume() before using xen_clocksource_read(). */
+       pvclock_resume();
+       xen_sched_clock_offset = xen_clocksource_read() - xen_clock_value_saved;
 }
 
 static void xen_setup_vsyscall_time_info(void)
index 20a0756..ce91682 100644 (file)
@@ -164,7 +164,7 @@ config XTENSA_FAKE_NMI
          If unsure, say N.
 
 config XTENSA_UNALIGNED_USER
-       bool "Unaligned memory access in use space"
+       bool "Unaligned memory access in user space"
        help
          The Xtensa architecture currently does not handle unaligned
          memory accesses in hardware but through an exception handler.
@@ -451,7 +451,7 @@ config USE_OF
        help
          Include support for flattened device tree machine descriptions.
 
-config BUILTIN_DTB
+config BUILTIN_DTB_SOURCE
        string "DTB to build into the kernel image"
        depends on OF
 
index f8052ba..0b8d00c 100644 (file)
@@ -7,9 +7,9 @@
 #
 #
 
-BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB)).dtb.o
-ifneq ($(CONFIG_BUILTIN_DTB),"")
-obj-$(CONFIG_OF) += $(BUILTIN_DTB)
+BUILTIN_DTB_SOURCE := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_SOURCE)).dtb.o
+ifneq ($(CONFIG_BUILTIN_DTB_SOURCE),"")
+obj-$(CONFIG_OF) += $(BUILTIN_DTB_SOURCE)
 endif
 
 # for CONFIG_OF_ALL_DTBS test
index 2bf964d..f378e56 100644 (file)
@@ -34,7 +34,7 @@ CONFIG_XTENSA_PLATFORM_XTFPGA=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="earlycon=uart8250,mmio32native,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=0x38000000@0"
 CONFIG_USE_OF=y
-CONFIG_BUILTIN_DTB="kc705"
+CONFIG_BUILTIN_DTB_SOURCE="kc705"
 # CONFIG_COMPACTION is not set
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_PM=y
index 3221b70..62f32a9 100644 (file)
@@ -38,7 +38,7 @@ CONFIG_HIGHMEM=y
 # CONFIG_PCI is not set
 CONFIG_XTENSA_PLATFORM_XTFPGA=y
 CONFIG_USE_OF=y
-CONFIG_BUILTIN_DTB="csp"
+CONFIG_BUILTIN_DTB_SOURCE="csp"
 # CONFIG_COMPACTION is not set
 CONFIG_XTFPGA_LCD=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
index 985fa85..8bebe07 100644 (file)
@@ -33,7 +33,7 @@ CONFIG_XTENSA_PLATFORM_XTFPGA=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="earlycon=uart8250,mmio32native,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=0x38000000@0"
 CONFIG_USE_OF=y
-CONFIG_BUILTIN_DTB="kc705"
+CONFIG_BUILTIN_DTB_SOURCE="kc705"
 # CONFIG_COMPACTION is not set
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_NET=y
index f3fc4f9..933ab2a 100644 (file)
@@ -39,7 +39,7 @@ CONFIG_XTENSA_PLATFORM_XTFPGA=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="earlycon=uart8250,mmio32native,0x9d050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=256M@0x60000000"
 CONFIG_USE_OF=y
-CONFIG_BUILTIN_DTB="kc705_nommu"
+CONFIG_BUILTIN_DTB_SOURCE="kc705_nommu"
 CONFIG_BINFMT_FLAT=y
 CONFIG_NET=y
 CONFIG_PACKET=y
index 11fed6c..e29c5b1 100644 (file)
@@ -33,11 +33,12 @@ CONFIG_SMP=y
 CONFIG_HOTPLUG_CPU=y
 # CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX is not set
 # CONFIG_PCI is not set
+CONFIG_VECTORS_OFFSET=0x00002000
 CONFIG_XTENSA_PLATFORM_XTFPGA=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="earlycon=uart8250,mmio32native,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=96M@0"
 CONFIG_USE_OF=y
-CONFIG_BUILTIN_DTB="lx200mx"
+CONFIG_BUILTIN_DTB_SOURCE="lx200mx"
 # CONFIG_COMPACTION is not set
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_NET=y
index da08e75..7f00971 100644 (file)
@@ -276,12 +276,13 @@ should_never_return:
 
        movi    a2, cpu_start_ccount
 1:
+       memw
        l32i    a3, a2, 0
        beqi    a3, 0, 1b
        movi    a3, 0
        s32i    a3, a2, 0
-       memw
 1:
+       memw
        l32i    a3, a2, 0
        beqi    a3, 0, 1b
        wsr     a3, ccount
@@ -317,11 +318,13 @@ ENTRY(cpu_restart)
        rsr     a0, prid
        neg     a2, a0
        movi    a3, cpu_start_id
+       memw
        s32i    a2, a3, 0
 #if XCHAL_DCACHE_IS_WRITEBACK
        dhwbi   a3, 0
 #endif
 1:
+       memw
        l32i    a2, a3, 0
        dhi     a3, 0
        bne     a2, a0, 1b
index 932d646..be1f280 100644 (file)
@@ -83,7 +83,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 {
        unsigned i;
 
-       for (i = 0; i < max_cpus; ++i)
+       for_each_possible_cpu(i)
                set_cpu_present(i, true);
 }
 
@@ -96,6 +96,11 @@ void __init smp_init_cpus(void)
        pr_info("%s: Core Count = %d\n", __func__, ncpus);
        pr_info("%s: Core Id = %d\n", __func__, core_id);
 
+       if (ncpus > NR_CPUS) {
+               ncpus = NR_CPUS;
+               pr_info("%s: limiting core count by %d\n", __func__, ncpus);
+       }
+
        for (i = 0; i < ncpus; ++i)
                set_cpu_possible(i, true);
 }
@@ -195,9 +200,11 @@ static int boot_secondary(unsigned int cpu, struct task_struct *ts)
        int i;
 
 #ifdef CONFIG_HOTPLUG_CPU
-       cpu_start_id = cpu;
-       system_flush_invalidate_dcache_range(
-                       (unsigned long)&cpu_start_id, sizeof(cpu_start_id));
+       WRITE_ONCE(cpu_start_id, cpu);
+       /* Pairs with the third memw in the cpu_restart */
+       mb();
+       system_flush_invalidate_dcache_range((unsigned long)&cpu_start_id,
+                                            sizeof(cpu_start_id));
 #endif
        smp_call_function_single(0, mx_cpu_start, (void *)cpu, 1);
 
@@ -206,18 +213,21 @@ static int boot_secondary(unsigned int cpu, struct task_struct *ts)
                        ccount = get_ccount();
                while (!ccount);
 
-               cpu_start_ccount = ccount;
+               WRITE_ONCE(cpu_start_ccount, ccount);
 
-               while (time_before(jiffies, timeout)) {
+               do {
+                       /*
+                        * Pairs with the first two memws in the
+                        * .Lboot_secondary.
+                        */
                        mb();
-                       if (!cpu_start_ccount)
-                               break;
-               }
+                       ccount = READ_ONCE(cpu_start_ccount);
+               } while (ccount && time_before(jiffies, timeout));
 
-               if (cpu_start_ccount) {
+               if (ccount) {
                        smp_call_function_single(0, mx_cpu_stop,
-                                       (void *)cpu, 1);
-                       cpu_start_ccount = 0;
+                                                (void *)cpu, 1);
+                       WRITE_ONCE(cpu_start_ccount, 0);
                        return -EIO;
                }
        }
@@ -237,6 +247,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
        pr_debug("%s: Calling wakeup_secondary(cpu:%d, idle:%p, sp: %08lx)\n",
                        __func__, cpu, idle, start_info.stack);
 
+       init_completion(&cpu_running);
        ret = boot_secondary(cpu, idle);
        if (ret == 0) {
                wait_for_completion_timeout(&cpu_running,
@@ -298,8 +309,10 @@ void __cpu_die(unsigned int cpu)
        unsigned long timeout = jiffies + msecs_to_jiffies(1000);
        while (time_before(jiffies, timeout)) {
                system_invalidate_dcache_range((unsigned long)&cpu_start_id,
-                               sizeof(cpu_start_id));
-               if (cpu_start_id == -cpu) {
+                                              sizeof(cpu_start_id));
+               /* Pairs with the second memw in the cpu_restart */
+               mb();
+               if (READ_ONCE(cpu_start_id) == -cpu) {
                        platform_cpu_kill(cpu);
                        return;
                }
index fd524a5..378186b 100644 (file)
@@ -89,7 +89,7 @@ static int ccount_timer_shutdown(struct clock_event_device *evt)
                container_of(evt, struct ccount_timer, evt);
 
        if (timer->irq_enabled) {
-               disable_irq(evt->irq);
+               disable_irq_nosync(evt->irq);
                timer->irq_enabled = 0;
        }
        return 0;
index 63e0f12..72adbbe 100644 (file)
@@ -1154,15 +1154,14 @@ static void bfq_activate_requeue_entity(struct bfq_entity *entity,
 }
 
 /**
- * __bfq_deactivate_entity - deactivate an entity from its service tree.
- * @entity: the entity to deactivate.
+ * __bfq_deactivate_entity - update sched_data and service trees for
+ * entity, so as to represent entity as inactive
+ * @entity: the entity being deactivated.
  * @ins_into_idle_tree: if false, the entity will not be put into the
  *                     idle tree.
  *
- * Deactivates an entity, independently of its previous state.  Must
- * be invoked only if entity is on a service tree. Extracts the entity
- * from that tree, and if necessary and allowed, puts it into the idle
- * tree.
+ * If necessary and allowed, puts entity into the idle tree. NOTE:
+ * entity may be on no tree if in service.
  */
 bool __bfq_deactivate_entity(struct bfq_entity *entity, bool ins_into_idle_tree)
 {
index c780429..6b78ec5 100644 (file)
@@ -462,6 +462,10 @@ static void blk_rq_timed_out_timer(struct timer_list *t)
        kblockd_schedule_work(&q->timeout_work);
 }
 
+static void blk_timeout_work(struct work_struct *work)
+{
+}
+
 /**
  * blk_alloc_queue_node - allocate a request queue
  * @gfp_mask: memory allocation flags
@@ -505,7 +509,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
        timer_setup(&q->backing_dev_info->laptop_mode_wb_timer,
                    laptop_mode_timer_fn, 0);
        timer_setup(&q->timeout, blk_rq_timed_out_timer, 0);
-       INIT_WORK(&q->timeout_work, NULL);
+       INIT_WORK(&q->timeout_work, blk_timeout_work);
        INIT_LIST_HEAD(&q->icq_list);
 #ifdef CONFIG_BLK_CGROUP
        INIT_LIST_HEAD(&q->blkg_list);
@@ -661,7 +665,6 @@ no_merge:
  * blk_attempt_plug_merge - try to merge with %current's plugged list
  * @q: request_queue new bio is being queued at
  * @bio: new bio being queued
- * @request_count: out parameter for number of traversed plugged requests
  * @same_queue_rq: pointer to &struct request that gets filled in when
  * another request associated with @q is found on the plug list
  * (optional, may be %NULL)
@@ -1683,6 +1686,15 @@ EXPORT_SYMBOL(kblockd_mod_delayed_work_on);
  * @plug:      The &struct blk_plug that needs to be initialized
  *
  * Description:
+ *   blk_start_plug() indicates to the block layer an intent by the caller
+ *   to submit multiple I/O requests in a batch.  The block layer may use
+ *   this hint to defer submitting I/Os from the caller until blk_finish_plug()
+ *   is called.  However, the block layer may choose to submit requests
+ *   before a call to blk_finish_plug() if the number of queued I/Os
+ *   exceeds %BLK_MAX_REQUEST_COUNT, or if the size of the I/O is larger than
+ *   %BLK_PLUG_FLUSH_SIZE.  The queued I/Os may also be submitted early if
+ *   the task schedules (see below).
+ *
  *   Tracking blk_plug inside the task_struct will help with auto-flushing the
  *   pending I/O should the task end up blocking between blk_start_plug() and
  *   blk_finish_plug(). This is important from a performance perspective, but
@@ -1765,6 +1777,16 @@ void blk_flush_plug_list(struct blk_plug *plug, bool from_schedule)
                blk_mq_flush_plug_list(plug, from_schedule);
 }
 
+/**
+ * blk_finish_plug - mark the end of a batch of submitted I/O
+ * @plug:      The &struct blk_plug passed to blk_start_plug()
+ *
+ * Description:
+ * Indicate that a batch of I/O submissions is complete.  This function
+ * must be paired with an initial call to blk_start_plug().  The intent
+ * is to allow the block layer to optimize I/O submission.  See the
+ * documentation for blk_start_plug() for more information.
+ */
 void blk_finish_plug(struct blk_plug *plug)
 {
        if (plug != current->plug)
index a3fc719..6e0f2d9 100644 (file)
@@ -335,7 +335,7 @@ static void mq_flush_data_end_io(struct request *rq, blk_status_t error)
        blk_flush_complete_seq(rq, fq, REQ_FSEQ_DATA, error);
        spin_unlock_irqrestore(&fq->mq_flush_lock, flags);
 
-       blk_mq_run_hw_queue(hctx, true);
+       blk_mq_sched_restart(hctx);
 }
 
 /**
index fc714ef..2620baa 100644 (file)
@@ -72,6 +72,7 @@
 #include <linux/sched/loadavg.h>
 #include <linux/sched/signal.h>
 #include <trace/events/block.h>
+#include <linux/blk-mq.h>
 #include "blk-rq-qos.h"
 #include "blk-stat.h"
 
@@ -591,6 +592,7 @@ static void blkcg_iolatency_done_bio(struct rq_qos *rqos, struct bio *bio)
        u64 now = ktime_to_ns(ktime_get());
        bool issue_as_root = bio_issue_as_root_blkg(bio);
        bool enabled = false;
+       int inflight = 0;
 
        blkg = bio->bi_blkg;
        if (!blkg || !bio_flagged(bio, BIO_TRACKED))
@@ -601,6 +603,9 @@ static void blkcg_iolatency_done_bio(struct rq_qos *rqos, struct bio *bio)
                return;
 
        enabled = blk_iolatency_enabled(iolat->blkiolat);
+       if (!enabled)
+               return;
+
        while (blkg && blkg->parent) {
                iolat = blkg_to_lat(blkg);
                if (!iolat) {
@@ -609,8 +614,9 @@ static void blkcg_iolatency_done_bio(struct rq_qos *rqos, struct bio *bio)
                }
                rqw = &iolat->rq_wait;
 
-               atomic_dec(&rqw->inflight);
-               if (!enabled || iolat->min_lat_nsec == 0)
+               inflight = atomic_dec_return(&rqw->inflight);
+               WARN_ON_ONCE(inflight < 0);
+               if (iolat->min_lat_nsec == 0)
                        goto next;
                iolatency_record_time(iolat, &bio->bi_issue, now,
                                      issue_as_root);
@@ -754,10 +760,13 @@ int blk_iolatency_init(struct request_queue *q)
        return 0;
 }
 
-static void iolatency_set_min_lat_nsec(struct blkcg_gq *blkg, u64 val)
+/*
+ * return 1 for enabling iolatency, return -1 for disabling iolatency, otherwise
+ * return 0.
+ */
+static int iolatency_set_min_lat_nsec(struct blkcg_gq *blkg, u64 val)
 {
        struct iolatency_grp *iolat = blkg_to_lat(blkg);
-       struct blk_iolatency *blkiolat = iolat->blkiolat;
        u64 oldval = iolat->min_lat_nsec;
 
        iolat->min_lat_nsec = val;
@@ -766,9 +775,10 @@ static void iolatency_set_min_lat_nsec(struct blkcg_gq *blkg, u64 val)
                                    BLKIOLATENCY_MAX_WIN_SIZE);
 
        if (!oldval && val)
-               atomic_inc(&blkiolat->enabled);
+               return 1;
        if (oldval && !val)
-               atomic_dec(&blkiolat->enabled);
+               return -1;
+       return 0;
 }
 
 static void iolatency_clear_scaling(struct blkcg_gq *blkg)
@@ -800,6 +810,7 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf,
        u64 lat_val = 0;
        u64 oldval;
        int ret;
+       int enable = 0;
 
        ret = blkg_conf_prep(blkcg, &blkcg_policy_iolatency, buf, &ctx);
        if (ret)
@@ -834,7 +845,12 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf,
        blkg = ctx.blkg;
        oldval = iolat->min_lat_nsec;
 
-       iolatency_set_min_lat_nsec(blkg, lat_val);
+       enable = iolatency_set_min_lat_nsec(blkg, lat_val);
+       if (enable) {
+               WARN_ON_ONCE(!blk_get_queue(blkg->q));
+               blkg_get(blkg);
+       }
+
        if (oldval != iolat->min_lat_nsec) {
                iolatency_clear_scaling(blkg);
        }
@@ -842,6 +858,24 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf,
        ret = 0;
 out:
        blkg_conf_finish(&ctx);
+       if (ret == 0 && enable) {
+               struct iolatency_grp *tmp = blkg_to_lat(blkg);
+               struct blk_iolatency *blkiolat = tmp->blkiolat;
+
+               blk_mq_freeze_queue(blkg->q);
+
+               if (enable == 1)
+                       atomic_inc(&blkiolat->enabled);
+               else if (enable == -1)
+                       atomic_dec(&blkiolat->enabled);
+               else
+                       WARN_ON_ONCE(1);
+
+               blk_mq_unfreeze_queue(blkg->q);
+
+               blkg_put(blkg);
+               blk_put_queue(blkg->q);
+       }
        return ret ?: nbytes;
 }
 
@@ -977,8 +1011,14 @@ static void iolatency_pd_offline(struct blkg_policy_data *pd)
 {
        struct iolatency_grp *iolat = pd_to_lat(pd);
        struct blkcg_gq *blkg = lat_to_blkg(iolat);
+       struct blk_iolatency *blkiolat = iolat->blkiolat;
+       int ret;
 
-       iolatency_set_min_lat_nsec(blkg, 0);
+       ret = iolatency_set_min_lat_nsec(blkg, 0);
+       if (ret == 1)
+               atomic_inc(&blkiolat->enabled);
+       if (ret == -1)
+               atomic_dec(&blkiolat->enabled);
        iolatency_clear_scaling(blkg);
 }
 
index fb2c82c..038cb62 100644 (file)
@@ -1,8 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2017 Western Digital Corporation or its affiliates.
- *
- * This file is released under the GPL.
  */
 
 #include <linux/blkdev.h>
index 90d6876..7921573 100644 (file)
@@ -308,8 +308,9 @@ static const char *const cmd_flag_name[] = {
        CMD_FLAG_NAME(PREFLUSH),
        CMD_FLAG_NAME(RAHEAD),
        CMD_FLAG_NAME(BACKGROUND),
-       CMD_FLAG_NAME(NOUNMAP),
        CMD_FLAG_NAME(NOWAIT),
+       CMD_FLAG_NAME(NOUNMAP),
+       CMD_FLAG_NAME(HIPRI),
 };
 #undef CMD_FLAG_NAME
 
@@ -838,6 +839,9 @@ static const struct blk_mq_debugfs_attr blk_mq_debugfs_ctx_attrs[] = {
 static bool debugfs_create_files(struct dentry *parent, void *data,
                                 const struct blk_mq_debugfs_attr *attr)
 {
+       if (IS_ERR_OR_NULL(parent))
+               return false;
+
        d_inode(parent)->i_private = data;
 
        for (; attr->name; attr++) {
index 3ba37b9..9437a5e 100644 (file)
@@ -737,12 +737,20 @@ static void blk_mq_requeue_work(struct work_struct *work)
        spin_unlock_irq(&q->requeue_lock);
 
        list_for_each_entry_safe(rq, next, &rq_list, queuelist) {
-               if (!(rq->rq_flags & RQF_SOFTBARRIER))
+               if (!(rq->rq_flags & (RQF_SOFTBARRIER | RQF_DONTPREP)))
                        continue;
 
                rq->rq_flags &= ~RQF_SOFTBARRIER;
                list_del_init(&rq->queuelist);
-               blk_mq_sched_insert_request(rq, true, false, false);
+               /*
+                * If RQF_DONTPREP, rq has contained some driver specific
+                * data, so insert it to hctx dispatch list to avoid any
+                * merge.
+                */
+               if (rq->rq_flags & RQF_DONTPREP)
+                       blk_mq_request_bypass_insert(rq, false);
+               else
+                       blk_mq_sched_insert_request(rq, true, false, false);
        }
 
        while (!list_empty(&rq_list)) {
@@ -1906,7 +1914,7 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
 {
        const int is_sync = op_is_sync(bio->bi_opf);
        const int is_flush_fua = op_is_flush(bio->bi_opf);
-       struct blk_mq_alloc_data data = { .flags = 0, .cmd_flags = bio->bi_opf };
+       struct blk_mq_alloc_data data = { .flags = 0};
        struct request *rq;
        struct blk_plug *plug;
        struct request *same_queue_rq = NULL;
@@ -1928,6 +1936,7 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
 
        rq_qos_throttle(q, bio);
 
+       data.cmd_flags = bio->bi_opf;
        rq = blk_mq_get_request(q, bio, &data);
        if (unlikely(!rq)) {
                rq_qos_cleanup(q, bio);
index d943d46..d0b3dd5 100644 (file)
@@ -36,7 +36,6 @@ struct blk_mq_ctx {
        struct kobject          kobj;
 } ____cacheline_aligned_in_smp;
 
-void blk_mq_freeze_queue(struct request_queue *q);
 void blk_mq_free_queue(struct request_queue *q);
 int blk_mq_update_nr_requests(struct request_queue *q, unsigned int nr);
 void blk_mq_wake_waiters(struct request_queue *q);
index f0c5664..fd166fb 100644 (file)
@@ -597,7 +597,7 @@ static void wbt_track(struct rq_qos *rqos, struct request *rq, struct bio *bio)
        rq->wbt_flags |= bio_to_wbt_flags(rwb, bio);
 }
 
-void wbt_issue(struct rq_qos *rqos, struct request *rq)
+static void wbt_issue(struct rq_qos *rqos, struct request *rq)
 {
        struct rq_wb *rwb = RQWB(rqos);
 
@@ -617,7 +617,7 @@ void wbt_issue(struct rq_qos *rqos, struct request *rq)
        }
 }
 
-void wbt_requeue(struct rq_qos *rqos, struct request *rq)
+static void wbt_requeue(struct rq_qos *rqos, struct request *rq)
 {
        struct rq_wb *rwb = RQWB(rqos);
        if (!rwb_enabled(rwb))
index 6651e71..5564e73 100644 (file)
@@ -539,6 +539,8 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
        ictx = skcipher_instance_ctx(inst);
 
        /* Stream cipher, e.g. "xchacha12" */
+       crypto_set_skcipher_spawn(&ictx->streamcipher_spawn,
+                                 skcipher_crypto_instance(inst));
        err = crypto_grab_skcipher(&ictx->streamcipher_spawn, streamcipher_name,
                                   0, crypto_requires_sync(algt->type,
                                                           algt->mask));
@@ -547,6 +549,8 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
        streamcipher_alg = crypto_spawn_skcipher_alg(&ictx->streamcipher_spawn);
 
        /* Block cipher, e.g. "aes" */
+       crypto_set_spawn(&ictx->blockcipher_spawn,
+                        skcipher_crypto_instance(inst));
        err = crypto_grab_spawn(&ictx->blockcipher_spawn, blockcipher_name,
                                CRYPTO_ALG_TYPE_CIPHER, CRYPTO_ALG_TYPE_MASK);
        if (err)
index 37f54d1..4be293a 100644 (file)
@@ -58,14 +58,22 @@ int crypto_authenc_extractkeys(struct crypto_authenc_keys *keys, const u8 *key,
                return -EINVAL;
        if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
                return -EINVAL;
-       if (RTA_PAYLOAD(rta) < sizeof(*param))
+
+       /*
+        * RTA_OK() didn't align the rtattr's payload when validating that it
+        * fits in the buffer.  Yet, the keys should start on the next 4-byte
+        * aligned boundary.  To avoid confusion, require that the rtattr
+        * payload be exactly the param struct, which has a 4-byte aligned size.
+        */
+       if (RTA_PAYLOAD(rta) != sizeof(*param))
                return -EINVAL;
+       BUILD_BUG_ON(sizeof(*param) % RTA_ALIGNTO);
 
        param = RTA_DATA(rta);
        keys->enckeylen = be32_to_cpu(param->enckeylen);
 
-       key += RTA_ALIGN(rta->rta_len);
-       keylen -= RTA_ALIGN(rta->rta_len);
+       key += rta->rta_len;
+       keylen -= rta->rta_len;
 
        if (keylen < keys->enckeylen)
                return -EINVAL;
index 80a25cc..4741fe8 100644 (file)
@@ -279,7 +279,7 @@ static void authenc_esn_verify_ahash_done(struct crypto_async_request *areq,
        struct aead_request *req = areq->data;
 
        err = err ?: crypto_authenc_esn_decrypt_tail(req, 0);
-       aead_request_complete(req, err);
+       authenc_esn_request_complete(req, err);
 }
 
 static int crypto_authenc_esn_decrypt(struct aead_request *req)
index 9a5c60f..c0cf87a 100644 (file)
@@ -100,7 +100,7 @@ static void sm3_compress(u32 *w, u32 *wt, u32 *m)
 
        for (i = 0; i <= 63; i++) {
 
-               ss1 = rol32((rol32(a, 12) + e + rol32(t(i), i)), 7);
+               ss1 = rol32((rol32(a, 12) + e + rol32(t(i), i & 31)), 7);
 
                ss2 = ss1 ^ rol32(a, 12);
 
index 7b65a80..90ff0a4 100644 (file)
@@ -10,6 +10,7 @@ menuconfig ACPI
        bool "ACPI (Advanced Configuration and Power Interface) Support"
        depends on ARCH_SUPPORTS_ACPI
        select PNP
+       select NLS
        default y if X86
        help
          Advanced Configuration and Power Interface (ACPI) support for 
index 7c6afc1..bb85742 100644 (file)
@@ -41,7 +41,8 @@ acpi-y                                += ec.o
 acpi-$(CONFIG_ACPI_DOCK)       += dock.o
 acpi-$(CONFIG_PCI)             += pci_root.o pci_link.o pci_irq.o
 obj-$(CONFIG_ACPI_MCFG)                += pci_mcfg.o
-acpi-y                         += acpi_lpss.o acpi_apd.o
+acpi-$(CONFIG_PCI)             += acpi_lpss.o
+acpi-y                         += acpi_apd.o
 acpi-y                         += acpi_platform.o
 acpi-y                         += acpi_pnp.o
 acpi-$(CONFIG_ARM_AMBA)        += acpi_amba.o
index fdd90ff..e48894e 100644 (file)
@@ -876,7 +876,7 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
        return (resv == its->its_count) ? resv : -ENODEV;
 }
 #else
-static inline const struct iommu_ops *iort_fwspec_iommu_ops(struct device *dev);
+static inline const struct iommu_ops *iort_fwspec_iommu_ops(struct device *dev)
 { return NULL; }
 static inline int iort_add_device_replay(const struct iommu_ops *ops,
                                         struct device *dev)
@@ -952,9 +952,10 @@ static int rc_dma_get_range(struct device *dev, u64 *size)
 {
        struct acpi_iort_node *node;
        struct acpi_iort_root_complex *rc;
+       struct pci_bus *pbus = to_pci_dev(dev)->bus;
 
        node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
-                             iort_match_node_callback, dev);
+                             iort_match_node_callback, &pbus->dev);
        if (!node || node->revision < 1)
                return -ENODEV;
 
index 99d820a..147f6c7 100644 (file)
@@ -1029,6 +1029,9 @@ void __init acpi_early_init(void)
 
        acpi_permanent_mmap = true;
 
+       /* Initialize debug output. Linux does not use ACPICA defaults */
+       acpi_dbg_level = ACPI_LV_INFO | ACPI_LV_REPAIR;
+
 #ifdef CONFIG_X86
        /*
         * If the machine falls into the DMI check table,
@@ -1054,18 +1057,6 @@ void __init acpi_early_init(void)
                goto error0;
        }
 
-       /*
-        * ACPI 2.0 requires the EC driver to be loaded and work before
-        * the EC device is found in the namespace (i.e. before
-        * acpi_load_tables() is called).
-        *
-        * This is accomplished by looking for the ECDT table, and getting
-        * the EC parameters out of that.
-        *
-        * Ignore the result. Not having an ECDT is not fatal.
-        */
-       status = acpi_ec_ecdt_probe();
-
 #ifdef CONFIG_X86
        if (!acpi_ioapic) {
                /* compatible (0) means level (3) */
@@ -1142,6 +1133,18 @@ static int __init acpi_bus_init(void)
                goto error1;
        }
 
+       /*
+        * ACPI 2.0 requires the EC driver to be loaded and work before the EC
+        * device is found in the namespace.
+        *
+        * This is accomplished by looking for the ECDT table and getting the EC
+        * parameters out of that.
+        *
+        * Do that before calling acpi_initialize_objects() which may trigger EC
+        * address space accesses.
+        */
+       acpi_ec_ecdt_probe();
+
        status = acpi_enable_subsystem(ACPI_NO_ACPI_ENABLE);
        if (ACPI_FAILURE(status)) {
                printk(KERN_ERR PREFIX
index 7e6952e..6a9e1fb 100644 (file)
@@ -81,7 +81,11 @@ void acpi_debugfs_init(void);
 #else
 static inline void acpi_debugfs_init(void) { return; }
 #endif
+#ifdef CONFIG_PCI
 void acpi_lpss_init(void);
+#else
+static inline void acpi_lpss_init(void) {}
+#endif
 
 void acpi_apd_init(void);
 
index 011d3db..e18ade5 100644 (file)
@@ -26,7 +26,6 @@
 #include <acpi/nfit.h>
 #include "intel.h"
 #include "nfit.h"
-#include "intel.h"
 
 /*
  * For readq() and writeq() on 32-bit builds, the hi-lo, lo-hi order is
@@ -78,12 +77,6 @@ const guid_t *to_nfit_uuid(enum nfit_uuids id)
 }
 EXPORT_SYMBOL(to_nfit_uuid);
 
-static struct acpi_nfit_desc *to_acpi_nfit_desc(
-               struct nvdimm_bus_descriptor *nd_desc)
-{
-       return container_of(nd_desc, struct acpi_nfit_desc, nd_desc);
-}
-
 static struct acpi_device *to_acpi_dev(struct acpi_nfit_desc *acpi_desc)
 {
        struct nvdimm_bus_descriptor *nd_desc = &acpi_desc->nd_desc;
@@ -416,10 +409,36 @@ static bool payload_dumpable(struct nvdimm *nvdimm, unsigned int func)
        return true;
 }
 
+static int cmd_to_func(struct nfit_mem *nfit_mem, unsigned int cmd,
+               struct nd_cmd_pkg *call_pkg)
+{
+       if (call_pkg) {
+               int i;
+
+               if (nfit_mem->family != call_pkg->nd_family)
+                       return -ENOTTY;
+
+               for (i = 0; i < ARRAY_SIZE(call_pkg->nd_reserved2); i++)
+                       if (call_pkg->nd_reserved2[i])
+                               return -EINVAL;
+               return call_pkg->nd_command;
+       }
+
+       /* Linux ND commands == NVDIMM_FAMILY_INTEL function numbers */
+       if (nfit_mem->family == NVDIMM_FAMILY_INTEL)
+               return cmd;
+
+       /*
+        * Force function number validation to fail since 0 is never
+        * published as a valid function in dsm_mask.
+        */
+       return 0;
+}
+
 int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
                unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc)
 {
-       struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
+       struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
        struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
        union acpi_object in_obj, in_buf, *out_obj;
        const struct nd_cmd_desc *desc = NULL;
@@ -429,30 +448,23 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
        unsigned long cmd_mask, dsm_mask;
        u32 offset, fw_status = 0;
        acpi_handle handle;
-       unsigned int func;
        const guid_t *guid;
-       int rc, i;
+       int func, rc, i;
 
        if (cmd_rc)
                *cmd_rc = -EINVAL;
-       func = cmd;
-       if (cmd == ND_CMD_CALL) {
-               call_pkg = buf;
-               func = call_pkg->nd_command;
-
-               for (i = 0; i < ARRAY_SIZE(call_pkg->nd_reserved2); i++)
-                       if (call_pkg->nd_reserved2[i])
-                               return -EINVAL;
-       }
 
        if (nvdimm) {
                struct acpi_device *adev = nfit_mem->adev;
 
                if (!adev)
                        return -ENOTTY;
-               if (call_pkg && nfit_mem->family != call_pkg->nd_family)
-                       return -ENOTTY;
 
+               if (cmd == ND_CMD_CALL)
+                       call_pkg = buf;
+               func = cmd_to_func(nfit_mem, cmd, call_pkg);
+               if (func < 0)
+                       return func;
                dimm_name = nvdimm_name(nvdimm);
                cmd_name = nvdimm_cmd_name(cmd);
                cmd_mask = nvdimm_cmd_mask(nvdimm);
@@ -463,6 +475,7 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
        } else {
                struct acpi_device *adev = to_acpi_dev(acpi_desc);
 
+               func = cmd;
                cmd_name = nvdimm_bus_cmd_name(cmd);
                cmd_mask = nd_desc->cmd_mask;
                dsm_mask = cmd_mask;
@@ -477,7 +490,13 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
        if (!desc || (cmd && (desc->out_num + desc->in_num == 0)))
                return -ENOTTY;
 
-       if (!test_bit(cmd, &cmd_mask) || !test_bit(func, &dsm_mask))
+       /*
+        * Check for a valid command.  For ND_CMD_CALL, we also have to
+        * make sure that the DSM function is supported.
+        */
+       if (cmd == ND_CMD_CALL && !test_bit(func, &dsm_mask))
+               return -ENOTTY;
+       else if (!test_bit(cmd, &cmd_mask))
                return -ENOTTY;
 
        in_obj.type = ACPI_TYPE_PACKAGE;
@@ -721,6 +740,7 @@ int nfit_get_smbios_id(u32 device_handle, u16 *flags)
        struct acpi_nfit_memory_map *memdev;
        struct acpi_nfit_desc *acpi_desc;
        struct nfit_mem *nfit_mem;
+       u16 physical_id;
 
        mutex_lock(&acpi_desc_lock);
        list_for_each_entry(acpi_desc, &acpi_descs, list) {
@@ -728,10 +748,11 @@ int nfit_get_smbios_id(u32 device_handle, u16 *flags)
                list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) {
                        memdev = __to_nfit_memdev(nfit_mem);
                        if (memdev->device_handle == device_handle) {
+                               *flags = memdev->flags;
+                               physical_id = memdev->physical_id;
                                mutex_unlock(&acpi_desc->init_mutex);
                                mutex_unlock(&acpi_desc_lock);
-                               *flags = memdev->flags;
-                               return memdev->physical_id;
+                               return physical_id;
                        }
                }
                mutex_unlock(&acpi_desc->init_mutex);
@@ -1872,6 +1893,13 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
                return 0;
        }
 
+       /*
+        * Function 0 is the command interrogation function, don't
+        * export it to potential userspace use, and enable it to be
+        * used as an error value in acpi_nfit_ctl().
+        */
+       dsm_mask &= ~1UL;
+
        guid = to_nfit_uuid(nfit_mem->family);
        for_each_set_bit(i, &dsm_mask, BITS_PER_LONG)
                if (acpi_check_dsm(adev_dimm->handle, guid,
@@ -2047,11 +2075,6 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
                if (!nvdimm)
                        continue;
 
-               rc = nvdimm_security_setup_events(nvdimm);
-               if (rc < 0)
-                       dev_warn(acpi_desc->dev,
-                               "security event setup failed: %d\n", rc);
-
                nfit_kernfs = sysfs_get_dirent(nvdimm_kobj(nvdimm)->sd, "nfit");
                if (nfit_kernfs)
                        nfit_mem->flags_attr = sysfs_get_dirent(nfit_kernfs,
@@ -2231,7 +2254,6 @@ static int acpi_nfit_init_interleave_set(struct acpi_nfit_desc *acpi_desc,
        nd_set = devm_kzalloc(dev, sizeof(*nd_set), GFP_KERNEL);
        if (!nd_set)
                return -ENOMEM;
-       ndr_desc->nd_set = nd_set;
        guid_copy(&nd_set->type_guid, (guid_t *) spa->range_guid);
 
        info = devm_kzalloc(dev, sizeof_nfit_set_info(nr), GFP_KERNEL);
@@ -3367,7 +3389,7 @@ EXPORT_SYMBOL_GPL(acpi_nfit_init);
 
 static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc)
 {
-       struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
+       struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
        struct device *dev = acpi_desc->dev;
 
        /* Bounce the device lock to flush acpi_nfit_add / acpi_nfit_notify */
@@ -3384,7 +3406,7 @@ static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc)
 static int __acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,
                struct nvdimm *nvdimm, unsigned int cmd)
 {
-       struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
+       struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
 
        if (nvdimm)
                return 0;
index 850b292..f70de71 100644 (file)
@@ -146,7 +146,7 @@ static int intel_security_change_key(struct nvdimm *nvdimm,
 
 static void nvdimm_invalidate_cache(void);
 
-static int intel_security_unlock(struct nvdimm *nvdimm,
+static int __maybe_unused intel_security_unlock(struct nvdimm *nvdimm,
                const struct nvdimm_key_data *key_data)
 {
        struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
@@ -227,7 +227,7 @@ static int intel_security_disable(struct nvdimm *nvdimm,
        return 0;
 }
 
-static int intel_security_erase(struct nvdimm *nvdimm,
+static int __maybe_unused intel_security_erase(struct nvdimm *nvdimm,
                const struct nvdimm_key_data *key,
                enum nvdimm_passphrase_type ptype)
 {
@@ -276,7 +276,7 @@ static int intel_security_erase(struct nvdimm *nvdimm,
        return 0;
 }
 
-static int intel_security_query_overwrite(struct nvdimm *nvdimm)
+static int __maybe_unused intel_security_query_overwrite(struct nvdimm *nvdimm)
 {
        int rc;
        struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
@@ -313,7 +313,7 @@ static int intel_security_query_overwrite(struct nvdimm *nvdimm)
        return 0;
 }
 
-static int intel_security_overwrite(struct nvdimm *nvdimm,
+static int __maybe_unused intel_security_overwrite(struct nvdimm *nvdimm,
                const struct nvdimm_key_data *nkey)
 {
        int rc;
index 2746994..7bbbf82 100644 (file)
@@ -146,9 +146,9 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header)
                {
                        struct acpi_srat_mem_affinity *p =
                            (struct acpi_srat_mem_affinity *)header;
-                       pr_debug("SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s%s\n",
-                                (unsigned long)p->base_address,
-                                (unsigned long)p->length,
+                       pr_debug("SRAT Memory (0x%llx length 0x%llx) in proximity domain %d %s%s%s\n",
+                                (unsigned long long)p->base_address,
+                                (unsigned long long)p->length,
                                 p->proximity_domain,
                                 (p->flags & ACPI_SRAT_MEM_ENABLED) ?
                                 "enabled" : "disabled",
index 2579675..e7c0006 100644 (file)
 #define GPI1_LDO_ON            (3 << 0)
 #define GPI1_LDO_OFF           (4 << 0)
 
-#define AXP288_ADC_TS_PIN_GPADC        0xf2
-#define AXP288_ADC_TS_PIN_ON   0xf3
+#define AXP288_ADC_TS_CURRENT_ON_OFF_MASK              GENMASK(1, 0)
+#define AXP288_ADC_TS_CURRENT_OFF                      (0 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_WHEN_CHARGING         (1 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_ONDEMAND              (2 << 0)
+#define AXP288_ADC_TS_CURRENT_ON                       (3 << 0)
 
 static struct pmic_table power_table[] = {
        {
@@ -212,22 +215,44 @@ out:
  */
 static int intel_xpower_pmic_get_raw_temp(struct regmap *regmap, int reg)
 {
+       int ret, adc_ts_pin_ctrl;
        u8 buf[2];
-       int ret;
 
-       ret = regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL,
-                          AXP288_ADC_TS_PIN_GPADC);
+       /*
+        * The current-source used for the battery temp-sensor (TS) is shared
+        * with the GPADC. For proper fuel-gauge and charger operation the TS
+        * current-source needs to be permanently on. But to read the GPADC we
+        * need to temporary switch the TS current-source to ondemand, so that
+        * the GPADC can use it, otherwise we will always read an all 0 value.
+        *
+        * Note that the switching from on to on-ondemand is not necessary
+        * when the TS current-source is off (this happens on devices which
+        * do not use the TS-pin).
+        */
+       ret = regmap_read(regmap, AXP288_ADC_TS_PIN_CTRL, &adc_ts_pin_ctrl);
        if (ret)
                return ret;
 
-       /* After switching to the GPADC pin give things some time to settle */
-       usleep_range(6000, 10000);
+       if (adc_ts_pin_ctrl & AXP288_ADC_TS_CURRENT_ON_OFF_MASK) {
+               ret = regmap_update_bits(regmap, AXP288_ADC_TS_PIN_CTRL,
+                                        AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+                                        AXP288_ADC_TS_CURRENT_ON_ONDEMAND);
+               if (ret)
+                       return ret;
+
+               /* Wait a bit after switching the current-source */
+               usleep_range(6000, 10000);
+       }
 
        ret = regmap_bulk_read(regmap, AXP288_GP_ADC_H, buf, 2);
        if (ret == 0)
                ret = (buf[0] << 4) + ((buf[1] >> 4) & 0x0f);
 
-       regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON);
+       if (adc_ts_pin_ctrl & AXP288_ADC_TS_CURRENT_ON_OFF_MASK) {
+               regmap_update_bits(regmap, AXP288_ADC_TS_PIN_CTRL,
+                                  AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+                                  AXP288_ADC_TS_CURRENT_ON);
+       }
 
        return ret;
 }
index 1b475bc..665e93c 100644 (file)
@@ -131,6 +131,23 @@ void acpi_power_resources_list_free(struct list_head *list)
        }
 }
 
+static bool acpi_power_resource_is_dup(union acpi_object *package,
+                                      unsigned int start, unsigned int i)
+{
+       acpi_handle rhandle, dup;
+       unsigned int j;
+
+       /* The caller is expected to check the package element types */
+       rhandle = package->package.elements[i].reference.handle;
+       for (j = start; j < i; j++) {
+               dup = package->package.elements[j].reference.handle;
+               if (dup == rhandle)
+                       return true;
+       }
+
+       return false;
+}
+
 int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
                                 struct list_head *list)
 {
@@ -150,6 +167,11 @@ int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
                        err = -ENODEV;
                        break;
                }
+
+               /* Some ACPI tables contain duplicate power resource references */
+               if (acpi_power_resource_is_dup(package, start, i))
+                       continue;
+
                err = acpi_add_power_resource(rhandle);
                if (err)
                        break;
index cdfc876..4d2b2ad 100644 (file)
@@ -5854,9 +5854,10 @@ static int __init init_binder_device(const char *name)
 static int __init binder_init(void)
 {
        int ret;
-       char *device_name, *device_names, *device_tmp;
+       char *device_name, *device_tmp;
        struct binder_device *device;
        struct hlist_node *tmp;
+       char *device_names = NULL;
 
        ret = binder_alloc_shrinker_init();
        if (ret)
@@ -5898,23 +5899,29 @@ static int __init binder_init(void)
                                    &transaction_log_fops);
        }
 
-       /*
-        * Copy the module_parameter string, because we don't want to
-        * tokenize it in-place.
-        */
-       device_names = kstrdup(binder_devices_param, GFP_KERNEL);
-       if (!device_names) {
-               ret = -ENOMEM;
-               goto err_alloc_device_names_failed;
-       }
+       if (strcmp(binder_devices_param, "") != 0) {
+               /*
+               * Copy the module_parameter string, because we don't want to
+               * tokenize it in-place.
+                */
+               device_names = kstrdup(binder_devices_param, GFP_KERNEL);
+               if (!device_names) {
+                       ret = -ENOMEM;
+                       goto err_alloc_device_names_failed;
+               }
 
-       device_tmp = device_names;
-       while ((device_name = strsep(&device_tmp, ","))) {
-               ret = init_binder_device(device_name);
-               if (ret)
-                       goto err_init_binder_device_failed;
+               device_tmp = device_names;
+               while ((device_name = strsep(&device_tmp, ","))) {
+                       ret = init_binder_device(device_name);
+                       if (ret)
+                               goto err_init_binder_device_failed;
+               }
        }
 
+       ret = init_binderfs();
+       if (ret)
+               goto err_init_binder_device_failed;
+
        return ret;
 
 err_init_binder_device_failed:
index 7fb97f5..045b3e4 100644 (file)
@@ -46,4 +46,13 @@ static inline bool is_binderfs_device(const struct inode *inode)
 }
 #endif
 
+#ifdef CONFIG_ANDROID_BINDERFS
+extern int __init init_binderfs(void);
+#else
+static inline int __init init_binderfs(void)
+{
+       return 0;
+}
+#endif
+
 #endif /* _LINUX_BINDER_INTERNAL_H */
index 7496b10..e773f45 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kdev_t.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/namei.h>
 #include <linux/magic.h>
 #include <linux/major.h>
 #include <linux/miscdevice.h>
@@ -20,6 +21,7 @@
 #include <linux/parser.h>
 #include <linux/radix-tree.h>
 #include <linux/sched.h>
+#include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/spinlock_types.h>
 #include <linux/stddef.h>
@@ -30,7 +32,7 @@
 #include <linux/xarray.h>
 #include <uapi/asm-generic/errno-base.h>
 #include <uapi/linux/android/binder.h>
-#include <uapi/linux/android/binder_ctl.h>
+#include <uapi/linux/android/binderfs.h>
 
 #include "binder_internal.h"
 
 #define INODE_OFFSET 3
 #define INTSTRLEN 21
 #define BINDERFS_MAX_MINOR (1U << MINORBITS)
-
-static struct vfsmount *binderfs_mnt;
+/* Ensure that the initial ipc namespace always has devices available. */
+#define BINDERFS_MAX_MINOR_CAPPED (BINDERFS_MAX_MINOR - 4)
 
 static dev_t binderfs_dev;
 static DEFINE_MUTEX(binderfs_minors_mutex);
 static DEFINE_IDA(binderfs_minors);
 
 /**
+ * binderfs_mount_opts - mount options for binderfs
+ * @max: maximum number of allocatable binderfs binder devices
+ */
+struct binderfs_mount_opts {
+       int max;
+};
+
+enum {
+       Opt_max,
+       Opt_err
+};
+
+static const match_table_t tokens = {
+       { Opt_max, "max=%d" },
+       { Opt_err, NULL     }
+};
+
+/**
  * binderfs_info - information about a binderfs mount
  * @ipc_ns:         The ipc namespace the binderfs mount belongs to.
  * @control_dentry: This records the dentry of this binderfs mount
@@ -55,13 +75,16 @@ static DEFINE_IDA(binderfs_minors);
  *                  created.
  * @root_gid:       gid that needs to be used when a new binder device is
  *                  created.
+ * @mount_opts:     The mount options in use.
+ * @device_count:   The current number of allocated binder devices.
  */
 struct binderfs_info {
        struct ipc_namespace *ipc_ns;
        struct dentry *control_dentry;
        kuid_t root_uid;
        kgid_t root_gid;
-
+       struct binderfs_mount_opts mount_opts;
+       int device_count;
 };
 
 static inline struct binderfs_info *BINDERFS_I(const struct inode *inode)
@@ -84,7 +107,7 @@ bool is_binderfs_device(const struct inode *inode)
  * @userp:     buffer to copy information about new device for userspace to
  * @req:       struct binderfs_device as copied from userspace
  *
- * This function allocated a new binder_device and reserves a new minor
+ * This function allocates a new binder_device and reserves a new minor
  * number for it.
  * Minor numbers are limited and tracked globally in binderfs_minors. The
  * function will stash a struct binder_device for the specific binder
@@ -100,20 +123,34 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
                                         struct binderfs_device *req)
 {
        int minor, ret;
-       struct dentry *dentry, *dup, *root;
+       struct dentry *dentry, *root;
        struct binder_device *device;
-       size_t name_len = BINDERFS_MAX_NAME + 1;
        char *name = NULL;
+       size_t name_len;
        struct inode *inode = NULL;
        struct super_block *sb = ref_inode->i_sb;
        struct binderfs_info *info = sb->s_fs_info;
+#if defined(CONFIG_IPC_NS)
+       bool use_reserve = (info->ipc_ns == &init_ipc_ns);
+#else
+       bool use_reserve = true;
+#endif
 
        /* Reserve new minor number for the new device. */
        mutex_lock(&binderfs_minors_mutex);
-       minor = ida_alloc_max(&binderfs_minors, BINDERFS_MAX_MINOR, GFP_KERNEL);
-       mutex_unlock(&binderfs_minors_mutex);
-       if (minor < 0)
+       if (++info->device_count <= info->mount_opts.max)
+               minor = ida_alloc_max(&binderfs_minors,
+                                     use_reserve ? BINDERFS_MAX_MINOR :
+                                                   BINDERFS_MAX_MINOR_CAPPED,
+                                     GFP_KERNEL);
+       else
+               minor = -ENOSPC;
+       if (minor < 0) {
+               --info->device_count;
+               mutex_unlock(&binderfs_minors_mutex);
                return minor;
+       }
+       mutex_unlock(&binderfs_minors_mutex);
 
        ret = -ENOMEM;
        device = kzalloc(sizeof(*device), GFP_KERNEL);
@@ -132,12 +169,13 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
        inode->i_uid = info->root_uid;
        inode->i_gid = info->root_gid;
 
-       name = kmalloc(name_len, GFP_KERNEL);
+       req->name[BINDERFS_MAX_NAME] = '\0'; /* NUL-terminate */
+       name_len = strlen(req->name);
+       /* Make sure to include terminating NUL byte */
+       name = kmemdup(req->name, name_len + 1, GFP_KERNEL);
        if (!name)
                goto err;
 
-       strscpy(name, req->name, name_len);
-
        device->binderfs_inode = inode;
        device->context.binder_context_mgr_uid = INVALID_UID;
        device->context.name = name;
@@ -156,28 +194,25 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
 
        root = sb->s_root;
        inode_lock(d_inode(root));
-       dentry = d_alloc_name(root, name);
-       if (!dentry) {
+
+       /* look it up */
+       dentry = lookup_one_len(name, root, name_len);
+       if (IS_ERR(dentry)) {
                inode_unlock(d_inode(root));
-               ret = -ENOMEM;
+               ret = PTR_ERR(dentry);
                goto err;
        }
 
-       /* Verify that the name userspace gave us is not already in use. */
-       dup = d_lookup(root, &dentry->d_name);
-       if (dup) {
-               if (d_really_is_positive(dup)) {
-                       dput(dup);
-                       dput(dentry);
-                       inode_unlock(d_inode(root));
-                       ret = -EEXIST;
-                       goto err;
-               }
-               dput(dup);
+       if (d_really_is_positive(dentry)) {
+               /* already exists */
+               dput(dentry);
+               inode_unlock(d_inode(root));
+               ret = -EEXIST;
+               goto err;
        }
 
        inode->i_private = device;
-       d_add(dentry, inode);
+       d_instantiate(dentry, inode);
        fsnotify_create(root->d_inode, dentry);
        inode_unlock(d_inode(root));
 
@@ -187,6 +222,7 @@ err:
        kfree(name);
        kfree(device);
        mutex_lock(&binderfs_minors_mutex);
+       --info->device_count;
        ida_free(&binderfs_minors, minor);
        mutex_unlock(&binderfs_minors_mutex);
        iput(inode);
@@ -232,6 +268,7 @@ static long binder_ctl_ioctl(struct file *file, unsigned int cmd,
 static void binderfs_evict_inode(struct inode *inode)
 {
        struct binder_device *device = inode->i_private;
+       struct binderfs_info *info = BINDERFS_I(inode);
 
        clear_inode(inode);
 
@@ -239,6 +276,7 @@ static void binderfs_evict_inode(struct inode *inode)
                return;
 
        mutex_lock(&binderfs_minors_mutex);
+       --info->device_count;
        ida_free(&binderfs_minors, device->miscdev.minor);
        mutex_unlock(&binderfs_minors_mutex);
 
@@ -246,43 +284,87 @@ static void binderfs_evict_inode(struct inode *inode)
        kfree(device);
 }
 
+/**
+ * binderfs_parse_mount_opts - parse binderfs mount options
+ * @data: options to set (can be NULL in which case defaults are used)
+ */
+static int binderfs_parse_mount_opts(char *data,
+                                    struct binderfs_mount_opts *opts)
+{
+       char *p;
+       opts->max = BINDERFS_MAX_MINOR;
+
+       while ((p = strsep(&data, ",")) != NULL) {
+               substring_t args[MAX_OPT_ARGS];
+               int token;
+               int max_devices;
+
+               if (!*p)
+                       continue;
+
+               token = match_token(p, tokens, args);
+               switch (token) {
+               case Opt_max:
+                       if (match_int(&args[0], &max_devices) ||
+                           (max_devices < 0 ||
+                            (max_devices > BINDERFS_MAX_MINOR)))
+                               return -EINVAL;
+
+                       opts->max = max_devices;
+                       break;
+               default:
+                       pr_err("Invalid mount options\n");
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+static int binderfs_remount(struct super_block *sb, int *flags, char *data)
+{
+       struct binderfs_info *info = sb->s_fs_info;
+       return binderfs_parse_mount_opts(data, &info->mount_opts);
+}
+
+static int binderfs_show_mount_opts(struct seq_file *seq, struct dentry *root)
+{
+       struct binderfs_info *info;
+
+       info = root->d_sb->s_fs_info;
+       if (info->mount_opts.max <= BINDERFS_MAX_MINOR)
+               seq_printf(seq, ",max=%d", info->mount_opts.max);
+
+       return 0;
+}
+
 static const struct super_operations binderfs_super_ops = {
-       .statfs = simple_statfs,
-       .evict_inode = binderfs_evict_inode,
+       .evict_inode    = binderfs_evict_inode,
+       .remount_fs     = binderfs_remount,
+       .show_options   = binderfs_show_mount_opts,
+       .statfs         = simple_statfs,
 };
 
+static inline bool is_binderfs_control_device(const struct dentry *dentry)
+{
+       struct binderfs_info *info = dentry->d_sb->s_fs_info;
+       return info->control_dentry == dentry;
+}
+
 static int binderfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                           struct inode *new_dir, struct dentry *new_dentry,
                           unsigned int flags)
 {
-       struct inode *inode = d_inode(old_dentry);
-
-       /* binderfs doesn't support directories. */
-       if (d_is_dir(old_dentry))
+       if (is_binderfs_control_device(old_dentry) ||
+           is_binderfs_control_device(new_dentry))
                return -EPERM;
 
-       if (flags & ~RENAME_NOREPLACE)
-               return -EINVAL;
-
-       if (!simple_empty(new_dentry))
-               return -ENOTEMPTY;
-
-       if (d_really_is_positive(new_dentry))
-               simple_unlink(new_dir, new_dentry);
-
-       old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime =
-               new_dir->i_mtime = inode->i_ctime = current_time(old_dir);
-
-       return 0;
+       return simple_rename(old_dir, old_dentry, new_dir, new_dentry, flags);
 }
 
 static int binderfs_unlink(struct inode *dir, struct dentry *dentry)
 {
-       /*
-        * The control dentry is only ever touched during mount so checking it
-        * here should not require us to take lock.
-        */
-       if (BINDERFS_I(dir)->control_dentry == dentry)
+       if (is_binderfs_control_device(dentry))
                return -EPERM;
 
        return simple_unlink(dir, dentry);
@@ -313,13 +395,16 @@ static int binderfs_binder_ctl_create(struct super_block *sb)
        struct inode *inode = NULL;
        struct dentry *root = sb->s_root;
        struct binderfs_info *info = sb->s_fs_info;
+#if defined(CONFIG_IPC_NS)
+       bool use_reserve = (info->ipc_ns == &init_ipc_ns);
+#else
+       bool use_reserve = true;
+#endif
 
        device = kzalloc(sizeof(*device), GFP_KERNEL);
        if (!device)
                return -ENOMEM;
 
-       inode_lock(d_inode(root));
-
        /* If we have already created a binder-control node, return. */
        if (info->control_dentry) {
                ret = 0;
@@ -333,7 +418,10 @@ static int binderfs_binder_ctl_create(struct super_block *sb)
 
        /* Reserve a new minor number for the new device. */
        mutex_lock(&binderfs_minors_mutex);
-       minor = ida_alloc_max(&binderfs_minors, BINDERFS_MAX_MINOR, GFP_KERNEL);
+       minor = ida_alloc_max(&binderfs_minors,
+                             use_reserve ? BINDERFS_MAX_MINOR :
+                                           BINDERFS_MAX_MINOR_CAPPED,
+                             GFP_KERNEL);
        mutex_unlock(&binderfs_minors_mutex);
        if (minor < 0) {
                ret = minor;
@@ -358,12 +446,10 @@ static int binderfs_binder_ctl_create(struct super_block *sb)
        inode->i_private = device;
        info->control_dentry = dentry;
        d_add(dentry, inode);
-       inode_unlock(d_inode(root));
 
        return 0;
 
 out:
-       inode_unlock(d_inode(root));
        kfree(device);
        iput(inode);
 
@@ -378,12 +464,9 @@ static const struct inode_operations binderfs_dir_inode_operations = {
 
 static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
 {
+       int ret;
        struct binderfs_info *info;
-       int ret = -ENOMEM;
        struct inode *inode = NULL;
-       struct ipc_namespace *ipc_ns = sb->s_fs_info;
-
-       get_ipc_ns(ipc_ns);
 
        sb->s_blocksize = PAGE_SIZE;
        sb->s_blocksize_bits = PAGE_SHIFT;
@@ -405,11 +488,17 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_op = &binderfs_super_ops;
        sb->s_time_gran = 1;
 
-       info = kzalloc(sizeof(struct binderfs_info), GFP_KERNEL);
-       if (!info)
-               goto err_without_dentry;
+       sb->s_fs_info = kzalloc(sizeof(struct binderfs_info), GFP_KERNEL);
+       if (!sb->s_fs_info)
+               return -ENOMEM;
+       info = sb->s_fs_info;
+
+       info->ipc_ns = get_ipc_ns(current->nsproxy->ipc_ns);
+
+       ret = binderfs_parse_mount_opts(data, &info->mount_opts);
+       if (ret)
+               return ret;
 
-       info->ipc_ns = ipc_ns;
        info->root_gid = make_kgid(sb->s_user_ns, 0);
        if (!gid_valid(info->root_gid))
                info->root_gid = GLOBAL_ROOT_GID;
@@ -417,11 +506,9 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
        if (!uid_valid(info->root_uid))
                info->root_uid = GLOBAL_ROOT_UID;
 
-       sb->s_fs_info = info;
-
        inode = new_inode(sb);
        if (!inode)
-               goto err_without_dentry;
+               return -ENOMEM;
 
        inode->i_ino = FIRST_INODE;
        inode->i_fop = &simple_dir_operations;
@@ -432,79 +519,28 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
 
        sb->s_root = d_make_root(inode);
        if (!sb->s_root)
-               goto err_without_dentry;
-
-       ret = binderfs_binder_ctl_create(sb);
-       if (ret)
-               goto err_with_dentry;
-
-       return 0;
-
-err_with_dentry:
-       dput(sb->s_root);
-       sb->s_root = NULL;
-
-err_without_dentry:
-       put_ipc_ns(ipc_ns);
-       iput(inode);
-       kfree(info);
-
-       return ret;
-}
-
-static int binderfs_test_super(struct super_block *sb, void *data)
-{
-       struct binderfs_info *info = sb->s_fs_info;
-
-       if (info)
-               return info->ipc_ns == data;
-
-       return 0;
-}
+               return -ENOMEM;
 
-static int binderfs_set_super(struct super_block *sb, void *data)
-{
-       sb->s_fs_info = data;
-       return set_anon_super(sb, NULL);
+       return binderfs_binder_ctl_create(sb);
 }
 
 static struct dentry *binderfs_mount(struct file_system_type *fs_type,
                                     int flags, const char *dev_name,
                                     void *data)
 {
-       struct super_block *sb;
-       struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
-
-       if (!ns_capable(ipc_ns->user_ns, CAP_SYS_ADMIN))
-               return ERR_PTR(-EPERM);
-
-       sb = sget_userns(fs_type, binderfs_test_super, binderfs_set_super,
-                        flags, ipc_ns->user_ns, ipc_ns);
-       if (IS_ERR(sb))
-               return ERR_CAST(sb);
-
-       if (!sb->s_root) {
-               int ret = binderfs_fill_super(sb, data, flags & SB_SILENT ? 1 : 0);
-               if (ret) {
-                       deactivate_locked_super(sb);
-                       return ERR_PTR(ret);
-               }
-
-               sb->s_flags |= SB_ACTIVE;
-       }
-
-       return dget(sb->s_root);
+       return mount_nodev(fs_type, flags, data, binderfs_fill_super);
 }
 
 static void binderfs_kill_super(struct super_block *sb)
 {
        struct binderfs_info *info = sb->s_fs_info;
 
+       kill_litter_super(sb);
+
        if (info && info->ipc_ns)
                put_ipc_ns(info->ipc_ns);
 
        kfree(info);
-       kill_litter_super(sb);
 }
 
 static struct file_system_type binder_fs_type = {
@@ -514,7 +550,7 @@ static struct file_system_type binder_fs_type = {
        .fs_flags       = FS_USERNS_MOUNT,
 };
 
-static int __init init_binderfs(void)
+int __init init_binderfs(void)
 {
        int ret;
 
@@ -530,15 +566,5 @@ static int __init init_binderfs(void)
                return ret;
        }
 
-       binderfs_mnt = kern_mount(&binder_fs_type);
-       if (IS_ERR(binderfs_mnt)) {
-               ret = PTR_ERR(binderfs_mnt);
-               binderfs_mnt = NULL;
-               unregister_filesystem(&binder_fs_type);
-               unregister_chrdev_region(binderfs_dev, BINDERFS_MAX_MINOR);
-       }
-
        return ret;
 }
-
-device_initcall(init_binderfs);
index 4ca7a6b..8218db1 100644 (file)
@@ -1091,7 +1091,7 @@ comment "Generic fallback / legacy drivers"
 
 config PATA_ACPI
        tristate "ACPI firmware driver for PATA"
-       depends on ATA_ACPI && ATA_BMDMA
+       depends on ATA_ACPI && ATA_BMDMA && PCI
        help
          This option enables an ACPI method driver which drives
          motherboard PATA controller interfaces through the ACPI
index ef356e7..8810475 100644 (file)
@@ -254,6 +254,8 @@ enum {
        AHCI_HFLAG_IS_MOBILE            = (1 << 25), /* mobile chipset, use
                                                        SATA_MOBILE_LPM_POLICY
                                                        as default lpm_policy */
+       AHCI_HFLAG_SUSPEND_PHYS         = (1 << 26), /* handle PHYs during
+                                                       suspend/resume */
 
        /* ap->flags bits */
 
index f9cb51b..d4bba3a 100644 (file)
 #define AHCI_WINDOW_BASE(win)  (0x64 + ((win) << 4))
 #define AHCI_WINDOW_SIZE(win)  (0x68 + ((win) << 4))
 
+struct ahci_mvebu_plat_data {
+       int (*plat_config)(struct ahci_host_priv *hpriv);
+       unsigned int flags;
+};
+
 static void ahci_mvebu_mbus_config(struct ahci_host_priv *hpriv,
                                   const struct mbus_dram_target_info *dram)
 {
@@ -62,6 +67,35 @@ static void ahci_mvebu_regret_option(struct ahci_host_priv *hpriv)
        writel(0x80, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA);
 }
 
+static int ahci_mvebu_armada_380_config(struct ahci_host_priv *hpriv)
+{
+       const struct mbus_dram_target_info *dram;
+       int rc = 0;
+
+       dram = mv_mbus_dram_info();
+       if (dram)
+               ahci_mvebu_mbus_config(hpriv, dram);
+       else
+               rc = -ENODEV;
+
+       ahci_mvebu_regret_option(hpriv);
+
+       return rc;
+}
+
+static int ahci_mvebu_armada_3700_config(struct ahci_host_priv *hpriv)
+{
+       u32 reg;
+
+       writel(0, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_ADDR);
+
+       reg = readl(hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA);
+       reg |= BIT(6);
+       writel(reg, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA);
+
+       return 0;
+}
+
 /**
  * ahci_mvebu_stop_engine
  *
@@ -126,13 +160,9 @@ static int ahci_mvebu_resume(struct platform_device *pdev)
 {
        struct ata_host *host = platform_get_drvdata(pdev);
        struct ahci_host_priv *hpriv = host->private_data;
-       const struct mbus_dram_target_info *dram;
+       const struct ahci_mvebu_plat_data *pdata = hpriv->plat_data;
 
-       dram = mv_mbus_dram_info();
-       if (dram)
-               ahci_mvebu_mbus_config(hpriv, dram);
-
-       ahci_mvebu_regret_option(hpriv);
+       pdata->plat_config(hpriv);
 
        return ahci_platform_resume_host(&pdev->dev);
 }
@@ -154,29 +184,30 @@ static struct scsi_host_template ahci_platform_sht = {
 
 static int ahci_mvebu_probe(struct platform_device *pdev)
 {
+       const struct ahci_mvebu_plat_data *pdata;
        struct ahci_host_priv *hpriv;
-       const struct mbus_dram_target_info *dram;
        int rc;
 
+       pdata = of_device_get_match_data(&pdev->dev);
+       if (!pdata)
+               return -EINVAL;
+
        hpriv = ahci_platform_get_resources(pdev, 0);
        if (IS_ERR(hpriv))
                return PTR_ERR(hpriv);
 
+       hpriv->flags |= pdata->flags;
+       hpriv->plat_data = (void *)pdata;
+
        rc = ahci_platform_enable_resources(hpriv);
        if (rc)
                return rc;
 
        hpriv->stop_engine = ahci_mvebu_stop_engine;
 
-       if (of_device_is_compatible(pdev->dev.of_node,
-                                   "marvell,armada-380-ahci")) {
-               dram = mv_mbus_dram_info();
-               if (!dram)
-                       return -ENODEV;
-
-               ahci_mvebu_mbus_config(hpriv, dram);
-               ahci_mvebu_regret_option(hpriv);
-       }
+       rc = pdata->plat_config(hpriv);
+       if (rc)
+               goto disable_resources;
 
        rc = ahci_platform_init_host(pdev, hpriv, &ahci_mvebu_port_info,
                                     &ahci_platform_sht);
@@ -190,18 +221,28 @@ disable_resources:
        return rc;
 }
 
+static const struct ahci_mvebu_plat_data ahci_mvebu_armada_380_plat_data = {
+       .plat_config = ahci_mvebu_armada_380_config,
+};
+
+static const struct ahci_mvebu_plat_data ahci_mvebu_armada_3700_plat_data = {
+       .plat_config = ahci_mvebu_armada_3700_config,
+       .flags = AHCI_HFLAG_SUSPEND_PHYS,
+};
+
 static const struct of_device_id ahci_mvebu_of_match[] = {
-       { .compatible = "marvell,armada-380-ahci", },
-       { .compatible = "marvell,armada-3700-ahci", },
+       {
+               .compatible = "marvell,armada-380-ahci",
+               .data = &ahci_mvebu_armada_380_plat_data,
+       },
+       {
+               .compatible = "marvell,armada-3700-ahci",
+               .data = &ahci_mvebu_armada_3700_plat_data,
+       },
        { },
 };
 MODULE_DEVICE_TABLE(of, ahci_mvebu_of_match);
 
-/*
- * We currently don't provide power management related operations,
- * since there is no suspend/resume support at the platform level for
- * Armada 38x for the moment.
- */
 static struct platform_driver ahci_mvebu_driver = {
        .probe = ahci_mvebu_probe,
        .remove = ata_platform_remove_one,
index 4b900fc..81b1a33 100644 (file)
@@ -56,6 +56,12 @@ static int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
                if (rc)
                        goto disable_phys;
 
+               rc = phy_set_mode(hpriv->phys[i], PHY_MODE_SATA);
+               if (rc) {
+                       phy_exit(hpriv->phys[i]);
+                       goto disable_phys;
+               }
+
                rc = phy_power_on(hpriv->phys[i]);
                if (rc) {
                        phy_exit(hpriv->phys[i]);
@@ -738,6 +744,9 @@ int ahci_platform_suspend_host(struct device *dev)
        writel(ctl, mmio + HOST_CTL);
        readl(mmio + HOST_CTL); /* flush */
 
+       if (hpriv->flags & AHCI_HFLAG_SUSPEND_PHYS)
+               ahci_platform_disable_phys(hpriv);
+
        return ata_host_suspend(host, PMSG_SUSPEND);
 }
 EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
@@ -756,6 +765,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
 int ahci_platform_resume_host(struct device *dev)
 {
        struct ata_host *host = dev_get_drvdata(dev);
+       struct ahci_host_priv *hpriv = host->private_data;
        int rc;
 
        if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
@@ -766,6 +776,9 @@ int ahci_platform_resume_host(struct device *dev)
                ahci_init_controller(host);
        }
 
+       if (hpriv->flags & AHCI_HFLAG_SUSPEND_PHYS)
+               ahci_platform_enable_phys(hpriv);
+
        ata_host_resume(host);
 
        return 0;
index b8c3f9e..adf2878 100644 (file)
@@ -4554,6 +4554,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "SAMSUNG MZMPC128HBFU-000MV", "CXM14M1Q", ATA_HORKAGE_NOLPM, },
        { "SAMSUNG SSD PM830 mSATA *",  "CXM13D1Q", ATA_HORKAGE_NOLPM, },
        { "SAMSUNG MZ7TD256HAFV-000L9", NULL,       ATA_HORKAGE_NOLPM, },
+       { "SAMSUNG MZ7TE512HMHP-000L1", "EXT06L0Q", ATA_HORKAGE_NOLPM, },
 
        /* devices that don't properly handle queued TRIM commands */
        { "Micron_M500IT_*",            "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
index 8cc9c42..9e7fc30 100644 (file)
@@ -915,6 +915,10 @@ static struct scsi_host_template pata_macio_sht = {
        .sg_tablesize           = MAX_DCMDS,
        /* We may not need that strict one */
        .dma_boundary           = ATA_DMA_BOUNDARY,
+       /* Not sure what the real max is but we know it's less than 64K, let's
+        * use 64K minus 256
+        */
+       .max_segment_size       = MAX_DBDMA_SEG,
        .slave_configure        = pata_macio_slave_config,
 };
 
@@ -1044,11 +1048,6 @@ static int pata_macio_common_init(struct pata_macio_priv *priv,
        /* Make sure we have sane initial timings in the cache */
        pata_macio_default_timings(priv);
 
-       /* Not sure what the real max is but we know it's less than 64K, let's
-        * use 64K minus 256
-        */
-       dma_set_max_seg_size(priv->dev, MAX_DBDMA_SEG);
-
        /* Allocate libata host for 1 port */
        memset(&pinfo, 0, sizeof(struct ata_port_info));
        pmac_macio_calc_timing_masks(priv, &pinfo);
index 4dc528b..9c1247d 100644 (file)
@@ -729,8 +729,8 @@ static int sata_fsl_port_start(struct ata_port *ap)
        if (!pp)
                return -ENOMEM;
 
-       mem = dma_zalloc_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ, &mem_dma,
-                                 GFP_KERNEL);
+       mem = dma_alloc_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ, &mem_dma,
+                                GFP_KERNEL);
        if (!mem) {
                kfree(pp);
                return -ENOMEM;
index e0bcf9b..174e84c 100644 (file)
@@ -245,8 +245,15 @@ struct inic_port_priv {
 
 static struct scsi_host_template inic_sht = {
        ATA_BASE_SHT(DRV_NAME),
-       .sg_tablesize   = LIBATA_MAX_PRD,       /* maybe it can be larger? */
-       .dma_boundary   = INIC_DMA_BOUNDARY,
+       .sg_tablesize           = LIBATA_MAX_PRD, /* maybe it can be larger? */
+
+       /*
+        * This controller is braindamaged.  dma_boundary is 0xffff like others
+        * but it will lock up the whole machine HARD if 65536 byte PRD entry
+        * is fed.  Reduce maximum segment size.
+        */
+       .dma_boundary           = INIC_DMA_BOUNDARY,
+       .max_segment_size       = 65536 - 512,
 };
 
 static const int scr_map[] = {
@@ -868,17 +875,6 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                return rc;
        }
 
-       /*
-        * This controller is braindamaged.  dma_boundary is 0xffff
-        * like others but it will lock up the whole machine HARD if
-        * 65536 byte PRD entry is fed. Reduce maximum segment size.
-        */
-       rc = dma_set_max_seg_size(&pdev->dev, 65536 - 512);
-       if (rc) {
-               dev_err(&pdev->dev, "failed to set the maximum segment size\n");
-               return rc;
-       }
-
        rc = init_controller(hpriv->mmio_base, hpriv->cached_hctl);
        if (rc) {
                dev_err(&pdev->dev, "failed to initialize controller\n");
index 29f102d..2116079 100644 (file)
@@ -533,9 +533,10 @@ static void he_init_tx_lbfp(struct he_dev *he_dev)
 
 static int he_init_tpdrq(struct he_dev *he_dev)
 {
-       he_dev->tpdrq_base = dma_zalloc_coherent(&he_dev->pci_dev->dev,
-                                                CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq),
-                                                &he_dev->tpdrq_phys, GFP_KERNEL);
+       he_dev->tpdrq_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
+                                               CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq),
+                                               &he_dev->tpdrq_phys,
+                                               GFP_KERNEL);
        if (he_dev->tpdrq_base == NULL) {
                hprintk("failed to alloc tpdrq\n");
                return -ENOMEM;
@@ -717,7 +718,7 @@ static int he_init_cs_block_rcm(struct he_dev *he_dev)
                        instead of '/ 512', use '>> 9' to prevent a call
                        to divdu3 on x86 platforms
                */
-               rate_cps = (unsigned long long) (1 << exp) * (man + 512) >> 9;
+               rate_cps = (unsigned long long) (1UL << exp) * (man + 512) >> 9;
 
                if (rate_cps < 10)
                        rate_cps = 10;  /* 2.2.1 minimum payload rate is 10 cps */
@@ -805,9 +806,9 @@ static int he_init_group(struct he_dev *he_dev, int group)
                goto out_free_rbpl_virt;
        }
 
-       he_dev->rbpl_base = dma_zalloc_coherent(&he_dev->pci_dev->dev,
-                                               CONFIG_RBPL_SIZE * sizeof(struct he_rbp),
-                                               &he_dev->rbpl_phys, GFP_KERNEL);
+       he_dev->rbpl_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
+                                              CONFIG_RBPL_SIZE * sizeof(struct he_rbp),
+                                              &he_dev->rbpl_phys, GFP_KERNEL);
        if (he_dev->rbpl_base == NULL) {
                hprintk("failed to alloc rbpl_base\n");
                goto out_destroy_rbpl_pool;
@@ -844,9 +845,9 @@ static int he_init_group(struct he_dev *he_dev, int group)
 
        /* rx buffer ready queue */
 
-       he_dev->rbrq_base = dma_zalloc_coherent(&he_dev->pci_dev->dev,
-                                               CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq),
-                                               &he_dev->rbrq_phys, GFP_KERNEL);
+       he_dev->rbrq_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
+                                              CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq),
+                                              &he_dev->rbrq_phys, GFP_KERNEL);
        if (he_dev->rbrq_base == NULL) {
                hprintk("failed to allocate rbrq\n");
                goto out_free_rbpl;
@@ -868,9 +869,9 @@ static int he_init_group(struct he_dev *he_dev, int group)
 
        /* tx buffer ready queue */
 
-       he_dev->tbrq_base = dma_zalloc_coherent(&he_dev->pci_dev->dev,
-                                               CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
-                                               &he_dev->tbrq_phys, GFP_KERNEL);
+       he_dev->tbrq_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
+                                              CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
+                                              &he_dev->tbrq_phys, GFP_KERNEL);
        if (he_dev->tbrq_base == NULL) {
                hprintk("failed to allocate tbrq\n");
                goto out_free_rbpq_base;
@@ -913,11 +914,9 @@ static int he_init_irq(struct he_dev *he_dev)
        /* 2.9.3.5  tail offset for each interrupt queue is located after the
                    end of the interrupt queue */
 
-       he_dev->irq_base = dma_zalloc_coherent(&he_dev->pci_dev->dev,
-                                              (CONFIG_IRQ_SIZE + 1)
-                                              * sizeof(struct he_irq),
-                                              &he_dev->irq_phys,
-                                              GFP_KERNEL);
+       he_dev->irq_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
+                                             (CONFIG_IRQ_SIZE + 1) * sizeof(struct he_irq),
+                                             &he_dev->irq_phys, GFP_KERNEL);
        if (he_dev->irq_base == NULL) {
                hprintk("failed to allocate irq\n");
                return -ENOMEM;
@@ -1464,9 +1463,9 @@ static int he_start(struct atm_dev *dev)
 
        /* host status page */
 
-       he_dev->hsp = dma_zalloc_coherent(&he_dev->pci_dev->dev,
-                                         sizeof(struct he_hsp),
-                                         &he_dev->hsp_phys, GFP_KERNEL);
+       he_dev->hsp = dma_alloc_coherent(&he_dev->pci_dev->dev,
+                                        sizeof(struct he_hsp),
+                                        &he_dev->hsp_phys, GFP_KERNEL);
        if (he_dev->hsp == NULL) {
                hprintk("failed to allocate host status page\n");
                return -ENOMEM;
index 6e73714..43a1457 100644 (file)
@@ -641,8 +641,8 @@ alloc_scq(struct idt77252_dev *card, int class)
        scq = kzalloc(sizeof(struct scq_info), GFP_KERNEL);
        if (!scq)
                return NULL;
-       scq->base = dma_zalloc_coherent(&card->pcidev->dev, SCQ_SIZE,
-                                       &scq->paddr, GFP_KERNEL);
+       scq->base = dma_alloc_coherent(&card->pcidev->dev, SCQ_SIZE,
+                                      &scq->paddr, GFP_KERNEL);
        if (scq->base == NULL) {
                kfree(scq);
                return NULL;
@@ -971,8 +971,8 @@ init_rsq(struct idt77252_dev *card)
 {
        struct rsq_entry *rsqe;
 
-       card->rsq.base = dma_zalloc_coherent(&card->pcidev->dev, RSQSIZE,
-                                            &card->rsq.paddr, GFP_KERNEL);
+       card->rsq.base = dma_alloc_coherent(&card->pcidev->dev, RSQSIZE,
+                                           &card->rsq.paddr, GFP_KERNEL);
        if (card->rsq.base == NULL) {
                printk("%s: can't allocate RSQ.\n", card->name);
                return -1;
@@ -3390,10 +3390,10 @@ static int init_card(struct atm_dev *dev)
        writel(0, SAR_REG_GP);
 
        /* Initialize RAW Cell Handle Register  */
-       card->raw_cell_hnd = dma_zalloc_coherent(&card->pcidev->dev,
-                                                2 * sizeof(u32),
-                                                &card->raw_cell_paddr,
-                                                GFP_KERNEL);
+       card->raw_cell_hnd = dma_alloc_coherent(&card->pcidev->dev,
+                                               2 * sizeof(u32),
+                                               &card->raw_cell_paddr,
+                                               GFP_KERNEL);
        if (!card->raw_cell_hnd) {
                printk("%s: memory allocation failure.\n", card->name);
                deinit_card(card);
index a43276c..21393ec 100644 (file)
@@ -509,7 +509,7 @@ static int ht16k33_remove(struct i2c_client *client)
        struct ht16k33_priv *priv = i2c_get_clientdata(client);
        struct ht16k33_fbdev *fbdev = &priv->fbdev;
 
-       cancel_delayed_work(&fbdev->work);
+       cancel_delayed_work_sync(&fbdev->work);
        unregister_framebuffer(fbdev->info);
        framebuffer_release(fbdev->info);
        free_page((unsigned long) fbdev->buffer);
index cf78fa6..a735953 100644 (file)
@@ -79,8 +79,7 @@ static void cache_size(struct cacheinfo *this_leaf, struct device_node *np)
        ct_idx = get_cacheinfo_idx(this_leaf->type);
        propname = cache_type_info[ct_idx].size_prop;
 
-       if (of_property_read_u32(np, propname, &this_leaf->size))
-               this_leaf->size = 0;
+       of_property_read_u32(np, propname, &this_leaf->size);
 }
 
 /* not cache_line_size() because that's a macro in include/linux/cache.h */
@@ -114,8 +113,7 @@ static void cache_nr_sets(struct cacheinfo *this_leaf, struct device_node *np)
        ct_idx = get_cacheinfo_idx(this_leaf->type);
        propname = cache_type_info[ct_idx].nr_sets_prop;
 
-       if (of_property_read_u32(np, propname, &this_leaf->number_of_sets))
-               this_leaf->number_of_sets = 0;
+       of_property_read_u32(np, propname, &this_leaf->number_of_sets);
 }
 
 static void cache_associativity(struct cacheinfo *this_leaf)
index a690fd4..0992e67 100644 (file)
@@ -32,6 +32,7 @@
 #include <trace/events/power.h>
 #include <linux/cpufreq.h>
 #include <linux/cpuidle.h>
+#include <linux/devfreq.h>
 #include <linux/timer.h>
 
 #include "../base.h"
@@ -1078,6 +1079,7 @@ void dpm_resume(pm_message_t state)
        dpm_show_time(starttime, state, 0, NULL);
 
        cpufreq_resume();
+       devfreq_resume();
        trace_suspend_resume(TPS("dpm_resume"), state.event, false);
 }
 
@@ -1852,6 +1854,7 @@ int dpm_suspend(pm_message_t state)
        trace_suspend_resume(TPS("dpm_suspend"), state.event, true);
        might_sleep();
 
+       devfreq_suspend();
        cpufreq_suspend();
 
        mutex_lock(&dpm_list_mtx);
index 7062469..0ea2139 100644 (file)
@@ -121,7 +121,7 @@ static void pm_runtime_cancel_pending(struct device *dev)
  * Compute the autosuspend-delay expiration time based on the device's
  * power.last_busy time.  If the delay has already expired or is disabled
  * (negative) or the power.use_autosuspend flag isn't set, return 0.
- * Otherwise return the expiration time in jiffies (adjusted to be nonzero).
+ * Otherwise return the expiration time in nanoseconds (adjusted to be nonzero).
  *
  * This function may be called either with or without dev->power.lock held.
  * Either way it can be racy, since power.last_busy may be updated at any time.
@@ -130,7 +130,7 @@ u64 pm_runtime_autosuspend_expiration(struct device *dev)
 {
        int autosuspend_delay;
        u64 last_busy, expires = 0;
-       u64 now = ktime_to_ns(ktime_get());
+       u64 now = ktime_get_mono_fast_ns();
 
        if (!dev->power.use_autosuspend)
                goto out;
@@ -141,7 +141,7 @@ u64 pm_runtime_autosuspend_expiration(struct device *dev)
 
        last_busy = READ_ONCE(dev->power.last_busy);
 
-       expires = last_busy + autosuspend_delay * NSEC_PER_MSEC;
+       expires = last_busy + (u64)autosuspend_delay * NSEC_PER_MSEC;
        if (expires <= now)
                expires = 0;    /* Already expired. */
 
@@ -525,7 +525,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
                                 * We add a slack of 25% to gather wakeups
                                 * without sacrificing the granularity.
                                 */
-                               u64 slack = READ_ONCE(dev->power.autosuspend_delay) *
+                               u64 slack = (u64)READ_ONCE(dev->power.autosuspend_delay) *
                                                    (NSEC_PER_MSEC >> 2);
 
                                dev->power.timer_expires = expires;
@@ -905,8 +905,11 @@ static enum hrtimer_restart  pm_suspend_timer_fn(struct hrtimer *timer)
        spin_lock_irqsave(&dev->power.lock, flags);
 
        expires = dev->power.timer_expires;
-       /* If 'expire' is after 'jiffies' we've been called too early. */
-       if (expires > 0 && expires < ktime_to_ns(ktime_get())) {
+       /*
+        * If 'expires' is after the current time, we've been called
+        * too early.
+        */
+       if (expires > 0 && expires < ktime_get_mono_fast_ns()) {
                dev->power.timer_expires = 0;
                rpm_suspend(dev, dev->power.timer_autosuspends ?
                    (RPM_ASYNC | RPM_AUTO) : RPM_ASYNC);
@@ -925,7 +928,7 @@ static enum hrtimer_restart  pm_suspend_timer_fn(struct hrtimer *timer)
 int pm_schedule_suspend(struct device *dev, unsigned int delay)
 {
        unsigned long flags;
-       ktime_t expires;
+       u64 expires;
        int retval;
 
        spin_lock_irqsave(&dev->power.lock, flags);
@@ -942,8 +945,8 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay)
        /* Other scheduled or pending requests need to be canceled. */
        pm_runtime_cancel_pending(dev);
 
-       expires = ktime_add(ktime_get(), ms_to_ktime(delay));
-       dev->power.timer_expires = ktime_to_ns(expires);
+       expires = ktime_get_mono_fast_ns() + (u64)delay * NSEC_PER_MSEC;
+       dev->power.timer_expires = expires;
        dev->power.timer_autosuspends = 0;
        hrtimer_start(&dev->power.suspend_timer, expires, HRTIMER_MODE_ABS);
 
index 1bd1145..330c1f7 100644 (file)
@@ -108,6 +108,9 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
         * suppress pointless writes.
         */
        for (i = 0; i < d->chip->num_regs; i++) {
+               if (!d->chip->mask_base)
+                       continue;
+
                reg = d->chip->mask_base +
                        (i * map->reg_stride * d->irq_reg_stride);
                if (d->chip->mask_invert) {
@@ -258,7 +261,7 @@ static int regmap_irq_set_type(struct irq_data *data, unsigned int type)
        const struct regmap_irq_type *t = &irq_data->type;
 
        if ((t->types_supported & type) != type)
-               return -ENOTSUPP;
+               return 0;
 
        reg = t->type_reg_offset / map->reg_stride;
 
@@ -588,6 +591,9 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
        /* Mask all the interrupts by default */
        for (i = 0; i < chip->num_regs; i++) {
                d->mask_buf[i] = d->mask_buf_def[i];
+               if (!chip->mask_base)
+                       continue;
+
                reg = chip->mask_base +
                        (i * map->reg_stride * d->irq_reg_stride);
                if (chip->mask_invert)
index 6f2856c..55481b4 100644 (file)
@@ -4075,7 +4075,7 @@ static unsigned int floppy_check_events(struct gendisk *disk,
 
        if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) {
                if (lock_fdc(drive))
-                       return -EINTR;
+                       return 0;
                poll_drive(false, 0);
                process_fd_request();
        }
index b8a0720..cf55389 100644 (file)
@@ -1190,6 +1190,12 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
                goto out_unlock;
        }
 
+       if (lo->lo_offset != info->lo_offset ||
+           lo->lo_sizelimit != info->lo_sizelimit) {
+               sync_blockdev(lo->lo_device);
+               kill_bdev(lo->lo_device);
+       }
+
        /* I/O need to be drained during transfer transition */
        blk_mq_freeze_queue(lo->lo_queue);
 
@@ -1218,6 +1224,14 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
 
        if (lo->lo_offset != info->lo_offset ||
            lo->lo_sizelimit != info->lo_sizelimit) {
+               /* kill_bdev should have truncated all the pages */
+               if (lo->lo_device->bd_inode->i_mapping->nrpages) {
+                       err = -EAGAIN;
+                       pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n",
+                               __func__, lo->lo_number, lo->lo_file_name,
+                               lo->lo_device->bd_inode->i_mapping->nrpages);
+                       goto out_unfreeze;
+               }
                if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit)) {
                        err = -EFBIG;
                        goto out_unfreeze;
@@ -1443,22 +1457,39 @@ static int loop_set_dio(struct loop_device *lo, unsigned long arg)
 
 static int loop_set_block_size(struct loop_device *lo, unsigned long arg)
 {
+       int err = 0;
+
        if (lo->lo_state != Lo_bound)
                return -ENXIO;
 
        if (arg < 512 || arg > PAGE_SIZE || !is_power_of_2(arg))
                return -EINVAL;
 
+       if (lo->lo_queue->limits.logical_block_size != arg) {
+               sync_blockdev(lo->lo_device);
+               kill_bdev(lo->lo_device);
+       }
+
        blk_mq_freeze_queue(lo->lo_queue);
 
+       /* kill_bdev should have truncated all the pages */
+       if (lo->lo_queue->limits.logical_block_size != arg &&
+                       lo->lo_device->bd_inode->i_mapping->nrpages) {
+               err = -EAGAIN;
+               pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n",
+                       __func__, lo->lo_number, lo->lo_file_name,
+                       lo->lo_device->bd_inode->i_mapping->nrpages);
+               goto out_unfreeze;
+       }
+
        blk_queue_logical_block_size(lo->lo_queue, arg);
        blk_queue_physical_block_size(lo->lo_queue, arg);
        blk_queue_io_min(lo->lo_queue, arg);
        loop_update_dio(lo);
-
+out_unfreeze:
        blk_mq_unfreeze_queue(lo->lo_queue);
 
-       return 0;
+       return err;
 }
 
 static int lo_simple_ioctl(struct loop_device *lo, unsigned int cmd,
index 08696f5..7c9a949 100644 (file)
@@ -288,9 +288,10 @@ static void nbd_size_update(struct nbd_device *nbd)
        blk_queue_physical_block_size(nbd->disk->queue, config->blksize);
        set_capacity(nbd->disk, config->bytesize >> 9);
        if (bdev) {
-               if (bdev->bd_disk)
+               if (bdev->bd_disk) {
                        bd_set_size(bdev, config->bytesize);
-               else
+                       set_blocksize(bdev, config->blksize);
+               } else
                        bdev->bd_invalidated = 1;
                bdput(bdev);
        }
index b3df279..34b22d6 100644 (file)
@@ -97,6 +97,7 @@ void null_zone_reset(struct nullb_cmd *cmd, sector_t sector);
 #else
 static inline int null_zone_init(struct nullb_device *dev)
 {
+       pr_err("null_blk: CONFIG_BLK_DEV_ZONED not enabled\n");
        return -EINVAL;
 }
 static inline void null_zone_exit(struct nullb_device *dev) {}
index 8e5140b..1e92b61 100644 (file)
@@ -5986,7 +5986,6 @@ static ssize_t do_rbd_remove(struct bus_type *bus,
        struct list_head *tmp;
        int dev_id;
        char opt_buf[6];
-       bool already = false;
        bool force = false;
        int ret;
 
@@ -6019,13 +6018,13 @@ static ssize_t do_rbd_remove(struct bus_type *bus,
                spin_lock_irq(&rbd_dev->lock);
                if (rbd_dev->open_count && !force)
                        ret = -EBUSY;
-               else
-                       already = test_and_set_bit(RBD_DEV_FLAG_REMOVING,
-                                                       &rbd_dev->flags);
+               else if (test_and_set_bit(RBD_DEV_FLAG_REMOVING,
+                                         &rbd_dev->flags))
+                       ret = -EINPROGRESS;
                spin_unlock_irq(&rbd_dev->lock);
        }
        spin_unlock(&rbd_dev_list_lock);
-       if (ret < 0 || already)
+       if (ret)
                return ret;
 
        if (force) {
index a10d573..ab893a7 100644 (file)
@@ -2641,8 +2641,8 @@ static int skd_cons_skcomp(struct skd_device *skdev)
                "comp pci_alloc, total bytes %zd entries %d\n",
                SKD_SKCOMP_SIZE, SKD_N_COMPLETION_ENTRY);
 
-       skcomp = dma_zalloc_coherent(&skdev->pdev->dev, SKD_SKCOMP_SIZE,
-                                    &skdev->cq_dma_address, GFP_KERNEL);
+       skcomp = dma_alloc_coherent(&skdev->pdev->dev, SKD_SKCOMP_SIZE,
+                                   &skdev->cq_dma_address, GFP_KERNEL);
 
        if (skcomp == NULL) {
                rc = -ENOMEM;
index 33c5cc8..04ca659 100644 (file)
@@ -316,11 +316,9 @@ static ssize_t idle_store(struct device *dev,
                 * See the comment in writeback_store.
                 */
                zram_slot_lock(zram, index);
-               if (!zram_allocated(zram, index) ||
-                               zram_test_flag(zram, index, ZRAM_UNDER_WB))
-                       goto next;
-               zram_set_flag(zram, index, ZRAM_IDLE);
-next:
+               if (zram_allocated(zram, index) &&
+                               !zram_test_flag(zram, index, ZRAM_UNDER_WB))
+                       zram_set_flag(zram, index, ZRAM_IDLE);
                zram_slot_unlock(zram, index);
        }
 
@@ -330,6 +328,41 @@ next:
 }
 
 #ifdef CONFIG_ZRAM_WRITEBACK
+static ssize_t writeback_limit_enable_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t len)
+{
+       struct zram *zram = dev_to_zram(dev);
+       u64 val;
+       ssize_t ret = -EINVAL;
+
+       if (kstrtoull(buf, 10, &val))
+               return ret;
+
+       down_read(&zram->init_lock);
+       spin_lock(&zram->wb_limit_lock);
+       zram->wb_limit_enable = val;
+       spin_unlock(&zram->wb_limit_lock);
+       up_read(&zram->init_lock);
+       ret = len;
+
+       return ret;
+}
+
+static ssize_t writeback_limit_enable_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       bool val;
+       struct zram *zram = dev_to_zram(dev);
+
+       down_read(&zram->init_lock);
+       spin_lock(&zram->wb_limit_lock);
+       val = zram->wb_limit_enable;
+       spin_unlock(&zram->wb_limit_lock);
+       up_read(&zram->init_lock);
+
+       return scnprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
 static ssize_t writeback_limit_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t len)
 {
@@ -341,9 +374,9 @@ static ssize_t writeback_limit_store(struct device *dev,
                return ret;
 
        down_read(&zram->init_lock);
-       atomic64_set(&zram->stats.bd_wb_limit, val);
-       if (val == 0)
-               zram->stop_writeback = false;
+       spin_lock(&zram->wb_limit_lock);
+       zram->bd_wb_limit = val;
+       spin_unlock(&zram->wb_limit_lock);
        up_read(&zram->init_lock);
        ret = len;
 
@@ -357,7 +390,9 @@ static ssize_t writeback_limit_show(struct device *dev,
        struct zram *zram = dev_to_zram(dev);
 
        down_read(&zram->init_lock);
-       val = atomic64_read(&zram->stats.bd_wb_limit);
+       spin_lock(&zram->wb_limit_lock);
+       val = zram->bd_wb_limit;
+       spin_unlock(&zram->wb_limit_lock);
        up_read(&zram->init_lock);
 
        return scnprintf(buf, PAGE_SIZE, "%llu\n", val);
@@ -588,8 +623,8 @@ static int read_from_bdev_async(struct zram *zram, struct bio_vec *bvec,
        return 1;
 }
 
-#define HUGE_WRITEBACK 0x1
-#define IDLE_WRITEBACK 0x2
+#define HUGE_WRITEBACK 1
+#define IDLE_WRITEBACK 2
 
 static ssize_t writeback_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t len)
@@ -602,7 +637,7 @@ static ssize_t writeback_store(struct device *dev,
        struct page *page;
        ssize_t ret, sz;
        char mode_buf[8];
-       unsigned long mode = -1UL;
+       int mode = -1;
        unsigned long blk_idx = 0;
 
        sz = strscpy(mode_buf, buf, sizeof(mode_buf));
@@ -618,7 +653,7 @@ static ssize_t writeback_store(struct device *dev,
        else if (!strcmp(mode_buf, "huge"))
                mode = HUGE_WRITEBACK;
 
-       if (mode == -1UL)
+       if (mode == -1)
                return -EINVAL;
 
        down_read(&zram->init_lock);
@@ -645,10 +680,13 @@ static ssize_t writeback_store(struct device *dev,
                bvec.bv_len = PAGE_SIZE;
                bvec.bv_offset = 0;
 
-               if (zram->stop_writeback) {
+               spin_lock(&zram->wb_limit_lock);
+               if (zram->wb_limit_enable && !zram->bd_wb_limit) {
+                       spin_unlock(&zram->wb_limit_lock);
                        ret = -EIO;
                        break;
                }
+               spin_unlock(&zram->wb_limit_lock);
 
                if (!blk_idx) {
                        blk_idx = alloc_block_bdev(zram);
@@ -667,10 +705,11 @@ static ssize_t writeback_store(struct device *dev,
                                zram_test_flag(zram, index, ZRAM_UNDER_WB))
                        goto next;
 
-               if ((mode & IDLE_WRITEBACK &&
-                         !zram_test_flag(zram, index, ZRAM_IDLE)) &&
-                   (mode & HUGE_WRITEBACK &&
-                         !zram_test_flag(zram, index, ZRAM_HUGE)))
+               if (mode == IDLE_WRITEBACK &&
+                         !zram_test_flag(zram, index, ZRAM_IDLE))
+                       goto next;
+               if (mode == HUGE_WRITEBACK &&
+                         !zram_test_flag(zram, index, ZRAM_HUGE))
                        goto next;
                /*
                 * Clearing ZRAM_UNDER_WB is duty of caller.
@@ -732,11 +771,10 @@ static ssize_t writeback_store(struct device *dev,
                zram_set_element(zram, index, blk_idx);
                blk_idx = 0;
                atomic64_inc(&zram->stats.pages_stored);
-               if (atomic64_add_unless(&zram->stats.bd_wb_limit,
-                                       -1 << (PAGE_SHIFT - 12), 0)) {
-                       if (atomic64_read(&zram->stats.bd_wb_limit) == 0)
-                               zram->stop_writeback = true;
-               }
+               spin_lock(&zram->wb_limit_lock);
+               if (zram->wb_limit_enable && zram->bd_wb_limit > 0)
+                       zram->bd_wb_limit -=  1UL << (PAGE_SHIFT - 12);
+               spin_unlock(&zram->wb_limit_lock);
 next:
                zram_slot_unlock(zram, index);
        }
@@ -1812,6 +1850,7 @@ static DEVICE_ATTR_RW(comp_algorithm);
 static DEVICE_ATTR_RW(backing_dev);
 static DEVICE_ATTR_WO(writeback);
 static DEVICE_ATTR_RW(writeback_limit);
+static DEVICE_ATTR_RW(writeback_limit_enable);
 #endif
 
 static struct attribute *zram_disk_attrs[] = {
@@ -1828,6 +1867,7 @@ static struct attribute *zram_disk_attrs[] = {
        &dev_attr_backing_dev.attr,
        &dev_attr_writeback.attr,
        &dev_attr_writeback_limit.attr,
+       &dev_attr_writeback_limit_enable.attr,
 #endif
        &dev_attr_io_stat.attr,
        &dev_attr_mm_stat.attr,
@@ -1867,7 +1907,9 @@ static int zram_add(void)
        device_id = ret;
 
        init_rwsem(&zram->init_lock);
-
+#ifdef CONFIG_ZRAM_WRITEBACK
+       spin_lock_init(&zram->wb_limit_lock);
+#endif
        queue = blk_alloc_queue(GFP_KERNEL);
        if (!queue) {
                pr_err("Error allocating disk queue for device %d\n",
index 4bd3afd..f2fd46d 100644 (file)
@@ -86,7 +86,6 @@ struct zram_stats {
        atomic64_t bd_count;            /* no. of pages in backing device */
        atomic64_t bd_reads;            /* no. of reads from backing device */
        atomic64_t bd_writes;           /* no. of writes from backing device */
-       atomic64_t bd_wb_limit;         /* writeback limit of backing device */
 #endif
 };
 
@@ -114,8 +113,10 @@ struct zram {
         */
        bool claim; /* Protected by bdev->bd_mutex */
        struct file *backing_dev;
-       bool stop_writeback;
 #ifdef CONFIG_ZRAM_WRITEBACK
+       spinlock_t wb_limit_lock;
+       bool wb_limit_enable;
+       u64 bd_wb_limit;
        struct block_device *bdev;
        unsigned int old_block_size;
        unsigned long *bitmap;
index f94d335..d299ec7 100644 (file)
@@ -781,12 +781,12 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
        SYSC_QUIRK("smartreflex", 0, -1, 0x38, -1, 0x00000000, 0xffffffff,
                   SYSC_QUIRK_LEGACY_IDLE),
        SYSC_QUIRK("timer", 0, 0, 0x10, 0x14, 0x00000015, 0xffffffff,
-                  SYSC_QUIRK_LEGACY_IDLE),
+                  0),
        /* Some timers on omap4 and later */
        SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x50002100, 0xffffffff,
-                  SYSC_QUIRK_LEGACY_IDLE),
+                  0),
        SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x4fff1301, 0xffff00ff,
-                  SYSC_QUIRK_LEGACY_IDLE),
+                  0),
        SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff,
                   SYSC_QUIRK_LEGACY_IDLE),
        /* Uarts on omap4 and later */
index a74ce88..c518659 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/moduleparam.h>
 #include <linux/workqueue.h>
 #include <linux/uuid.h>
+#include <linux/nospec.h>
 
 #define IPMI_DRIVER_VERSION "39.2"
 
@@ -62,7 +63,8 @@ static void ipmi_debug_msg(const char *title, unsigned char *data,
 { }
 #endif
 
-static int initialized;
+static bool initialized;
+static bool drvregistered;
 
 enum ipmi_panic_event_op {
        IPMI_SEND_PANIC_EVENT_NONE,
@@ -612,7 +614,7 @@ static DEFINE_MUTEX(ipmidriver_mutex);
 
 static LIST_HEAD(ipmi_interfaces);
 static DEFINE_MUTEX(ipmi_interfaces_mutex);
-DEFINE_STATIC_SRCU(ipmi_interfaces_srcu);
+struct srcu_struct ipmi_interfaces_srcu;
 
 /*
  * List of watchers that want to know when smi's are added and deleted.
@@ -720,7 +722,15 @@ struct watcher_entry {
 int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
 {
        struct ipmi_smi *intf;
-       int index;
+       int index, rv;
+
+       /*
+        * Make sure the driver is actually initialized, this handles
+        * problems with initialization order.
+        */
+       rv = ipmi_init_msghandler();
+       if (rv)
+               return rv;
 
        mutex_lock(&smi_watchers_mutex);
 
@@ -884,7 +894,7 @@ static int deliver_response(struct ipmi_smi *intf, struct ipmi_recv_msg *msg)
 
                if (user) {
                        user->handler->ipmi_recv_hndl(msg, user->handler_data);
-                       release_ipmi_user(msg->user, index);
+                       release_ipmi_user(user, index);
                } else {
                        /* User went away, give up. */
                        ipmi_free_recv_msg(msg);
@@ -1076,7 +1086,7 @@ int ipmi_create_user(unsigned int          if_num,
 {
        unsigned long flags;
        struct ipmi_user *new_user;
-       int           rv = 0, index;
+       int           rv, index;
        struct ipmi_smi *intf;
 
        /*
@@ -1094,18 +1104,9 @@ int ipmi_create_user(unsigned int          if_num,
         * Make sure the driver is actually initialized, this handles
         * problems with initialization order.
         */
-       if (!initialized) {
-               rv = ipmi_init_msghandler();
-               if (rv)
-                       return rv;
-
-               /*
-                * The init code doesn't return an error if it was turned
-                * off, but it won't initialize.  Check that.
-                */
-               if (!initialized)
-                       return -ENODEV;
-       }
+       rv = ipmi_init_msghandler();
+       if (rv)
+               return rv;
 
        new_user = kmalloc(sizeof(*new_user), GFP_KERNEL);
        if (!new_user)
@@ -1183,6 +1184,7 @@ EXPORT_SYMBOL(ipmi_get_smi_info);
 static void free_user(struct kref *ref)
 {
        struct ipmi_user *user = container_of(ref, struct ipmi_user, refcount);
+       cleanup_srcu_struct(&user->release_barrier);
        kfree(user);
 }
 
@@ -1259,7 +1261,6 @@ int ipmi_destroy_user(struct ipmi_user *user)
 {
        _ipmi_destroy_user(user);
 
-       cleanup_srcu_struct(&user->release_barrier);
        kref_put(&user->refcount, free_user);
 
        return 0;
@@ -1298,10 +1299,12 @@ int ipmi_set_my_address(struct ipmi_user *user,
        if (!user)
                return -ENODEV;
 
-       if (channel >= IPMI_MAX_CHANNELS)
+       if (channel >= IPMI_MAX_CHANNELS) {
                rv = -EINVAL;
-       else
+       } else {
+               channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
                user->intf->addrinfo[channel].address = address;
+       }
        release_ipmi_user(user, index);
 
        return rv;
@@ -1318,10 +1321,12 @@ int ipmi_get_my_address(struct ipmi_user *user,
        if (!user)
                return -ENODEV;
 
-       if (channel >= IPMI_MAX_CHANNELS)
+       if (channel >= IPMI_MAX_CHANNELS) {
                rv = -EINVAL;
-       else
+       } else {
+               channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
                *address = user->intf->addrinfo[channel].address;
+       }
        release_ipmi_user(user, index);
 
        return rv;
@@ -1338,10 +1343,12 @@ int ipmi_set_my_LUN(struct ipmi_user *user,
        if (!user)
                return -ENODEV;
 
-       if (channel >= IPMI_MAX_CHANNELS)
+       if (channel >= IPMI_MAX_CHANNELS) {
                rv = -EINVAL;
-       else
+       } else {
+               channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
                user->intf->addrinfo[channel].lun = LUN & 0x3;
+       }
        release_ipmi_user(user, index);
 
        return rv;
@@ -1358,10 +1365,12 @@ int ipmi_get_my_LUN(struct ipmi_user *user,
        if (!user)
                return -ENODEV;
 
-       if (channel >= IPMI_MAX_CHANNELS)
+       if (channel >= IPMI_MAX_CHANNELS) {
                rv = -EINVAL;
-       else
+       } else {
+               channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
                *address = user->intf->addrinfo[channel].lun;
+       }
        release_ipmi_user(user, index);
 
        return rv;
@@ -2184,6 +2193,7 @@ static int check_addr(struct ipmi_smi  *intf,
 {
        if (addr->channel >= IPMI_MAX_CHANNELS)
                return -EINVAL;
+       addr->channel = array_index_nospec(addr->channel, IPMI_MAX_CHANNELS);
        *lun = intf->addrinfo[addr->channel].lun;
        *saddr = intf->addrinfo[addr->channel].address;
        return 0;
@@ -3291,17 +3301,9 @@ int ipmi_register_smi(const struct ipmi_smi_handlers *handlers,
         * Make sure the driver is actually initialized, this handles
         * problems with initialization order.
         */
-       if (!initialized) {
-               rv = ipmi_init_msghandler();
-               if (rv)
-                       return rv;
-               /*
-                * The init code doesn't return an error if it was turned
-                * off, but it won't initialize.  Check that.
-                */
-               if (!initialized)
-                       return -ENODEV;
-       }
+       rv = ipmi_init_msghandler();
+       if (rv)
+               return rv;
 
        intf = kzalloc(sizeof(*intf), GFP_KERNEL);
        if (!intf)
@@ -5017,6 +5019,22 @@ static int panic_event(struct notifier_block *this,
        return NOTIFY_DONE;
 }
 
+/* Must be called with ipmi_interfaces_mutex held. */
+static int ipmi_register_driver(void)
+{
+       int rv;
+
+       if (drvregistered)
+               return 0;
+
+       rv = driver_register(&ipmidriver.driver);
+       if (rv)
+               pr_err("Could not register IPMI driver\n");
+       else
+               drvregistered = true;
+       return rv;
+}
+
 static struct notifier_block panic_block = {
        .notifier_call  = panic_event,
        .next           = NULL,
@@ -5027,66 +5045,75 @@ static int ipmi_init_msghandler(void)
 {
        int rv;
 
+       mutex_lock(&ipmi_interfaces_mutex);
+       rv = ipmi_register_driver();
+       if (rv)
+               goto out;
        if (initialized)
-               return 0;
-
-       rv = driver_register(&ipmidriver.driver);
-       if (rv) {
-               pr_err("Could not register IPMI driver\n");
-               return rv;
-       }
+               goto out;
 
-       pr_info("version " IPMI_DRIVER_VERSION "\n");
+       init_srcu_struct(&ipmi_interfaces_srcu);
 
        timer_setup(&ipmi_timer, ipmi_timeout, 0);
        mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES);
 
        atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
 
-       initialized = 1;
+       initialized = true;
 
-       return 0;
+out:
+       mutex_unlock(&ipmi_interfaces_mutex);
+       return rv;
 }
 
 static int __init ipmi_init_msghandler_mod(void)
 {
-       ipmi_init_msghandler();
-       return 0;
+       int rv;
+
+       pr_info("version " IPMI_DRIVER_VERSION "\n");
+
+       mutex_lock(&ipmi_interfaces_mutex);
+       rv = ipmi_register_driver();
+       mutex_unlock(&ipmi_interfaces_mutex);
+
+       return rv;
 }
 
 static void __exit cleanup_ipmi(void)
 {
        int count;
 
-       if (!initialized)
-               return;
-
-       atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block);
+       if (initialized) {
+               atomic_notifier_chain_unregister(&panic_notifier_list,
+                                                &panic_block);
 
-       /*
-        * This can't be called if any interfaces exist, so no worry
-        * about shutting down the interfaces.
-        */
+               /*
+                * This can't be called if any interfaces exist, so no worry
+                * about shutting down the interfaces.
+                */
 
-       /*
-        * Tell the timer to stop, then wait for it to stop.  This
-        * avoids problems with race conditions removing the timer
-        * here.
-        */
-       atomic_inc(&stop_operation);
-       del_timer_sync(&ipmi_timer);
+               /*
+                * Tell the timer to stop, then wait for it to stop.  This
+                * avoids problems with race conditions removing the timer
+                * here.
+                */
+               atomic_inc(&stop_operation);
+               del_timer_sync(&ipmi_timer);
 
-       driver_unregister(&ipmidriver.driver);
+               initialized = false;
 
-       initialized = 0;
+               /* Check for buffer leaks. */
+               count = atomic_read(&smi_msg_inuse_count);
+               if (count != 0)
+                       pr_warn("SMI message count %d at exit\n", count);
+               count = atomic_read(&recv_msg_inuse_count);
+               if (count != 0)
+                       pr_warn("recv message count %d at exit\n", count);
 
-       /* Check for buffer leaks. */
-       count = atomic_read(&smi_msg_inuse_count);
-       if (count != 0)
-               pr_warn("SMI message count %d at exit\n", count);
-       count = atomic_read(&recv_msg_inuse_count);
-       if (count != 0)
-               pr_warn("recv message count %d at exit\n", count);
+               cleanup_srcu_struct(&ipmi_interfaces_srcu);
+       }
+       if (drvregistered)
+               driver_unregister(&ipmidriver.driver);
 }
 module_exit(cleanup_ipmi);
 
index ca9528c..b7a1ae2 100644 (file)
@@ -632,8 +632,9 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
 
                /* Remove the multi-part read marker. */
                len -= 2;
+               data += 2;
                for (i = 0; i < len; i++)
-                       ssif_info->data[i] = data[i+2];
+                       ssif_info->data[i] = data[i];
                ssif_info->multi_len = len;
                ssif_info->multi_pos = 1;
 
@@ -661,8 +662,19 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
                }
 
                blocknum = data[0];
+               len--;
+               data++;
+
+               if (blocknum != 0xff && len != 31) {
+                   /* All blocks but the last must have 31 data bytes. */
+                       result = -EIO;
+                       if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
+                               pr_info("Received middle message <31\n");
 
-               if (ssif_info->multi_len + len - 1 > IPMI_MAX_MSG_LENGTH) {
+                       goto continue_op;
+               }
+
+               if (ssif_info->multi_len + len > IPMI_MAX_MSG_LENGTH) {
                        /* Received message too big, abort the operation. */
                        result = -E2BIG;
                        if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
@@ -671,16 +683,14 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
                        goto continue_op;
                }
 
-               /* Remove the blocknum from the data. */
-               len--;
                for (i = 0; i < len; i++)
-                       ssif_info->data[i + ssif_info->multi_len] = data[i + 1];
+                       ssif_info->data[i + ssif_info->multi_len] = data[i];
                ssif_info->multi_len += len;
                if (blocknum == 0xff) {
                        /* End of read */
                        len = ssif_info->multi_len;
                        data = ssif_info->data;
-               } else if (blocknum + 1 != ssif_info->multi_pos) {
+               } else if (blocknum != ssif_info->multi_pos) {
                        /*
                         * Out of sequence block, just abort.  Block
                         * numbers start at zero for the second block,
@@ -707,6 +717,7 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
                }
        }
 
+ continue_op:
        if (result < 0) {
                ssif_inc_stat(ssif_info, receive_errors);
        } else {
@@ -714,8 +725,6 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
                ssif_inc_stat(ssif_info, received_message_parts);
        }
 
-
- continue_op:
        if (ssif_info->ssif_debug & SSIF_DEBUG_STATE)
                pr_info("DONE 1: state = %d, result=%d\n",
                        ssif_info->ssif_state, result);
index b5e3103..e43c876 100644 (file)
@@ -59,6 +59,7 @@
 #include <linux/mutex.h>
 #include <linux/delay.h>
 #include <linux/serial_8250.h>
+#include <linux/nospec.h>
 #include "smapi.h"
 #include "mwavedd.h"
 #include "3780i.h"
@@ -289,6 +290,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                                                ipcnum);
                                return -EINVAL;
                        }
+                       ipcnum = array_index_nospec(ipcnum,
+                                                   ARRAY_SIZE(pDrvData->IPCs));
                        PRINTK_3(TRACE_MWAVE,
                                "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
                                " ipcnum %x entry usIntCount %x\n",
@@ -317,6 +320,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                                                " Invalid ipcnum %x\n", ipcnum);
                                return -EINVAL;
                        }
+                       ipcnum = array_index_nospec(ipcnum,
+                                                   ARRAY_SIZE(pDrvData->IPCs));
                        PRINTK_3(TRACE_MWAVE,
                                "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC"
                                " ipcnum %x, usIntCount %x\n",
@@ -383,6 +388,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                                                ipcnum);
                                return -EINVAL;
                        }
+                       ipcnum = array_index_nospec(ipcnum,
+                                                   ARRAY_SIZE(pDrvData->IPCs));
                        mutex_lock(&mwave_mutex);
                        if (pDrvData->IPCs[ipcnum].bIsEnabled == true) {
                                pDrvData->IPCs[ipcnum].bIsEnabled = false;
index e5b2fe8..d2f0bb5 100644 (file)
@@ -293,7 +293,6 @@ config COMMON_CLK_BD718XX
 source "drivers/clk/actions/Kconfig"
 source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/hisilicon/Kconfig"
-source "drivers/clk/imx/Kconfig"
 source "drivers/clk/imgtec/Kconfig"
 source "drivers/clk/imx/Kconfig"
 source "drivers/clk/ingenic/Kconfig"
index 5b393e7..7d16ab0 100644 (file)
@@ -262,8 +262,10 @@ static int vc5_mux_set_parent(struct clk_hw *hw, u8 index)
 
                if (vc5->clk_mux_ins == VC5_MUX_IN_XIN)
                        src = VC5_PRIM_SRC_SHDN_EN_XTAL;
-               if (vc5->clk_mux_ins == VC5_MUX_IN_CLKIN)
+               else if (vc5->clk_mux_ins == VC5_MUX_IN_CLKIN)
                        src = VC5_PRIM_SRC_SHDN_EN_CLKIN;
+               else /* Invalid; should have been caught by vc5_probe() */
+                       return -EINVAL;
        }
 
        return regmap_update_bits(vc5->regmap, VC5_PRIM_SRC_SHDN, mask, src);
index 75d13c0..d2477a5 100644 (file)
@@ -1513,9 +1513,19 @@ static int clk_fetch_parent_index(struct clk_core *core,
        if (!parent)
                return -EINVAL;
 
-       for (i = 0; i < core->num_parents; i++)
-               if (clk_core_get_parent_by_index(core, i) == parent)
+       for (i = 0; i < core->num_parents; i++) {
+               if (core->parents[i] == parent)
+                       return i;
+
+               if (core->parents[i])
+                       continue;
+
+               /* Fallback to comparing globally unique names */
+               if (!strcmp(parent->name, core->parent_names[i])) {
+                       core->parents[i] = parent;
                        return i;
+               }
+       }
 
        return -EINVAL;
 }
@@ -2779,7 +2789,7 @@ static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
        seq_printf(s, "\"protect_count\": %d,", c->protect_count);
        seq_printf(s, "\"rate\": %lu,", clk_core_get_rate(c));
        seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c));
-       seq_printf(s, "\"phase\": %d", clk_core_get_phase(c));
+       seq_printf(s, "\"phase\": %d,", clk_core_get_phase(c));
        seq_printf(s, "\"duty_cycle\": %u",
                   clk_core_get_scaled_duty_cycle(c, 100000));
 }
index 0026c39..76b9eb1 100644 (file)
@@ -155,13 +155,14 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 {
        struct clk_frac_pll *pll = to_clk_frac_pll(hw);
        u32 val, divfi, divff;
-       u64 temp64 = parent_rate;
+       u64 temp64;
        int ret;
 
        parent_rate *= 8;
        rate *= 2;
        divfi = rate / parent_rate;
-       temp64 *= rate - divfi;
+       temp64 = parent_rate * divfi;
+       temp64 = rate - temp64;
        temp64 *= PLL_FRAC_DENOM;
        do_div(temp64, parent_rate);
        divff = temp64;
index 99c2508..fb6edf1 100644 (file)
@@ -169,6 +169,8 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev)
                return -ENODEV;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -EINVAL;
        base = devm_ioremap(dev, res->start, resource_size(res));
        if (!base)
                return -ENOMEM;
index 61fefc0..d083b86 100644 (file)
@@ -53,7 +53,6 @@
 #define APMU_DISP1     0x110
 #define APMU_CCIC0     0x50
 #define APMU_CCIC1     0xf4
-#define APMU_SP                0x68
 #define MPMU_UART_PLL  0x14
 
 struct mmp2_clk_unit {
@@ -210,8 +209,6 @@ static struct mmp_clk_mix_config ccic1_mix_config = {
        .reg_info = DEFINE_MIX_REG_INFO(4, 16, 2, 6, 32),
 };
 
-static DEFINE_SPINLOCK(sp_lock);
-
 static struct mmp_param_mux_clk apmu_mux_clks[] = {
        {MMP2_CLK_DISP0_MUX, "disp0_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP0, 6, 2, 0, &disp0_lock},
        {MMP2_CLK_DISP1_MUX, "disp1_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP1, 6, 2, 0, &disp1_lock},
@@ -242,7 +239,6 @@ static struct mmp_param_gate_clk apmu_gate_clks[] = {
        {MMP2_CLK_CCIC1, "ccic1_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x1b, 0x1b, 0x0, 0, &ccic1_lock},
        {MMP2_CLK_CCIC1_PHY, "ccic1_phy_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x24, 0x24, 0x0, 0, &ccic1_lock},
        {MMP2_CLK_CCIC1_SPHY, "ccic1_sphy_clk", "ccic1_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x300, 0x300, 0x0, 0, &ccic1_lock},
-       {MMP2_CLK_SP, "sp_clk", NULL, CLK_SET_RATE_PARENT, APMU_SP, 0x1b, 0x1b, 0x0, 0, &sp_lock},
 };
 
 static void mmp2_axi_periph_clk_init(struct mmp2_clk_unit *pxa_unit)
index 1b1ba54..1c04575 100644 (file)
@@ -215,6 +215,7 @@ config MSM_MMCC_8996
 
 config MSM_GCC_8998
        tristate "MSM8998 Global Clock Controller"
+       select QCOM_GDSC
        help
          Support for the global clock controller on msm8998 devices.
          Say Y if you want to use peripheral devices such as UART, SPI,
index c782e62..58fa5c2 100644 (file)
@@ -115,8 +115,8 @@ static const char * const gcc_parent_names_6[] = {
        "core_bi_pll_test_se",
 };
 
-static const char * const gcc_parent_names_7[] = {
-       "bi_tcxo",
+static const char * const gcc_parent_names_7_ao[] = {
+       "bi_tcxo_ao",
        "gpll0",
        "gpll0_out_even",
        "core_bi_pll_test_se",
@@ -128,6 +128,12 @@ static const char * const gcc_parent_names_8[] = {
        "core_bi_pll_test_se",
 };
 
+static const char * const gcc_parent_names_8_ao[] = {
+       "bi_tcxo_ao",
+       "gpll0",
+       "core_bi_pll_test_se",
+};
+
 static const struct parent_map gcc_parent_map_10[] = {
        { P_BI_TCXO, 0 },
        { P_GPLL0_OUT_MAIN, 1 },
@@ -210,7 +216,7 @@ static struct clk_rcg2 gcc_cpuss_ahb_clk_src = {
        .freq_tbl = ftbl_gcc_cpuss_ahb_clk_src,
        .clkr.hw.init = &(struct clk_init_data){
                .name = "gcc_cpuss_ahb_clk_src",
-               .parent_names = gcc_parent_names_7,
+               .parent_names = gcc_parent_names_7_ao,
                .num_parents = 4,
                .ops = &clk_rcg2_ops,
        },
@@ -229,7 +235,7 @@ static struct clk_rcg2 gcc_cpuss_rbcpr_clk_src = {
        .freq_tbl = ftbl_gcc_cpuss_rbcpr_clk_src,
        .clkr.hw.init = &(struct clk_init_data){
                .name = "gcc_cpuss_rbcpr_clk_src",
-               .parent_names = gcc_parent_names_8,
+               .parent_names = gcc_parent_names_8_ao,
                .num_parents = 3,
                .ops = &clk_rcg2_ops,
        },
index 2d5d8b4..c4d0b6f 100644 (file)
@@ -43,7 +43,7 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
        /* Read mdiv and fdiv from the fdbck register */
        reg = readl(socfpgaclk->hw.reg + 0x4);
        mdiv = (reg & SOCFPGA_PLL_MDIV_MASK) >> SOCFPGA_PLL_MDIV_SHIFT;
-       vco_freq = (unsigned long long)parent_rate * (mdiv + 6);
+       vco_freq = (unsigned long long)vco_freq * (mdiv + 6);
 
        return (unsigned long)vco_freq;
 }
index 5b238fc..8281dfb 100644 (file)
 
 #include "stratix10-clk.h"
 
-static const char * const pll_mux[] = { "osc1", "cb_intosc_hs_div2_clk",
-                                       "f2s_free_clk",};
+static const char * const pll_mux[] = { "osc1", "cb-intosc-hs-div2-clk",
+                                       "f2s-free-clk",};
 static const char * const cntr_mux[] = { "main_pll", "periph_pll",
-                                        "osc1", "cb_intosc_hs_div2_clk",
-                                        "f2s_free_clk"};
-static const char * const boot_mux[] = { "osc1", "cb_intosc_hs_div2_clk",};
+                                        "osc1", "cb-intosc-hs-div2-clk",
+                                        "f2s-free-clk"};
+static const char * const boot_mux[] = { "osc1", "cb-intosc-hs-div2-clk",};
 
 static const char * const noc_free_mux[] = {"main_noc_base_clk",
                                            "peri_noc_base_clk",
-                                           "osc1", "cb_intosc_hs_div2_clk",
-                                           "f2s_free_clk"};
+                                           "osc1", "cb-intosc-hs-div2-clk",
+                                           "f2s-free-clk"};
 
 static const char * const emaca_free_mux[] = {"peri_emaca_clk", "boot_clk"};
 static const char * const emacb_free_mux[] = {"peri_emacb_clk", "boot_clk"};
@@ -33,14 +33,14 @@ static const char * const s2f_usr1_free_mux[] = {"peri_s2f_usr1_clk", "boot_clk"
 static const char * const psi_ref_free_mux[] = {"peri_psi_ref_clk", "boot_clk"};
 static const char * const mpu_mux[] = { "mpu_free_clk", "boot_clk",};
 
-static const char * const s2f_usr0_mux[] = {"f2s_free_clk", "boot_clk"};
+static const char * const s2f_usr0_mux[] = {"f2s-free-clk", "boot_clk"};
 static const char * const emac_mux[] = {"emaca_free_clk", "emacb_free_clk"};
 static const char * const noc_mux[] = {"noc_free_clk", "boot_clk"};
 
 static const char * const mpu_free_mux[] = {"main_mpu_base_clk",
                                            "peri_mpu_base_clk",
-                                           "osc1", "cb_intosc_hs_div2_clk",
-                                           "f2s_free_clk"};
+                                           "osc1", "cb-intosc-hs-div2-clk",
+                                           "f2s-free-clk"};
 
 /* clocks in AO (always on) controller */
 static const struct stratix10_pll_clock s10_pll_clks[] = {
index 269d359..edc31bb 100644 (file)
@@ -133,9 +133,11 @@ static int tegra124_dfll_fcpu_remove(struct platform_device *pdev)
        struct tegra_dfll_soc_data *soc;
 
        soc = tegra_dfll_unregister(pdev);
-       if (IS_ERR(soc))
+       if (IS_ERR(soc)) {
                dev_err(&pdev->dev, "failed to unregister DFLL: %ld\n",
                        PTR_ERR(soc));
+               return PTR_ERR(soc);
+       }
 
        tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq);
 
index 8d77090..0241450 100644 (file)
@@ -403,8 +403,10 @@ int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
        num_dividers = i;
 
        tmp = kcalloc(valid_div + 1, sizeof(*tmp), GFP_KERNEL);
-       if (!tmp)
+       if (!tmp) {
+               *table = ERR_PTR(-ENOMEM);
                return -ENOMEM;
+       }
 
        valid_div = 0;
        *width = 0;
@@ -439,6 +441,7 @@ struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup)
 {
        struct clk_omap_divider *div;
        struct clk_omap_reg *reg;
+       int ret;
 
        if (!setup)
                return NULL;
@@ -458,6 +461,12 @@ struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup)
                div->flags |= CLK_DIVIDER_POWER_OF_TWO;
 
        div->table = _get_div_table_from_setup(setup, &div->width);
+       if (IS_ERR(div->table)) {
+               ret = PTR_ERR(div->table);
+               kfree(div);
+               return ERR_PTR(ret);
+       }
+
 
        div->shift = setup->bit_shift;
        div->latch = -EINVAL;
index f65cc0f..b0908ec 100644 (file)
@@ -669,8 +669,8 @@ static int zynqmp_clk_setup(struct device_node *np)
        if (ret)
                return ret;
 
-       zynqmp_data = kzalloc(sizeof(*zynqmp_data) + sizeof(*zynqmp_data) *
-                                               clock_max_idx, GFP_KERNEL);
+       zynqmp_data = kzalloc(struct_size(zynqmp_data, hws, clock_max_idx),
+                             GFP_KERNEL);
        if (!zynqmp_data)
                return -ENOMEM;
 
index 5951240..c364027 100644 (file)
@@ -154,6 +154,10 @@ static int omap_dm_timer_of_set_source(struct omap_dm_timer *timer)
        if (IS_ERR(parent))
                return -ENODEV;
 
+       /* Bail out if both clocks point to fck */
+       if (clk_is_match(parent, timer->fclk))
+               return 0;
+
        ret = clk_set_parent(timer->fclk, parent);
        if (ret < 0)
                pr_err("%s: failed to set parent\n", __func__);
@@ -864,7 +868,6 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
        timer->pdev = pdev;
 
        pm_runtime_enable(dev);
-       pm_runtime_irq_safe(dev);
 
        if (!timer->reserved) {
                ret = pm_runtime_get_sync(dev);
index 6f23ebb..e35a886 100644 (file)
@@ -1530,17 +1530,16 @@ static unsigned int __cpufreq_get(struct cpufreq_policy *policy)
 {
        unsigned int ret_freq = 0;
 
-       if (!cpufreq_driver->get)
+       if (unlikely(policy_is_inactive(policy)) || !cpufreq_driver->get)
                return ret_freq;
 
        ret_freq = cpufreq_driver->get(policy->cpu);
 
        /*
-        * Updating inactive policies is invalid, so avoid doing that.  Also
-        * if fast frequency switching is used with the given policy, the check
+        * If fast frequency switching is used with the given policy, the check
         * against policy->cur is pointless, so skip it in that case too.
         */
-       if (unlikely(policy_is_inactive(policy)) || policy->fast_switch_enabled)
+       if (policy->fast_switch_enabled)
                return ret_freq;
 
        if (ret_freq && policy->cur &&
@@ -1569,10 +1568,7 @@ unsigned int cpufreq_get(unsigned int cpu)
 
        if (policy) {
                down_read(&policy->rwsem);
-
-               if (!policy_is_inactive(policy))
-                       ret_freq = __cpufreq_get(policy);
-
+               ret_freq = __cpufreq_get(policy);
                up_read(&policy->rwsem);
 
                cpufreq_cpu_put(policy);
index 50b1551..242c337 100644 (file)
@@ -52,9 +52,9 @@ scmi_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index)
        int ret;
        struct scmi_data *priv = policy->driver_data;
        struct scmi_perf_ops *perf_ops = handle->perf_ops;
-       u64 freq = policy->freq_table[index].frequency * 1000;
+       u64 freq = policy->freq_table[index].frequency;
 
-       ret = perf_ops->freq_set(handle, priv->domain_id, freq, false);
+       ret = perf_ops->freq_set(handle, priv->domain_id, freq * 1000, false);
        if (!ret)
                arch_set_freq_scale(policy->related_cpus, freq,
                                    policy->cpuinfo.max_freq);
@@ -176,7 +176,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
 out_free_priv:
        kfree(priv);
 out_free_opp:
-       dev_pm_opp_cpumask_remove_table(policy->cpus);
+       dev_pm_opp_remove_all_dynamic(cpu_dev);
 
        return ret;
 }
@@ -188,7 +188,7 @@ static int scmi_cpufreq_exit(struct cpufreq_policy *policy)
        cpufreq_cooling_unregister(priv->cdev);
        dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
        kfree(priv);
-       dev_pm_opp_cpumask_remove_table(policy->related_cpus);
+       dev_pm_opp_remove_all_dynamic(priv->cpu_dev);
 
        return 0;
 }
index 87a98ec..9944973 100644 (file)
@@ -177,7 +177,7 @@ out_free_cpufreq_table:
 out_free_priv:
        kfree(priv);
 out_free_opp:
-       dev_pm_opp_cpumask_remove_table(policy->cpus);
+       dev_pm_opp_remove_all_dynamic(cpu_dev);
 
        return ret;
 }
@@ -190,7 +190,7 @@ static int scpi_cpufreq_exit(struct cpufreq_policy *policy)
        clk_put(priv->clk);
        dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
        kfree(priv);
-       dev_pm_opp_cpumask_remove_table(policy->related_cpus);
+       dev_pm_opp_remove_all_dynamic(priv->cpu_dev);
 
        return 0;
 }
index b17d153..23a1b27 100644 (file)
@@ -21,7 +21,7 @@ static int __cpuidle poll_idle(struct cpuidle_device *dev,
        local_irq_enable();
        if (!current_set_polling_and_test()) {
                unsigned int loop_count = 0;
-               u64 limit = TICK_USEC;
+               u64 limit = TICK_NSEC;
                int i;
 
                for (i = 1; i < drv->state_count; i++) {
index 5a90075..0be55fc 100644 (file)
@@ -692,6 +692,7 @@ config CRYPTO_DEV_BCM_SPU
        depends on ARCH_BCM_IPROC
        depends on MAILBOX
        default m
+       select CRYPTO_AUTHENC
        select CRYPTO_DES
        select CRYPTO_MD5
        select CRYPTO_SHA1
index 63cb695..acf7988 100644 (file)
@@ -283,9 +283,9 @@ static u32 crypto4xx_put_pd_to_pdr(struct crypto4xx_device *dev, u32 idx)
  */
 static u32 crypto4xx_build_gdr(struct crypto4xx_device *dev)
 {
-       dev->gdr = dma_zalloc_coherent(dev->core_dev->device,
-                                      sizeof(struct ce_gd) * PPC4XX_NUM_GD,
-                                      &dev->gdr_pa, GFP_ATOMIC);
+       dev->gdr = dma_alloc_coherent(dev->core_dev->device,
+                                     sizeof(struct ce_gd) * PPC4XX_NUM_GD,
+                                     &dev->gdr_pa, GFP_ATOMIC);
        if (!dev->gdr)
                return -ENOMEM;
 
index c9393ff..5567cbd 100644 (file)
@@ -2845,44 +2845,28 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
        struct spu_hw *spu = &iproc_priv.spu;
        struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
        struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
-       struct rtattr *rta = (void *)key;
-       struct crypto_authenc_key_param *param;
-       const u8 *origkey = key;
-       const unsigned int origkeylen = keylen;
-
-       int ret = 0;
+       struct crypto_authenc_keys keys;
+       int ret;
 
        flow_log("%s() aead:%p key:%p keylen:%u\n", __func__, cipher, key,
                 keylen);
        flow_dump("  key: ", key, keylen);
 
-       if (!RTA_OK(rta, keylen))
-               goto badkey;
-       if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
-               goto badkey;
-       if (RTA_PAYLOAD(rta) < sizeof(*param))
+       ret = crypto_authenc_extractkeys(&keys, key, keylen);
+       if (ret)
                goto badkey;
 
-       param = RTA_DATA(rta);
-       ctx->enckeylen = be32_to_cpu(param->enckeylen);
-
-       key += RTA_ALIGN(rta->rta_len);
-       keylen -= RTA_ALIGN(rta->rta_len);
-
-       if (keylen < ctx->enckeylen)
-               goto badkey;
-       if (ctx->enckeylen > MAX_KEY_SIZE)
+       if (keys.enckeylen > MAX_KEY_SIZE ||
+           keys.authkeylen > MAX_KEY_SIZE)
                goto badkey;
 
-       ctx->authkeylen = keylen - ctx->enckeylen;
-
-       if (ctx->authkeylen > MAX_KEY_SIZE)
-               goto badkey;
+       ctx->enckeylen = keys.enckeylen;
+       ctx->authkeylen = keys.authkeylen;
 
-       memcpy(ctx->enckey, key + ctx->authkeylen, ctx->enckeylen);
+       memcpy(ctx->enckey, keys.enckey, keys.enckeylen);
        /* May end up padding auth key. So make sure it's zeroed. */
        memset(ctx->authkey, 0, sizeof(ctx->authkey));
-       memcpy(ctx->authkey, key, ctx->authkeylen);
+       memcpy(ctx->authkey, keys.authkey, keys.authkeylen);
 
        switch (ctx->alg->cipher_info.alg) {
        case CIPHER_ALG_DES:
@@ -2890,7 +2874,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
                        u32 tmp[DES_EXPKEY_WORDS];
                        u32 flags = CRYPTO_TFM_RES_WEAK_KEY;
 
-                       if (des_ekey(tmp, key) == 0) {
+                       if (des_ekey(tmp, keys.enckey) == 0) {
                                if (crypto_aead_get_flags(cipher) &
                                    CRYPTO_TFM_REQ_WEAK_KEY) {
                                        crypto_aead_set_flags(cipher, flags);
@@ -2905,7 +2889,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
                break;
        case CIPHER_ALG_3DES:
                if (ctx->enckeylen == (DES_KEY_SIZE * 3)) {
-                       const u32 *K = (const u32 *)key;
+                       const u32 *K = (const u32 *)keys.enckey;
                        u32 flags = CRYPTO_TFM_RES_BAD_KEY_SCHED;
 
                        if (!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
@@ -2956,9 +2940,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
                ctx->fallback_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
                ctx->fallback_cipher->base.crt_flags |=
                    tfm->crt_flags & CRYPTO_TFM_REQ_MASK;
-               ret =
-                   crypto_aead_setkey(ctx->fallback_cipher, origkey,
-                                      origkeylen);
+               ret = crypto_aead_setkey(ctx->fallback_cipher, key, keylen);
                if (ret) {
                        flow_log("  fallback setkey() returned:%d\n", ret);
                        tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
index 92e593e..80ae69f 100644 (file)
@@ -3476,7 +3476,7 @@ static int __init caam_algapi_init(void)
                 * Skip algorithms requiring message digests
                 * if MD or MD size is not supported by device.
                 */
-               if ((c2_alg_sel & ~OP_ALG_ALGSEL_SUBMASK) == 0x40 &&
+               if (is_mdha(c2_alg_sel) &&
                    (!md_inst || t_alg->aead.maxauthsize > md_limit))
                        continue;
 
index 81712aa..bb1a2cd 100644 (file)
@@ -1072,13 +1072,16 @@ static int ahash_final_no_ctx(struct ahash_request *req)
 
        desc = edesc->hw_desc;
 
-       state->buf_dma = dma_map_single(jrdev, buf, buflen, DMA_TO_DEVICE);
-       if (dma_mapping_error(jrdev, state->buf_dma)) {
-               dev_err(jrdev, "unable to map src\n");
-               goto unmap;
-       }
+       if (buflen) {
+               state->buf_dma = dma_map_single(jrdev, buf, buflen,
+                                               DMA_TO_DEVICE);
+               if (dma_mapping_error(jrdev, state->buf_dma)) {
+                       dev_err(jrdev, "unable to map src\n");
+                       goto unmap;
+               }
 
-       append_seq_in_ptr(desc, state->buf_dma, buflen, 0);
+               append_seq_in_ptr(desc, state->buf_dma, buflen, 0);
+       }
 
        edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
                                                digestsize);
index ec10230..4b6854b 100644 (file)
 #define OP_ALG_ALGSEL_DES      (0x20 << OP_ALG_ALGSEL_SHIFT)
 #define OP_ALG_ALGSEL_3DES     (0x21 << OP_ALG_ALGSEL_SHIFT)
 #define OP_ALG_ALGSEL_ARC4     (0x30 << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_CHA_MDHA                (0x40 << OP_ALG_ALGSEL_SHIFT)
 #define OP_ALG_ALGSEL_MD5      (0x40 << OP_ALG_ALGSEL_SHIFT)
 #define OP_ALG_ALGSEL_SHA1     (0x41 << OP_ALG_ALGSEL_SHIFT)
 #define OP_ALG_ALGSEL_SHA224   (0x42 << OP_ALG_ALGSEL_SHIFT)
index 67ea940..8c6b83e 100644 (file)
@@ -7,6 +7,9 @@
 
 #ifndef CAAM_ERROR_H
 #define CAAM_ERROR_H
+
+#include "desc.h"
+
 #define CAAM_ERROR_STR_MAX 302
 
 void caam_strstatus(struct device *dev, u32 status, bool qi_v2);
@@ -17,4 +20,10 @@ void caam_strstatus(struct device *dev, u32 status, bool qi_v2);
 void caam_dump_sg(const char *level, const char *prefix_str, int prefix_type,
                  int rowsize, int groupsize, struct scatterlist *sg,
                  size_t tlen, bool ascii);
+
+static inline bool is_mdha(u32 algtype)
+{
+       return (algtype & OP_ALG_ALGSEL_MASK & ~OP_ALG_ALGSEL_SUBMASK) ==
+              OP_ALG_CHA_MDHA;
+}
 #endif /* CAAM_ERROR_H */
index 06ad85a..a876535 100644 (file)
@@ -278,8 +278,8 @@ static int cpt_ucode_load_fw(struct cpt_device *cpt, const u8 *fw, bool is_ae)
        mcode->num_cores = is_ae ? 6 : 10;
 
        /*  Allocate DMAable space */
-       mcode->code = dma_zalloc_coherent(&cpt->pdev->dev, mcode->code_size,
-                                         &mcode->phys_base, GFP_KERNEL);
+       mcode->code = dma_alloc_coherent(&cpt->pdev->dev, mcode->code_size,
+                                        &mcode->phys_base, GFP_KERNEL);
        if (!mcode->code) {
                dev_err(dev, "Unable to allocate space for microcode");
                ret = -ENOMEM;
index 5c796ed..2ca431e 100644 (file)
@@ -236,9 +236,10 @@ static int alloc_command_queues(struct cpt_vf *cptvf,
 
                        c_size = (rem_q_size > qcsize_bytes) ? qcsize_bytes :
                                        rem_q_size;
-                       curr->head = (u8 *)dma_zalloc_coherent(&pdev->dev,
-                                         c_size + CPT_NEXT_CHUNK_PTR_SIZE,
-                                         &curr->dma_addr, GFP_KERNEL);
+                       curr->head = (u8 *)dma_alloc_coherent(&pdev->dev,
+                                                             c_size + CPT_NEXT_CHUNK_PTR_SIZE,
+                                                             &curr->dma_addr,
+                                                             GFP_KERNEL);
                        if (!curr->head) {
                                dev_err(&pdev->dev, "Command Q (%d) chunk (%d) allocation failed\n",
                                        i, queue->nchunks);
index 9138bae..4ace9bc 100644 (file)
@@ -25,9 +25,9 @@ static int nitrox_cmdq_init(struct nitrox_cmdq *cmdq, int align_bytes)
        struct nitrox_device *ndev = cmdq->ndev;
 
        cmdq->qsize = (ndev->qlen * cmdq->instr_size) + align_bytes;
-       cmdq->unalign_base = dma_zalloc_coherent(DEV(ndev), cmdq->qsize,
-                                                &cmdq->unalign_dma,
-                                                GFP_KERNEL);
+       cmdq->unalign_base = dma_alloc_coherent(DEV(ndev), cmdq->qsize,
+                                               &cmdq->unalign_dma,
+                                               GFP_KERNEL);
        if (!cmdq->unalign_base)
                return -ENOMEM;
 
index e34e4df..4c97478 100644 (file)
@@ -537,6 +537,8 @@ static void process_response_list(struct nitrox_cmdq *cmdq)
        struct nitrox_device *ndev = cmdq->ndev;
        struct nitrox_softreq *sr;
        int req_completed = 0, err = 0, budget;
+       completion_t callback;
+       void *cb_arg;
 
        /* check all pending requests */
        budget = atomic_read(&cmdq->pending_count);
@@ -564,13 +566,13 @@ static void process_response_list(struct nitrox_cmdq *cmdq)
                smp_mb__after_atomic();
                /* remove from response list */
                response_list_del(sr, cmdq);
-
                /* ORH error code */
                err = READ_ONCE(*sr->resp.orh) & 0xff;
+               callback = sr->callback;
+               cb_arg = sr->cb_arg;
                softreq_destroy(sr);
-
-               if (sr->callback)
-                       sr->callback(sr->cb_arg, err);
+               if (callback)
+                       callback(cb_arg, err);
 
                req_completed++;
        }
index 44a4d27..c9bfd4f 100644 (file)
@@ -822,9 +822,9 @@ static int ccp5_init(struct ccp_device *ccp)
                /* Page alignment satisfies our needs for N <= 128 */
                BUILD_BUG_ON(COMMANDS_PER_QUEUE > 128);
                cmd_q->qsize = Q_SIZE(Q_DESC_SIZE);
-               cmd_q->qbase = dma_zalloc_coherent(dev, cmd_q->qsize,
-                                                  &cmd_q->qbase_dma,
-                                                  GFP_KERNEL);
+               cmd_q->qbase = dma_alloc_coherent(dev, cmd_q->qsize,
+                                                 &cmd_q->qbase_dma,
+                                                 GFP_KERNEL);
                if (!cmd_q->qbase) {
                        dev_err(dev, "unable to allocate command queue\n");
                        ret = -ENOMEM;
index f2643cd..a3527c0 100644 (file)
@@ -549,13 +549,12 @@ static int cc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
                          unsigned int keylen)
 {
        struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct rtattr *rta = (struct rtattr *)key;
        struct cc_crypto_req cc_req = {};
-       struct crypto_authenc_key_param *param;
        struct cc_hw_desc desc[MAX_AEAD_SETKEY_SEQ];
-       int rc = -EINVAL;
        unsigned int seq_len = 0;
        struct device *dev = drvdata_to_dev(ctx->drvdata);
+       const u8 *enckey, *authkey;
+       int rc;
 
        dev_dbg(dev, "Setting key in context @%p for %s. key=%p keylen=%u\n",
                ctx, crypto_tfm_alg_name(crypto_aead_tfm(tfm)), key, keylen);
@@ -563,35 +562,33 @@ static int cc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
        /* STAT_PHASE_0: Init and sanity checks */
 
        if (ctx->auth_mode != DRV_HASH_NULL) { /* authenc() alg. */
-               if (!RTA_OK(rta, keylen))
-                       goto badkey;
-               if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
-                       goto badkey;
-               if (RTA_PAYLOAD(rta) < sizeof(*param))
-                       goto badkey;
-               param = RTA_DATA(rta);
-               ctx->enc_keylen = be32_to_cpu(param->enckeylen);
-               key += RTA_ALIGN(rta->rta_len);
-               keylen -= RTA_ALIGN(rta->rta_len);
-               if (keylen < ctx->enc_keylen)
+               struct crypto_authenc_keys keys;
+
+               rc = crypto_authenc_extractkeys(&keys, key, keylen);
+               if (rc)
                        goto badkey;
-               ctx->auth_keylen = keylen - ctx->enc_keylen;
+               enckey = keys.enckey;
+               authkey = keys.authkey;
+               ctx->enc_keylen = keys.enckeylen;
+               ctx->auth_keylen = keys.authkeylen;
 
                if (ctx->cipher_mode == DRV_CIPHER_CTR) {
                        /* the nonce is stored in bytes at end of key */
+                       rc = -EINVAL;
                        if (ctx->enc_keylen <
                            (AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE))
                                goto badkey;
                        /* Copy nonce from last 4 bytes in CTR key to
                         *  first 4 bytes in CTR IV
                         */
-                       memcpy(ctx->ctr_nonce, key + ctx->auth_keylen +
-                              ctx->enc_keylen - CTR_RFC3686_NONCE_SIZE,
-                              CTR_RFC3686_NONCE_SIZE);
+                       memcpy(ctx->ctr_nonce, enckey + ctx->enc_keylen -
+                              CTR_RFC3686_NONCE_SIZE, CTR_RFC3686_NONCE_SIZE);
                        /* Set CTR key size */
                        ctx->enc_keylen -= CTR_RFC3686_NONCE_SIZE;
                }
        } else { /* non-authenc - has just one key */
+               enckey = key;
+               authkey = NULL;
                ctx->enc_keylen = keylen;
                ctx->auth_keylen = 0;
        }
@@ -603,13 +600,14 @@ static int cc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
        /* STAT_PHASE_1: Copy key to ctx */
 
        /* Get key material */
-       memcpy(ctx->enckey, key + ctx->auth_keylen, ctx->enc_keylen);
+       memcpy(ctx->enckey, enckey, ctx->enc_keylen);
        if (ctx->enc_keylen == 24)
                memset(ctx->enckey + 24, 0, CC_AES_KEY_SIZE_MAX - 24);
        if (ctx->auth_mode == DRV_HASH_XCBC_MAC) {
-               memcpy(ctx->auth_state.xcbc.xcbc_keys, key, ctx->auth_keylen);
+               memcpy(ctx->auth_state.xcbc.xcbc_keys, authkey,
+                      ctx->auth_keylen);
        } else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC */
-               rc = cc_get_plain_hmac_key(tfm, key, ctx->auth_keylen);
+               rc = cc_get_plain_hmac_key(tfm, authkey, ctx->auth_keylen);
                if (rc)
                        goto badkey;
        }
index 8ada308..b0125ad 100644 (file)
@@ -380,7 +380,7 @@ static int init_cc_resources(struct platform_device *plat_dev)
        rc = cc_ivgen_init(new_drvdata);
        if (rc) {
                dev_err(dev, "cc_ivgen_init failed\n");
-               goto post_power_mgr_err;
+               goto post_buf_mgr_err;
        }
 
        /* Allocate crypto algs */
@@ -403,6 +403,9 @@ static int init_cc_resources(struct platform_device *plat_dev)
                goto post_hash_err;
        }
 
+       /* All set, we can allow autosuspend */
+       cc_pm_go(new_drvdata);
+
        /* If we got here and FIPS mode is enabled
         * it means all FIPS test passed, so let TEE
         * know we're good.
@@ -417,8 +420,6 @@ post_cipher_err:
        cc_cipher_free(new_drvdata);
 post_ivgen_err:
        cc_ivgen_fini(new_drvdata);
-post_power_mgr_err:
-       cc_pm_fini(new_drvdata);
 post_buf_mgr_err:
         cc_buffer_mgr_fini(new_drvdata);
 post_req_mgr_err:
index d990f47..6ff7e75 100644 (file)
@@ -100,20 +100,19 @@ int cc_pm_put_suspend(struct device *dev)
 
 int cc_pm_init(struct cc_drvdata *drvdata)
 {
-       int rc = 0;
        struct device *dev = drvdata_to_dev(drvdata);
 
        /* must be before the enabling to avoid resdundent suspending */
        pm_runtime_set_autosuspend_delay(dev, CC_SUSPEND_TIMEOUT);
        pm_runtime_use_autosuspend(dev);
        /* activate the PM module */
-       rc = pm_runtime_set_active(dev);
-       if (rc)
-               return rc;
-       /* enable the PM module*/
-       pm_runtime_enable(dev);
+       return pm_runtime_set_active(dev);
+}
 
-       return rc;
+/* enable the PM module*/
+void cc_pm_go(struct cc_drvdata *drvdata)
+{
+       pm_runtime_enable(drvdata_to_dev(drvdata));
 }
 
 void cc_pm_fini(struct cc_drvdata *drvdata)
index 020a540..f626243 100644 (file)
@@ -16,6 +16,7 @@
 extern const struct dev_pm_ops ccree_pm;
 
 int cc_pm_init(struct cc_drvdata *drvdata);
+void cc_pm_go(struct cc_drvdata *drvdata);
 void cc_pm_fini(struct cc_drvdata *drvdata);
 int cc_pm_suspend(struct device *dev);
 int cc_pm_resume(struct device *dev);
@@ -29,6 +30,8 @@ static inline int cc_pm_init(struct cc_drvdata *drvdata)
        return 0;
 }
 
+static void cc_pm_go(struct cc_drvdata *drvdata) {}
+
 static inline void cc_pm_fini(struct cc_drvdata *drvdata) {}
 
 static inline int cc_pm_suspend(struct device *dev)
index cdc4f9a..adc0cd8 100644 (file)
@@ -241,8 +241,8 @@ static int sec_alg_skcipher_setkey(struct crypto_skcipher *tfm,
                memset(ctx->key, 0, SEC_MAX_CIPHER_KEY);
        } else {
                /* new key */
-               ctx->key = dma_zalloc_coherent(dev, SEC_MAX_CIPHER_KEY,
-                                              &ctx->pkey, GFP_KERNEL);
+               ctx->key = dma_alloc_coherent(dev, SEC_MAX_CIPHER_KEY,
+                                             &ctx->pkey, GFP_KERNEL);
                if (!ctx->key) {
                        mutex_unlock(&ctx->lock);
                        return -ENOMEM;
index c1ee4e7..91ee2bb 100644 (file)
@@ -1082,9 +1082,8 @@ static int sec_queue_res_cfg(struct sec_queue *queue)
        struct sec_queue_ring_db *ring_db = &queue->ring_db;
        int ret;
 
-       ring_cmd->vaddr = dma_zalloc_coherent(dev, SEC_Q_CMD_SIZE,
-                                             &ring_cmd->paddr,
-                                             GFP_KERNEL);
+       ring_cmd->vaddr = dma_alloc_coherent(dev, SEC_Q_CMD_SIZE,
+                                            &ring_cmd->paddr, GFP_KERNEL);
        if (!ring_cmd->vaddr)
                return -ENOMEM;
 
@@ -1092,17 +1091,15 @@ static int sec_queue_res_cfg(struct sec_queue *queue)
        mutex_init(&ring_cmd->lock);
        ring_cmd->callback = sec_alg_callback;
 
-       ring_cq->vaddr = dma_zalloc_coherent(dev, SEC_Q_CQ_SIZE,
-                                            &ring_cq->paddr,
-                                            GFP_KERNEL);
+       ring_cq->vaddr = dma_alloc_coherent(dev, SEC_Q_CQ_SIZE,
+                                           &ring_cq->paddr, GFP_KERNEL);
        if (!ring_cq->vaddr) {
                ret = -ENOMEM;
                goto err_free_ring_cmd;
        }
 
-       ring_db->vaddr = dma_zalloc_coherent(dev, SEC_Q_DB_SIZE,
-                                            &ring_db->paddr,
-                                            GFP_KERNEL);
+       ring_db->vaddr = dma_alloc_coherent(dev, SEC_Q_DB_SIZE,
+                                           &ring_db->paddr, GFP_KERNEL);
        if (!ring_db->vaddr) {
                ret = -ENOMEM;
                goto err_free_ring_cq;
index 19fba99..1b0d156 100644 (file)
@@ -260,9 +260,9 @@ static int setup_crypt_desc(void)
 {
        struct device *dev = &pdev->dev;
        BUILD_BUG_ON(sizeof(struct crypt_ctl) != 64);
-       crypt_virt = dma_zalloc_coherent(dev,
-                                        NPE_QLEN * sizeof(struct crypt_ctl),
-                                        &crypt_phys, GFP_ATOMIC);
+       crypt_virt = dma_alloc_coherent(dev,
+                                       NPE_QLEN * sizeof(struct crypt_ctl),
+                                       &crypt_phys, GFP_ATOMIC);
        if (!crypt_virt)
                return -ENOMEM;
        return 0;
index ee0404e..5660e5e 100644 (file)
@@ -453,17 +453,17 @@ static int mtk_desc_ring_alloc(struct mtk_cryp *cryp)
                if (!ring[i])
                        goto err_cleanup;
 
-               ring[i]->cmd_base = dma_zalloc_coherent(cryp->dev,
-                                          MTK_DESC_RING_SZ,
-                                          &ring[i]->cmd_dma,
-                                          GFP_KERNEL);
+               ring[i]->cmd_base = dma_alloc_coherent(cryp->dev,
+                                                      MTK_DESC_RING_SZ,
+                                                      &ring[i]->cmd_dma,
+                                                      GFP_KERNEL);
                if (!ring[i]->cmd_base)
                        goto err_cleanup;
 
-               ring[i]->res_base = dma_zalloc_coherent(cryp->dev,
-                                          MTK_DESC_RING_SZ,
-                                          &ring[i]->res_dma,
-                                          GFP_KERNEL);
+               ring[i]->res_base = dma_alloc_coherent(cryp->dev,
+                                                      MTK_DESC_RING_SZ,
+                                                      &ring[i]->res_dma,
+                                                      GFP_KERNEL);
                if (!ring[i]->res_base)
                        goto err_cleanup;
 
index 3744b22..d28cba3 100644 (file)
@@ -244,18 +244,18 @@ int adf_init_admin_comms(struct adf_accel_dev *accel_dev)
                             dev_to_node(&GET_DEV(accel_dev)));
        if (!admin)
                return -ENOMEM;
-       admin->virt_addr = dma_zalloc_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
-                                              &admin->phy_addr, GFP_KERNEL);
+       admin->virt_addr = dma_alloc_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
+                                             &admin->phy_addr, GFP_KERNEL);
        if (!admin->virt_addr) {
                dev_err(&GET_DEV(accel_dev), "Failed to allocate dma buff\n");
                kfree(admin);
                return -ENOMEM;
        }
 
-       admin->virt_tbl_addr = dma_zalloc_coherent(&GET_DEV(accel_dev),
-                                                  PAGE_SIZE,
-                                                  &admin->const_tbl_addr,
-                                                  GFP_KERNEL);
+       admin->virt_tbl_addr = dma_alloc_coherent(&GET_DEV(accel_dev),
+                                                 PAGE_SIZE,
+                                                 &admin->const_tbl_addr,
+                                                 GFP_KERNEL);
        if (!admin->virt_tbl_addr) {
                dev_err(&GET_DEV(accel_dev), "Failed to allocate const_tbl\n");
                dma_free_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
index d269829..975c751 100644 (file)
@@ -601,15 +601,15 @@ static int qat_alg_aead_setkey(struct crypto_aead *tfm, const uint8_t *key,
 
                dev = &GET_DEV(inst->accel_dev);
                ctx->inst = inst;
-               ctx->enc_cd = dma_zalloc_coherent(dev, sizeof(*ctx->enc_cd),
-                                                 &ctx->enc_cd_paddr,
-                                                 GFP_ATOMIC);
+               ctx->enc_cd = dma_alloc_coherent(dev, sizeof(*ctx->enc_cd),
+                                                &ctx->enc_cd_paddr,
+                                                GFP_ATOMIC);
                if (!ctx->enc_cd) {
                        return -ENOMEM;
                }
-               ctx->dec_cd = dma_zalloc_coherent(dev, sizeof(*ctx->dec_cd),
-                                                 &ctx->dec_cd_paddr,
-                                                 GFP_ATOMIC);
+               ctx->dec_cd = dma_alloc_coherent(dev, sizeof(*ctx->dec_cd),
+                                                &ctx->dec_cd_paddr,
+                                                GFP_ATOMIC);
                if (!ctx->dec_cd) {
                        goto out_free_enc;
                }
@@ -933,16 +933,16 @@ static int qat_alg_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
 
                dev = &GET_DEV(inst->accel_dev);
                ctx->inst = inst;
-               ctx->enc_cd = dma_zalloc_coherent(dev, sizeof(*ctx->enc_cd),
-                                                 &ctx->enc_cd_paddr,
-                                                 GFP_ATOMIC);
+               ctx->enc_cd = dma_alloc_coherent(dev, sizeof(*ctx->enc_cd),
+                                                &ctx->enc_cd_paddr,
+                                                GFP_ATOMIC);
                if (!ctx->enc_cd) {
                        spin_unlock(&ctx->lock);
                        return -ENOMEM;
                }
-               ctx->dec_cd = dma_zalloc_coherent(dev, sizeof(*ctx->dec_cd),
-                                                 &ctx->dec_cd_paddr,
-                                                 GFP_ATOMIC);
+               ctx->dec_cd = dma_alloc_coherent(dev, sizeof(*ctx->dec_cd),
+                                                &ctx->dec_cd_paddr,
+                                                GFP_ATOMIC);
                if (!ctx->dec_cd) {
                        spin_unlock(&ctx->lock);
                        goto out_free_enc;
index 320e785..c9f3247 100644 (file)
@@ -332,10 +332,10 @@ static int qat_dh_compute_value(struct kpp_request *req)
                } else {
                        int shift = ctx->p_size - req->src_len;
 
-                       qat_req->src_align = dma_zalloc_coherent(dev,
-                                                                ctx->p_size,
-                                                                &qat_req->in.dh.in.b,
-                                                                GFP_KERNEL);
+                       qat_req->src_align = dma_alloc_coherent(dev,
+                                                               ctx->p_size,
+                                                               &qat_req->in.dh.in.b,
+                                                               GFP_KERNEL);
                        if (unlikely(!qat_req->src_align))
                                return ret;
 
@@ -360,9 +360,9 @@ static int qat_dh_compute_value(struct kpp_request *req)
                        goto unmap_src;
 
        } else {
-               qat_req->dst_align = dma_zalloc_coherent(dev, ctx->p_size,
-                                                        &qat_req->out.dh.r,
-                                                        GFP_KERNEL);
+               qat_req->dst_align = dma_alloc_coherent(dev, ctx->p_size,
+                                                       &qat_req->out.dh.r,
+                                                       GFP_KERNEL);
                if (unlikely(!qat_req->dst_align))
                        goto unmap_src;
        }
@@ -447,7 +447,7 @@ static int qat_dh_set_params(struct qat_dh_ctx *ctx, struct dh *params)
                return -EINVAL;
 
        ctx->p_size = params->p_size;
-       ctx->p = dma_zalloc_coherent(dev, ctx->p_size, &ctx->dma_p, GFP_KERNEL);
+       ctx->p = dma_alloc_coherent(dev, ctx->p_size, &ctx->dma_p, GFP_KERNEL);
        if (!ctx->p)
                return -ENOMEM;
        memcpy(ctx->p, params->p, ctx->p_size);
@@ -458,7 +458,7 @@ static int qat_dh_set_params(struct qat_dh_ctx *ctx, struct dh *params)
                return 0;
        }
 
-       ctx->g = dma_zalloc_coherent(dev, ctx->p_size, &ctx->dma_g, GFP_KERNEL);
+       ctx->g = dma_alloc_coherent(dev, ctx->p_size, &ctx->dma_g, GFP_KERNEL);
        if (!ctx->g)
                return -ENOMEM;
        memcpy(ctx->g + (ctx->p_size - params->g_size), params->g,
@@ -503,8 +503,8 @@ static int qat_dh_set_secret(struct crypto_kpp *tfm, const void *buf,
        if (ret < 0)
                goto err_clear_ctx;
 
-       ctx->xa = dma_zalloc_coherent(dev, ctx->p_size, &ctx->dma_xa,
-                                     GFP_KERNEL);
+       ctx->xa = dma_alloc_coherent(dev, ctx->p_size, &ctx->dma_xa,
+                                    GFP_KERNEL);
        if (!ctx->xa) {
                ret = -ENOMEM;
                goto err_clear_ctx;
@@ -737,9 +737,9 @@ static int qat_rsa_enc(struct akcipher_request *req)
        } else {
                int shift = ctx->key_sz - req->src_len;
 
-               qat_req->src_align = dma_zalloc_coherent(dev, ctx->key_sz,
-                                                        &qat_req->in.rsa.enc.m,
-                                                        GFP_KERNEL);
+               qat_req->src_align = dma_alloc_coherent(dev, ctx->key_sz,
+                                                       &qat_req->in.rsa.enc.m,
+                                                       GFP_KERNEL);
                if (unlikely(!qat_req->src_align))
                        return ret;
 
@@ -756,9 +756,9 @@ static int qat_rsa_enc(struct akcipher_request *req)
                        goto unmap_src;
 
        } else {
-               qat_req->dst_align = dma_zalloc_coherent(dev, ctx->key_sz,
-                                                        &qat_req->out.rsa.enc.c,
-                                                        GFP_KERNEL);
+               qat_req->dst_align = dma_alloc_coherent(dev, ctx->key_sz,
+                                                       &qat_req->out.rsa.enc.c,
+                                                       GFP_KERNEL);
                if (unlikely(!qat_req->dst_align))
                        goto unmap_src;
 
@@ -881,9 +881,9 @@ static int qat_rsa_dec(struct akcipher_request *req)
        } else {
                int shift = ctx->key_sz - req->src_len;
 
-               qat_req->src_align = dma_zalloc_coherent(dev, ctx->key_sz,
-                                                        &qat_req->in.rsa.dec.c,
-                                                        GFP_KERNEL);
+               qat_req->src_align = dma_alloc_coherent(dev, ctx->key_sz,
+                                                       &qat_req->in.rsa.dec.c,
+                                                       GFP_KERNEL);
                if (unlikely(!qat_req->src_align))
                        return ret;
 
@@ -900,9 +900,9 @@ static int qat_rsa_dec(struct akcipher_request *req)
                        goto unmap_src;
 
        } else {
-               qat_req->dst_align = dma_zalloc_coherent(dev, ctx->key_sz,
-                                                        &qat_req->out.rsa.dec.m,
-                                                        GFP_KERNEL);
+               qat_req->dst_align = dma_alloc_coherent(dev, ctx->key_sz,
+                                                       &qat_req->out.rsa.dec.m,
+                                                       GFP_KERNEL);
                if (unlikely(!qat_req->dst_align))
                        goto unmap_src;
 
@@ -989,7 +989,7 @@ static int qat_rsa_set_n(struct qat_rsa_ctx *ctx, const char *value,
                goto err;
 
        ret = -ENOMEM;
-       ctx->n = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_n, GFP_KERNEL);
+       ctx->n = dma_alloc_coherent(dev, ctx->key_sz, &ctx->dma_n, GFP_KERNEL);
        if (!ctx->n)
                goto err;
 
@@ -1018,7 +1018,7 @@ static int qat_rsa_set_e(struct qat_rsa_ctx *ctx, const char *value,
                return -EINVAL;
        }
 
-       ctx->e = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_e, GFP_KERNEL);
+       ctx->e = dma_alloc_coherent(dev, ctx->key_sz, &ctx->dma_e, GFP_KERNEL);
        if (!ctx->e)
                return -ENOMEM;
 
@@ -1044,7 +1044,7 @@ static int qat_rsa_set_d(struct qat_rsa_ctx *ctx, const char *value,
                goto err;
 
        ret = -ENOMEM;
-       ctx->d = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_d, GFP_KERNEL);
+       ctx->d = dma_alloc_coherent(dev, ctx->key_sz, &ctx->dma_d, GFP_KERNEL);
        if (!ctx->d)
                goto err;
 
@@ -1077,7 +1077,7 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
        qat_rsa_drop_leading_zeros(&ptr, &len);
        if (!len)
                goto err;
-       ctx->p = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_p, GFP_KERNEL);
+       ctx->p = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_p, GFP_KERNEL);
        if (!ctx->p)
                goto err;
        memcpy(ctx->p + (half_key_sz - len), ptr, len);
@@ -1088,7 +1088,7 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
        qat_rsa_drop_leading_zeros(&ptr, &len);
        if (!len)
                goto free_p;
-       ctx->q = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_q, GFP_KERNEL);
+       ctx->q = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_q, GFP_KERNEL);
        if (!ctx->q)
                goto free_p;
        memcpy(ctx->q + (half_key_sz - len), ptr, len);
@@ -1099,8 +1099,8 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
        qat_rsa_drop_leading_zeros(&ptr, &len);
        if (!len)
                goto free_q;
-       ctx->dp = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_dp,
-                                     GFP_KERNEL);
+       ctx->dp = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_dp,
+                                    GFP_KERNEL);
        if (!ctx->dp)
                goto free_q;
        memcpy(ctx->dp + (half_key_sz - len), ptr, len);
@@ -1111,8 +1111,8 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
        qat_rsa_drop_leading_zeros(&ptr, &len);
        if (!len)
                goto free_dp;
-       ctx->dq = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_dq,
-                                     GFP_KERNEL);
+       ctx->dq = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_dq,
+                                    GFP_KERNEL);
        if (!ctx->dq)
                goto free_dp;
        memcpy(ctx->dq + (half_key_sz - len), ptr, len);
@@ -1123,8 +1123,8 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
        qat_rsa_drop_leading_zeros(&ptr, &len);
        if (!len)
                goto free_dq;
-       ctx->qinv = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_qinv,
-                                       GFP_KERNEL);
+       ctx->qinv = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_qinv,
+                                      GFP_KERNEL);
        if (!ctx->qinv)
                goto free_dq;
        memcpy(ctx->qinv + (half_key_sz - len), ptr, len);
index 45e2070..f8e2c5c 100644 (file)
@@ -1361,23 +1361,18 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
        struct talitos_private *priv = dev_get_drvdata(dev);
        bool is_sec1 = has_ftr_sec1(priv);
        int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
-       void *err;
 
        if (cryptlen + authsize > max_len) {
                dev_err(dev, "length exceeds h/w max limit\n");
                return ERR_PTR(-EINVAL);
        }
 
-       if (ivsize)
-               iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
-
        if (!dst || dst == src) {
                src_len = assoclen + cryptlen + authsize;
                src_nents = sg_nents_for_len(src, src_len);
                if (src_nents < 0) {
                        dev_err(dev, "Invalid number of src SG.\n");
-                       err = ERR_PTR(-EINVAL);
-                       goto error_sg;
+                       return ERR_PTR(-EINVAL);
                }
                src_nents = (src_nents == 1) ? 0 : src_nents;
                dst_nents = dst ? src_nents : 0;
@@ -1387,16 +1382,14 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
                src_nents = sg_nents_for_len(src, src_len);
                if (src_nents < 0) {
                        dev_err(dev, "Invalid number of src SG.\n");
-                       err = ERR_PTR(-EINVAL);
-                       goto error_sg;
+                       return ERR_PTR(-EINVAL);
                }
                src_nents = (src_nents == 1) ? 0 : src_nents;
                dst_len = assoclen + cryptlen + (encrypt ? authsize : 0);
                dst_nents = sg_nents_for_len(dst, dst_len);
                if (dst_nents < 0) {
                        dev_err(dev, "Invalid number of dst SG.\n");
-                       err = ERR_PTR(-EINVAL);
-                       goto error_sg;
+                       return ERR_PTR(-EINVAL);
                }
                dst_nents = (dst_nents == 1) ? 0 : dst_nents;
        }
@@ -1423,11 +1416,14 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
        /* if its a ahash, add space for a second desc next to the first one */
        if (is_sec1 && !dst)
                alloc_len += sizeof(struct talitos_desc);
+       alloc_len += ivsize;
 
        edesc = kmalloc(alloc_len, GFP_DMA | flags);
-       if (!edesc) {
-               err = ERR_PTR(-ENOMEM);
-               goto error_sg;
+       if (!edesc)
+               return ERR_PTR(-ENOMEM);
+       if (ivsize) {
+               iv = memcpy(((u8 *)edesc) + alloc_len - ivsize, iv, ivsize);
+               iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
        }
        memset(&edesc->desc, 0, sizeof(edesc->desc));
 
@@ -1445,10 +1441,6 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
                                                     DMA_BIDIRECTIONAL);
        }
        return edesc;
-error_sg:
-       if (iv_dma)
-               dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
-       return err;
 }
 
 static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
index 4e55768..fe69dcc 100644 (file)
@@ -203,6 +203,7 @@ struct at_xdmac_chan {
        u32                             save_cim;
        u32                             save_cnda;
        u32                             save_cndc;
+       u32                             irq_status;
        unsigned long                   status;
        struct tasklet_struct           tasklet;
        struct dma_slave_config         sconfig;
@@ -1580,8 +1581,8 @@ static void at_xdmac_tasklet(unsigned long data)
        struct at_xdmac_desc    *desc;
        u32                     error_mask;
 
-       dev_dbg(chan2dev(&atchan->chan), "%s: status=0x%08lx\n",
-                __func__, atchan->status);
+       dev_dbg(chan2dev(&atchan->chan), "%s: status=0x%08x\n",
+               __func__, atchan->irq_status);
 
        error_mask = AT_XDMAC_CIS_RBEIS
                     | AT_XDMAC_CIS_WBEIS
@@ -1589,15 +1590,15 @@ static void at_xdmac_tasklet(unsigned long data)
 
        if (at_xdmac_chan_is_cyclic(atchan)) {
                at_xdmac_handle_cyclic(atchan);
-       } else if ((atchan->status & AT_XDMAC_CIS_LIS)
-                  || (atchan->status & error_mask)) {
+       } else if ((atchan->irq_status & AT_XDMAC_CIS_LIS)
+                  || (atchan->irq_status & error_mask)) {
                struct dma_async_tx_descriptor  *txd;
 
-               if (atchan->status & AT_XDMAC_CIS_RBEIS)
+               if (atchan->irq_status & AT_XDMAC_CIS_RBEIS)
                        dev_err(chan2dev(&atchan->chan), "read bus error!!!");
-               if (atchan->status & AT_XDMAC_CIS_WBEIS)
+               if (atchan->irq_status & AT_XDMAC_CIS_WBEIS)
                        dev_err(chan2dev(&atchan->chan), "write bus error!!!");
-               if (atchan->status & AT_XDMAC_CIS_ROIS)
+               if (atchan->irq_status & AT_XDMAC_CIS_ROIS)
                        dev_err(chan2dev(&atchan->chan), "request overflow error!!!");
 
                spin_lock(&atchan->lock);
@@ -1652,7 +1653,7 @@ static irqreturn_t at_xdmac_interrupt(int irq, void *dev_id)
                        atchan = &atxdmac->chan[i];
                        chan_imr = at_xdmac_chan_read(atchan, AT_XDMAC_CIM);
                        chan_status = at_xdmac_chan_read(atchan, AT_XDMAC_CIS);
-                       atchan->status = chan_status & chan_imr;
+                       atchan->irq_status = chan_status & chan_imr;
                        dev_vdbg(atxdmac->dma.dev,
                                 "%s: chan%d: imr=0x%x, status=0x%x\n",
                                 __func__, i, chan_imr, chan_status);
@@ -1666,7 +1667,7 @@ static irqreturn_t at_xdmac_interrupt(int irq, void *dev_id)
                                 at_xdmac_chan_read(atchan, AT_XDMAC_CDA),
                                 at_xdmac_chan_read(atchan, AT_XDMAC_CUBC));
 
-                       if (atchan->status & (AT_XDMAC_CIS_RBEIS | AT_XDMAC_CIS_WBEIS))
+                       if (atchan->irq_status & (AT_XDMAC_CIS_RBEIS | AT_XDMAC_CIS_WBEIS))
                                at_xdmac_write(atxdmac, AT_XDMAC_GD, atchan->mask);
 
                        tasklet_schedule(&atchan->tasklet);
index 1a44c80..ae10f56 100644 (file)
@@ -406,38 +406,32 @@ static void bcm2835_dma_fill_cb_chain_with_sg(
        }
 }
 
-static int bcm2835_dma_abort(void __iomem *chan_base)
+static int bcm2835_dma_abort(struct bcm2835_chan *c)
 {
-       unsigned long cs;
+       void __iomem *chan_base = c->chan_base;
        long int timeout = 10000;
 
-       cs = readl(chan_base + BCM2835_DMA_CS);
-       if (!(cs & BCM2835_DMA_ACTIVE))
+       /*
+        * A zero control block address means the channel is idle.
+        * (The ACTIVE flag in the CS register is not a reliable indicator.)
+        */
+       if (!readl(chan_base + BCM2835_DMA_ADDR))
                return 0;
 
        /* Write 0 to the active bit - Pause the DMA */
        writel(0, chan_base + BCM2835_DMA_CS);
 
        /* Wait for any current AXI transfer to complete */
-       while ((cs & BCM2835_DMA_ISPAUSED) && --timeout) {
+       while ((readl(chan_base + BCM2835_DMA_CS) &
+               BCM2835_DMA_WAITING_FOR_WRITES) && --timeout)
                cpu_relax();
-               cs = readl(chan_base + BCM2835_DMA_CS);
-       }
 
-       /* We'll un-pause when we set of our next DMA */
+       /* Peripheral might be stuck and fail to signal AXI write responses */
        if (!timeout)
-               return -ETIMEDOUT;
-
-       if (!(cs & BCM2835_DMA_ACTIVE))
-               return 0;
-
-       /* Terminate the control block chain */
-       writel(0, chan_base + BCM2835_DMA_NEXTCB);
-
-       /* Abort the whole DMA */
-       writel(BCM2835_DMA_ABORT | BCM2835_DMA_ACTIVE,
-              chan_base + BCM2835_DMA_CS);
+               dev_err(c->vc.chan.device->dev,
+                       "failed to complete outstanding writes\n");
 
+       writel(BCM2835_DMA_RESET, chan_base + BCM2835_DMA_CS);
        return 0;
 }
 
@@ -476,8 +470,15 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
 
        spin_lock_irqsave(&c->vc.lock, flags);
 
-       /* Acknowledge interrupt */
-       writel(BCM2835_DMA_INT, c->chan_base + BCM2835_DMA_CS);
+       /*
+        * Clear the INT flag to receive further interrupts. Keep the channel
+        * active in case the descriptor is cyclic or in case the client has
+        * already terminated the descriptor and issued a new one. (May happen
+        * if this IRQ handler is threaded.) If the channel is finished, it
+        * will remain idle despite the ACTIVE flag being set.
+        */
+       writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE,
+              c->chan_base + BCM2835_DMA_CS);
 
        d = c->desc;
 
@@ -485,11 +486,7 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
                if (d->cyclic) {
                        /* call the cyclic callback */
                        vchan_cyclic_callback(&d->vd);
-
-                       /* Keep the DMA engine running */
-                       writel(BCM2835_DMA_ACTIVE,
-                              c->chan_base + BCM2835_DMA_CS);
-               } else {
+               } else if (!readl(c->chan_base + BCM2835_DMA_ADDR)) {
                        vchan_cookie_complete(&c->desc->vd);
                        bcm2835_dma_start_desc(c);
                }
@@ -779,7 +776,6 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan)
        struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
        struct bcm2835_dmadev *d = to_bcm2835_dma_dev(c->vc.chan.device);
        unsigned long flags;
-       int timeout = 10000;
        LIST_HEAD(head);
 
        spin_lock_irqsave(&c->vc.lock, flags);
@@ -789,27 +785,11 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan)
        list_del_init(&c->node);
        spin_unlock(&d->lock);
 
-       /*
-        * Stop DMA activity: we assume the callback will not be called
-        * after bcm_dma_abort() returns (even if it does, it will see
-        * c->desc is NULL and exit.)
-        */
+       /* stop DMA activity */
        if (c->desc) {
                vchan_terminate_vdesc(&c->desc->vd);
                c->desc = NULL;
-               bcm2835_dma_abort(c->chan_base);
-
-               /* Wait for stopping */
-               while (--timeout) {
-                       if (!(readl(c->chan_base + BCM2835_DMA_CS) &
-                                               BCM2835_DMA_ACTIVE))
-                               break;
-
-                       cpu_relax();
-               }
-
-               if (!timeout)
-                       dev_err(d->ddev.dev, "DMA transfer could not be terminated\n");
+               bcm2835_dma_abort(c);
        }
 
        vchan_get_all_descriptors(&c->vc, &head);
index 2eea4ef..6511928 100644 (file)
@@ -711,11 +711,9 @@ static int dmatest_func(void *data)
                        srcs[i] = um->addr[i] + src_off;
                        ret = dma_mapping_error(dev->dev, um->addr[i]);
                        if (ret) {
-                               dmaengine_unmap_put(um);
                                result("src mapping error", total_tests,
                                       src_off, dst_off, len, ret);
-                               failed_tests++;
-                               continue;
+                               goto error_unmap_continue;
                        }
                        um->to_cnt++;
                }
@@ -730,11 +728,9 @@ static int dmatest_func(void *data)
                                               DMA_BIDIRECTIONAL);
                        ret = dma_mapping_error(dev->dev, dsts[i]);
                        if (ret) {
-                               dmaengine_unmap_put(um);
                                result("dst mapping error", total_tests,
                                       src_off, dst_off, len, ret);
-                               failed_tests++;
-                               continue;
+                               goto error_unmap_continue;
                        }
                        um->bidi_cnt++;
                }
@@ -762,12 +758,10 @@ static int dmatest_func(void *data)
                }
 
                if (!tx) {
-                       dmaengine_unmap_put(um);
                        result("prep error", total_tests, src_off,
                               dst_off, len, ret);
                        msleep(100);
-                       failed_tests++;
-                       continue;
+                       goto error_unmap_continue;
                }
 
                done->done = false;
@@ -776,12 +770,10 @@ static int dmatest_func(void *data)
                cookie = tx->tx_submit(tx);
 
                if (dma_submit_error(cookie)) {
-                       dmaengine_unmap_put(um);
                        result("submit error", total_tests, src_off,
                               dst_off, len, ret);
                        msleep(100);
-                       failed_tests++;
-                       continue;
+                       goto error_unmap_continue;
                }
                dma_async_issue_pending(chan);
 
@@ -790,22 +782,20 @@ static int dmatest_func(void *data)
 
                status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
 
-               dmaengine_unmap_put(um);
-
                if (!done->done) {
                        result("test timed out", total_tests, src_off, dst_off,
                               len, 0);
-                       failed_tests++;
-                       continue;
+                       goto error_unmap_continue;
                } else if (status != DMA_COMPLETE) {
                        result(status == DMA_ERROR ?
                               "completion error status" :
                               "completion busy status", total_tests, src_off,
                               dst_off, len, ret);
-                       failed_tests++;
-                       continue;
+                       goto error_unmap_continue;
                }
 
+               dmaengine_unmap_put(um);
+
                if (params->noverify) {
                        verbose_result("test passed", total_tests, src_off,
                                       dst_off, len, 0);
@@ -846,6 +836,12 @@ static int dmatest_func(void *data)
                        verbose_result("test passed", total_tests, src_off,
                                       dst_off, len, 0);
                }
+
+               continue;
+
+error_unmap_continue:
+               dmaengine_unmap_put(um);
+               failed_tests++;
        }
        ktime = ktime_sub(ktime_get(), ktime);
        ktime = ktime_sub(ktime, comparetime);
index c2fff3f..4a09af3 100644 (file)
@@ -618,7 +618,7 @@ static void imxdma_tasklet(unsigned long data)
 {
        struct imxdma_channel *imxdmac = (void *)data;
        struct imxdma_engine *imxdma = imxdmac->imxdma;
-       struct imxdma_desc *desc;
+       struct imxdma_desc *desc, *next_desc;
        unsigned long flags;
 
        spin_lock_irqsave(&imxdma->lock, flags);
@@ -648,10 +648,10 @@ static void imxdma_tasklet(unsigned long data)
        list_move_tail(imxdmac->ld_active.next, &imxdmac->ld_free);
 
        if (!list_empty(&imxdmac->ld_queue)) {
-               desc = list_first_entry(&imxdmac->ld_queue, struct imxdma_desc,
-                                       node);
+               next_desc = list_first_entry(&imxdmac->ld_queue,
+                                            struct imxdma_desc, node);
                list_move_tail(imxdmac->ld_queue.next, &imxdmac->ld_active);
-               if (imxdma_xfer_desc(desc) < 0)
+               if (imxdma_xfer_desc(next_desc) < 0)
                        dev_warn(imxdma->dev, "%s: channel: %d couldn't xfer desc\n",
                                 __func__, imxdmac->channel);
        }
index a2b0a0e..86708fb 100644 (file)
@@ -1182,8 +1182,8 @@ static int sdma_request_channel0(struct sdma_engine *sdma)
 {
        int ret = -EBUSY;
 
-       sdma->bd0 = dma_zalloc_coherent(NULL, PAGE_SIZE, &sdma->bd0_phys,
-                                       GFP_NOWAIT);
+       sdma->bd0 = dma_alloc_coherent(NULL, PAGE_SIZE, &sdma->bd0_phys,
+                                      GFP_NOWAIT);
        if (!sdma->bd0) {
                ret = -ENOMEM;
                goto out;
@@ -1205,8 +1205,8 @@ static int sdma_alloc_bd(struct sdma_desc *desc)
        u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor);
        int ret = 0;
 
-       desc->bd = dma_zalloc_coherent(NULL, bd_size, &desc->bd_phys,
-                                       GFP_NOWAIT);
+       desc->bd = dma_alloc_coherent(NULL, bd_size, &desc->bd_phys,
+                                     GFP_NOWAIT);
        if (!desc->bd) {
                ret = -ENOMEM;
                goto out;
index b7ec56a..1a2028e 100644 (file)
@@ -325,8 +325,8 @@ static int mtk_hsdma_alloc_pchan(struct mtk_hsdma_device *hsdma,
         * and [MTK_DMA_SIZE ... 2 * MTK_DMA_SIZE - 1] is for RX ring.
         */
        pc->sz_ring = 2 * MTK_DMA_SIZE * sizeof(*ring->txd);
-       ring->txd = dma_zalloc_coherent(hsdma2dev(hsdma), pc->sz_ring,
-                                       &ring->tphys, GFP_NOWAIT);
+       ring->txd = dma_alloc_coherent(hsdma2dev(hsdma), pc->sz_ring,
+                                      &ring->tphys, GFP_NOWAIT);
        if (!ring->txd)
                return -ENOMEM;
 
index 35193b3..22cc7f6 100644 (file)
@@ -416,9 +416,9 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
        struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
        int ret;
 
-       mxs_chan->ccw = dma_zalloc_coherent(mxs_dma->dma_device.dev,
-                                           CCW_BLOCK_SIZE,
-                                           &mxs_chan->ccw_phys, GFP_KERNEL);
+       mxs_chan->ccw = dma_alloc_coherent(mxs_dma->dma_device.dev,
+                                          CCW_BLOCK_SIZE,
+                                          &mxs_chan->ccw_phys, GFP_KERNEL);
        if (!mxs_chan->ccw) {
                ret = -ENOMEM;
                goto err_alloc;
index 1d59888..eafd6c4 100644 (file)
@@ -1208,8 +1208,8 @@ static int xgene_dma_create_ring_one(struct xgene_dma_chan *chan,
        ring->size = ret;
 
        /* Allocate memory for DMA ring descriptor */
-       ring->desc_vaddr = dma_zalloc_coherent(chan->dev, ring->size,
-                                              &ring->desc_paddr, GFP_KERNEL);
+       ring->desc_vaddr = dma_alloc_coherent(chan->dev, ring->size,
+                                             &ring->desc_paddr, GFP_KERNEL);
        if (!ring->desc_vaddr) {
                chan_err(chan, "Failed to allocate ring desc\n");
                return -ENOMEM;
index 0288096..cb20b41 100644 (file)
@@ -879,10 +879,9 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
         */
        if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
                /* Allocate the buffer descriptors. */
-               chan->seg_v = dma_zalloc_coherent(chan->dev,
-                                                 sizeof(*chan->seg_v) *
-                                                 XILINX_DMA_NUM_DESCS,
-                                                 &chan->seg_p, GFP_KERNEL);
+               chan->seg_v = dma_alloc_coherent(chan->dev,
+                                                sizeof(*chan->seg_v) * XILINX_DMA_NUM_DESCS,
+                                                &chan->seg_p, GFP_KERNEL);
                if (!chan->seg_v) {
                        dev_err(chan->dev,
                                "unable to allocate channel %d descriptors\n",
@@ -895,9 +894,10 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
                 * so allocating a desc segment during channel allocation for
                 * programming tail descriptor.
                 */
-               chan->cyclic_seg_v = dma_zalloc_coherent(chan->dev,
-                                       sizeof(*chan->cyclic_seg_v),
-                                       &chan->cyclic_seg_p, GFP_KERNEL);
+               chan->cyclic_seg_v = dma_alloc_coherent(chan->dev,
+                                                       sizeof(*chan->cyclic_seg_v),
+                                                       &chan->cyclic_seg_p,
+                                                       GFP_KERNEL);
                if (!chan->cyclic_seg_v) {
                        dev_err(chan->dev,
                                "unable to allocate desc segment for cyclic DMA\n");
index 8db5175..4478787 100644 (file)
@@ -490,9 +490,9 @@ static int zynqmp_dma_alloc_chan_resources(struct dma_chan *dchan)
                list_add_tail(&desc->node, &chan->free_list);
        }
 
-       chan->desc_pool_v = dma_zalloc_coherent(chan->dev,
-                               (2 * chan->desc_size * ZYNQMP_DMA_NUM_DESCS),
-                               &chan->desc_pool_p, GFP_KERNEL);
+       chan->desc_pool_v = dma_alloc_coherent(chan->dev,
+                                              (2 * chan->desc_size * ZYNQMP_DMA_NUM_DESCS),
+                                              &chan->desc_pool_p, GFP_KERNEL);
        if (!chan->desc_pool_v)
                return -ENOMEM;
 
index 4213cb0..f8664ba 100644 (file)
@@ -295,8 +295,8 @@ struct altr_sdram_mc_data {
 #define S10_SYSMGR_ECC_INTSTAT_DERR_OFST  0xA0
 
 /* Sticky registers for Uncorrected Errors */
-#define S10_SYSMGR_UE_VAL_OFST            0x120
-#define S10_SYSMGR_UE_ADDR_OFST           0x124
+#define S10_SYSMGR_UE_VAL_OFST            0x220
+#define S10_SYSMGR_UE_ADDR_OFST           0x224
 
 #define S10_DDR0_IRQ_MASK                 BIT(16)
 
index 09b845e..a785ffd 100644 (file)
@@ -1144,10 +1144,6 @@ static int sbp2_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
        if (device->is_local)
                return -ENODEV;
 
-       if (dma_get_max_seg_size(device->card->device) > SBP2_MAX_SEG_SIZE)
-               WARN_ON(dma_set_max_seg_size(device->card->device,
-                                            SBP2_MAX_SEG_SIZE));
-
        shost = scsi_host_alloc(&scsi_driver_template, sizeof(*tgt));
        if (shost == NULL)
                return -ENOMEM;
@@ -1610,6 +1606,7 @@ static struct scsi_host_template scsi_driver_template = {
        .eh_abort_handler       = sbp2_scsi_abort,
        .this_id                = -1,
        .sg_tablesize           = SG_ALL,
+       .max_segment_size       = SBP2_MAX_SEG_SIZE,
        .can_queue              = 1,
        .sdev_attrs             = sbp2_scsi_sysfs_attrs,
 };
index 472c88a..92f843e 100644 (file)
@@ -119,6 +119,11 @@ void scmi_driver_unregister(struct scmi_driver *driver)
 }
 EXPORT_SYMBOL_GPL(scmi_driver_unregister);
 
+static void scmi_device_release(struct device *dev)
+{
+       kfree(to_scmi_dev(dev));
+}
+
 struct scmi_device *
 scmi_device_create(struct device_node *np, struct device *parent, int protocol)
 {
@@ -138,6 +143,7 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol)
        scmi_dev->dev.parent = parent;
        scmi_dev->dev.of_node = np;
        scmi_dev->dev.bus = &scmi_bus_type;
+       scmi_dev->dev.release = scmi_device_release;
        dev_set_name(&scmi_dev->dev, "scmi_dev.%d", id);
 
        retval = device_register(&scmi_dev->dev);
@@ -156,9 +162,8 @@ free_mem:
 void scmi_device_destroy(struct scmi_device *scmi_dev)
 {
        scmi_handle_put(scmi_dev->handle);
-       device_unregister(&scmi_dev->dev);
        ida_simple_remove(&scmi_bus_id, scmi_dev->id);
-       kfree(scmi_dev);
+       device_unregister(&scmi_dev->dev);
 }
 
 void scmi_set_handle(struct scmi_device *scmi_dev)
index 23ea1ed..352bd24 100644 (file)
@@ -37,8 +37,9 @@ extern u64 efi_system_table;
 static struct ptdump_info efi_ptdump_info = {
        .mm             = &efi_mm,
        .markers        = (struct addr_marker[]){
-               { 0,            "UEFI runtime start" },
-               { DEFAULT_MAP_WINDOW_64, "UEFI runtime end" }
+               { 0,                            "UEFI runtime start" },
+               { DEFAULT_MAP_WINDOW_64,        "UEFI runtime end" },
+               { -1,                           NULL }
        },
        .base_addr      = 0,
 };
index 4c46ff6..55b77c5 100644 (file)
@@ -592,11 +592,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
 
                early_memunmap(tbl, sizeof(*tbl));
        }
-       return 0;
-}
 
-int __init efi_apply_persistent_mem_reservations(void)
-{
        if (efi.mem_reserve != EFI_INVALID_TABLE_ADDR) {
                unsigned long prsv = efi.mem_reserve;
 
index eee42d5..c037c6c 100644 (file)
@@ -75,9 +75,6 @@ void install_memreserve_table(efi_system_table_t *sys_table_arg)
        efi_guid_t memreserve_table_guid = LINUX_EFI_MEMRESERVE_TABLE_GUID;
        efi_status_t status;
 
-       if (IS_ENABLED(CONFIG_ARM))
-               return;
-
        status = efi_call_early(allocate_pool, EFI_LOADER_DATA, sizeof(*rsv),
                                (void **)&rsv);
        if (status != EFI_SUCCESS) {
index 8903b9c..e2abfdb 100644 (file)
@@ -147,6 +147,13 @@ void efi_call_virt_check_flags(unsigned long flags, const char *call)
 static DEFINE_SEMAPHORE(efi_runtime_lock);
 
 /*
+ * Expose the EFI runtime lock to the UV platform
+ */
+#ifdef CONFIG_X86_UV
+extern struct semaphore __efi_uv_runtime_lock __alias(efi_runtime_lock);
+#endif
+
+/*
  * Calls the appropriate efi_runtime_service() with the appropriate
  * arguments.
  *
index a1a09e0..13851b3 100644 (file)
@@ -508,14 +508,11 @@ static int __init s10_init(void)
                return -ENODEV;
 
        np = of_find_matching_node(fw_np, s10_of_match);
-       if (!np) {
-               of_node_put(fw_np);
+       if (!np)
                return -ENODEV;
-       }
 
        of_node_put(np);
        ret = of_platform_populate(fw_np, s10_of_match, NULL, NULL);
-       of_node_put(fw_np);
        if (ret)
                return ret;
 
index 6b11f13..7f9e030 100644 (file)
@@ -66,8 +66,10 @@ static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc,
 static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc,
                                            unsigned int nr, int value)
 {
-       if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT))
+       if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT)) {
+               altr_a10sr_gpio_set(gc, nr, value);
                return 0;
+       }
        return -EINVAL;
 }
 
index e0d6a0a..e41223c 100644 (file)
@@ -180,7 +180,18 @@ static void sprd_eic_free(struct gpio_chip *chip, unsigned int offset)
 
 static int sprd_eic_get(struct gpio_chip *chip, unsigned int offset)
 {
-       return sprd_eic_read(chip, offset, SPRD_EIC_DBNC_DATA);
+       struct sprd_eic *sprd_eic = gpiochip_get_data(chip);
+
+       switch (sprd_eic->type) {
+       case SPRD_EIC_DEBOUNCE:
+               return sprd_eic_read(chip, offset, SPRD_EIC_DBNC_DATA);
+       case SPRD_EIC_ASYNC:
+               return sprd_eic_read(chip, offset, SPRD_EIC_ASYNC_DATA);
+       case SPRD_EIC_SYNC:
+               return sprd_eic_read(chip, offset, SPRD_EIC_SYNC_DATA);
+       default:
+               return -ENOTSUPP;
+       }
 }
 
 static int sprd_eic_direction_input(struct gpio_chip *chip, unsigned int offset)
@@ -368,6 +379,7 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
                        irq_set_handler_locked(data, handle_edge_irq);
                        break;
                case IRQ_TYPE_EDGE_BOTH:
+                       sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0);
                        sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 1);
                        irq_set_handler_locked(data, handle_edge_irq);
                        break;
index 83617fd..0dc9641 100644 (file)
@@ -289,7 +289,7 @@ static bool pca953x_volatile_register(struct device *dev, unsigned int reg)
        return pca953x_check_register(chip, reg, bank);
 }
 
-const struct regmap_config pca953x_i2c_regmap = {
+static const struct regmap_config pca953x_i2c_regmap = {
        .reg_bits = 8,
        .val_bits = 8,
 
index adf72dd..68a35b6 100644 (file)
@@ -84,6 +84,7 @@ MODULE_DEVICE_TABLE(of, pcf857x_of_table);
  */
 struct pcf857x {
        struct gpio_chip        chip;
+       struct irq_chip         irqchip;
        struct i2c_client       *client;
        struct mutex            lock;           /* protect 'out' */
        unsigned                out;            /* software latch */
@@ -252,18 +253,6 @@ static void pcf857x_irq_bus_sync_unlock(struct irq_data *data)
        mutex_unlock(&gpio->lock);
 }
 
-static struct irq_chip pcf857x_irq_chip = {
-       .name           = "pcf857x",
-       .irq_enable     = pcf857x_irq_enable,
-       .irq_disable    = pcf857x_irq_disable,
-       .irq_ack        = noop,
-       .irq_mask       = noop,
-       .irq_unmask     = noop,
-       .irq_set_wake   = pcf857x_irq_set_wake,
-       .irq_bus_lock           = pcf857x_irq_bus_lock,
-       .irq_bus_sync_unlock    = pcf857x_irq_bus_sync_unlock,
-};
-
 /*-------------------------------------------------------------------------*/
 
 static int pcf857x_probe(struct i2c_client *client,
@@ -376,8 +365,17 @@ static int pcf857x_probe(struct i2c_client *client,
 
        /* Enable irqchip if we have an interrupt */
        if (client->irq) {
+               gpio->irqchip.name = "pcf857x",
+               gpio->irqchip.irq_enable = pcf857x_irq_enable,
+               gpio->irqchip.irq_disable = pcf857x_irq_disable,
+               gpio->irqchip.irq_ack = noop,
+               gpio->irqchip.irq_mask = noop,
+               gpio->irqchip.irq_unmask = noop,
+               gpio->irqchip.irq_set_wake = pcf857x_irq_set_wake,
+               gpio->irqchip.irq_bus_lock = pcf857x_irq_bus_lock,
+               gpio->irqchip.irq_bus_sync_unlock = pcf857x_irq_bus_sync_unlock,
                status = gpiochip_irqchip_add_nested(&gpio->chip,
-                                                    &pcf857x_irq_chip,
+                                                    &gpio->irqchip,
                                                     0, handle_level_irq,
                                                     IRQ_TYPE_NONE);
                if (status) {
@@ -392,7 +390,7 @@ static int pcf857x_probe(struct i2c_client *client,
                if (status)
                        goto fail;
 
-               gpiochip_set_nested_irqchip(&gpio->chip, &pcf857x_irq_chip,
+               gpiochip_set_nested_irqchip(&gpio->chip, &gpio->irqchip,
                                            client->irq);
                gpio->irq_parent = client->irq;
        }
index 1b79ebc..541fa6a 100644 (file)
@@ -253,6 +253,7 @@ static int vf610_gpio_probe(struct platform_device *pdev)
        struct vf610_gpio_port *port;
        struct resource *iores;
        struct gpio_chip *gc;
+       int i;
        int ret;
 
        port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
@@ -319,6 +320,10 @@ static int vf610_gpio_probe(struct platform_device *pdev)
        if (ret < 0)
                return ret;
 
+       /* Mask all GPIO interrupts */
+       for (i = 0; i < gc->ngpio; i++)
+               vf610_gpio_writel(0, port->base + PORT_PCR(i));
+
        /* Clear the interrupt status register for all GPIO's */
        vf610_gpio_writel(~0, port->base + PORT_ISFR);
 
index 48534bd..259cf6a 100644 (file)
@@ -357,8 +357,6 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
        mutex_unlock(&acpi_gpio_deferred_req_irqs_lock);
 
        list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) {
-               struct gpio_desc *desc;
-
                if (event->irq_requested) {
                        if (event->irq_is_wake)
                                disable_irq_wake(event->irq);
@@ -366,11 +364,8 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
                        free_irq(event->irq, event);
                }
 
-               desc = event->desc;
-               if (WARN_ON(IS_ERR(desc)))
-                       continue;
                gpiochip_unlock_as_irq(chip, event->pin);
-               gpiochip_free_own_desc(desc);
+               gpiochip_free_own_desc(event->desc);
                list_del(&event->node);
                kfree(event);
        }
index 1651d7f..d1adfdf 100644 (file)
@@ -828,7 +828,14 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p)
        /* Do not leak kernel stack to userspace */
        memset(&ge, 0, sizeof(ge));
 
-       ge.timestamp = le->timestamp;
+       /*
+        * We may be running from a nested threaded interrupt in which case
+        * we didn't get the timestamp from lineevent_irq_handler().
+        */
+       if (!le->timestamp)
+               ge.timestamp = ktime_get_real_ns();
+       else
+               ge.timestamp = le->timestamp;
 
        if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE
            && le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
index a028661..92b11de 100644 (file)
@@ -576,6 +576,7 @@ static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = {
        { 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0x1002, 0x6900, 0x1028, 0x0813, 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 8a078f4..7ff3a28 100644 (file)
@@ -1701,8 +1701,10 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
                amdgpu_xgmi_add_device(adev);
        amdgpu_amdkfd_device_init(adev);
 
-       if (amdgpu_sriov_vf(adev))
+       if (amdgpu_sriov_vf(adev)) {
+               amdgpu_virt_init_data_exchange(adev);
                amdgpu_virt_release_full_gpu(adev, true);
+       }
 
        return 0;
 }
@@ -2632,9 +2634,6 @@ fence_driver_init:
                goto failed;
        }
 
-       if (amdgpu_sriov_vf(adev))
-               amdgpu_virt_init_data_exchange(adev);
-
        amdgpu_fbdev_init(adev);
 
        r = amdgpu_pm_sysfs_init(adev);
@@ -2798,7 +2797,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
                        struct drm_framebuffer *fb = crtc->primary->fb;
                        struct amdgpu_bo *robj;
 
-                       if (amdgpu_crtc->cursor_bo) {
+                       if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) {
                                struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
                                r = amdgpu_bo_reserve(aobj, true);
                                if (r == 0) {
@@ -2906,7 +2905,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
                list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                        struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 
-                       if (amdgpu_crtc->cursor_bo) {
+                       if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) {
                                struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
                                r = amdgpu_bo_reserve(aobj, true);
                                if (r == 0) {
@@ -3226,6 +3225,7 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
        r = amdgpu_ib_ring_tests(adev);
 
 error:
+       amdgpu_virt_init_data_exchange(adev);
        amdgpu_virt_release_full_gpu(adev, true);
        if (!r && adev->virt.gim_feature & AMDGIM_FEATURE_GIM_FLR_VRAMLOST) {
                atomic_inc(&adev->vram_lost_counter);
index 15ce7e6..b083b21 100644 (file)
@@ -188,10 +188,12 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,
                goto cleanup;
        }
 
-       r = amdgpu_bo_pin(new_abo, amdgpu_display_supported_domains(adev));
-       if (unlikely(r != 0)) {
-               DRM_ERROR("failed to pin new abo buffer before flip\n");
-               goto unreserve;
+       if (!adev->enable_virtual_display) {
+               r = amdgpu_bo_pin(new_abo, amdgpu_display_supported_domains(adev));
+               if (unlikely(r != 0)) {
+                       DRM_ERROR("failed to pin new abo buffer before flip\n");
+                       goto unreserve;
+               }
        }
 
        r = amdgpu_ttm_alloc_gart(&new_abo->tbo);
@@ -211,7 +213,8 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,
        amdgpu_bo_get_tiling_flags(new_abo, &tiling_flags);
        amdgpu_bo_unreserve(new_abo);
 
-       work->base = amdgpu_bo_gpu_offset(new_abo);
+       if (!adev->enable_virtual_display)
+               work->base = amdgpu_bo_gpu_offset(new_abo);
        work->target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) +
                amdgpu_get_vblank_counter_kms(dev, work->crtc_id);
 
@@ -242,9 +245,10 @@ pflip_cleanup:
                goto cleanup;
        }
 unpin:
-       if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) {
-               DRM_ERROR("failed to unpin new abo in error path\n");
-       }
+       if (!adev->enable_virtual_display)
+               if (unlikely(amdgpu_bo_unpin(new_abo) != 0))
+                       DRM_ERROR("failed to unpin new abo in error path\n");
+
 unreserve:
        amdgpu_bo_unreserve(new_abo);
 
index 1f61ed9..0ed41a9 100644 (file)
@@ -1686,7 +1686,8 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
                effective_mode &= ~S_IWUSR;
 
        if ((adev->flags & AMD_IS_APU) &&
-           (attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr ||
+           (attr == &sensor_dev_attr_power1_average.dev_attr.attr ||
+            attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr ||
             attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr||
             attr == &sensor_dev_attr_power1_cap.dev_attr.attr))
                return 0;
@@ -2008,6 +2009,7 @@ void amdgpu_pm_print_power_states(struct amdgpu_device *adev)
 
 int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
 {
+       struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
        int ret;
 
        if (adev->pm.sysfs_initialized)
@@ -2091,12 +2093,14 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
                                "pp_power_profile_mode\n");
                return ret;
        }
-       ret = device_create_file(adev->dev,
-                       &dev_attr_pp_od_clk_voltage);
-       if (ret) {
-               DRM_ERROR("failed to create device file "
-                               "pp_od_clk_voltage\n");
-               return ret;
+       if (hwmgr->od_enabled) {
+               ret = device_create_file(adev->dev,
+                               &dev_attr_pp_od_clk_voltage);
+               if (ret) {
+                       DRM_ERROR("failed to create device file "
+                                       "pp_od_clk_voltage\n");
+                       return ret;
+               }
        }
        ret = device_create_file(adev->dev,
                        &dev_attr_gpu_busy_percent);
@@ -2118,6 +2122,8 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
 
 void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
 {
+       struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
+
        if (adev->pm.dpm_enabled == 0)
                return;
 
@@ -2138,8 +2144,9 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
        device_remove_file(adev->dev, &dev_attr_pp_mclk_od);
        device_remove_file(adev->dev,
                        &dev_attr_pp_power_profile_mode);
-       device_remove_file(adev->dev,
-                       &dev_attr_pp_od_clk_voltage);
+       if (hwmgr->od_enabled)
+               device_remove_file(adev->dev,
+                               &dev_attr_pp_od_clk_voltage);
        device_remove_file(adev->dev, &dev_attr_gpu_busy_percent);
 }
 
index 71913a1..a38e0fb 100644 (file)
@@ -38,6 +38,7 @@
 #include "amdgpu_gem.h"
 #include <drm/amdgpu_drm.h>
 #include <linux/dma-buf.h>
+#include <linux/dma-fence-array.h>
 
 /**
  * amdgpu_gem_prime_get_sg_table - &drm_driver.gem_prime_get_sg_table
@@ -187,6 +188,48 @@ error:
        return ERR_PTR(ret);
 }
 
+static int
+__reservation_object_make_exclusive(struct reservation_object *obj)
+{
+       struct dma_fence **fences;
+       unsigned int count;
+       int r;
+
+       if (!reservation_object_get_list(obj)) /* no shared fences to convert */
+               return 0;
+
+       r = reservation_object_get_fences_rcu(obj, NULL, &count, &fences);
+       if (r)
+               return r;
+
+       if (count == 0) {
+               /* Now that was unexpected. */
+       } else if (count == 1) {
+               reservation_object_add_excl_fence(obj, fences[0]);
+               dma_fence_put(fences[0]);
+               kfree(fences);
+       } else {
+               struct dma_fence_array *array;
+
+               array = dma_fence_array_create(count, fences,
+                                              dma_fence_context_alloc(1), 0,
+                                              false);
+               if (!array)
+                       goto err_fences_put;
+
+               reservation_object_add_excl_fence(obj, &array->base);
+               dma_fence_put(&array->base);
+       }
+
+       return 0;
+
+err_fences_put:
+       while (count--)
+               dma_fence_put(fences[count]);
+       kfree(fences);
+       return -ENOMEM;
+}
+
 /**
  * amdgpu_gem_map_attach - &dma_buf_ops.attach implementation
  * @dma_buf: Shared DMA buffer
@@ -218,16 +261,16 @@ static int amdgpu_gem_map_attach(struct dma_buf *dma_buf,
 
        if (attach->dev->driver != adev->dev->driver) {
                /*
-                * Wait for all shared fences to complete before we switch to future
-                * use of exclusive fence on this prime shared bo.
+                * We only create shared fences for internal use, but importers
+                * of the dmabuf rely on exclusive fences for implicitly
+                * tracking write hazards. As any of the current fences may
+                * correspond to a write, we need to convert all existing
+                * fences on the reservation object into a single exclusive
+                * fence.
                 */
-               r = reservation_object_wait_timeout_rcu(bo->tbo.resv,
-                                                       true, false,
-                                                       MAX_SCHEDULE_TIMEOUT);
-               if (unlikely(r < 0)) {
-                       DRM_DEBUG_PRIME("Fence wait failed: %li\n", r);
+               r = __reservation_object_make_exclusive(bo->tbo.resv);
+               if (r)
                        goto error_unreserve;
-               }
        }
 
        /* pin buffer into GTT */
index 8fab0d6..3a9b48b 100644 (file)
@@ -90,8 +90,10 @@ static int psp_sw_fini(void *handle)
        adev->psp.sos_fw = NULL;
        release_firmware(adev->psp.asd_fw);
        adev->psp.asd_fw = NULL;
-       release_firmware(adev->psp.ta_fw);
-       adev->psp.ta_fw = NULL;
+       if (adev->psp.ta_fw) {
+               release_firmware(adev->psp.ta_fw);
+               adev->psp.ta_fw = NULL;
+       }
        return 0;
 }
 
@@ -435,6 +437,9 @@ static int psp_xgmi_initialize(struct psp_context *psp)
        struct ta_xgmi_shared_memory *xgmi_cmd;
        int ret;
 
+       if (!psp->adev->psp.ta_fw)
+               return -ENOENT;
+
        if (!psp->xgmi_context.initialized) {
                ret = psp_xgmi_init_shared_buf(psp);
                if (ret)
index e73d152..7c108e6 100644 (file)
@@ -847,9 +847,6 @@ static void amdgpu_vm_bo_param(struct amdgpu_device *adev, struct amdgpu_vm *vm,
        bp->size = amdgpu_vm_bo_size(adev, level);
        bp->byte_align = AMDGPU_GPU_PAGE_SIZE;
        bp->domain = AMDGPU_GEM_DOMAIN_VRAM;
-       if (bp->size <= PAGE_SIZE && adev->asic_type >= CHIP_VEGA10 &&
-           adev->flags & AMD_IS_APU)
-               bp->domain |= AMDGPU_GEM_DOMAIN_GTT;
        bp->domain = amdgpu_bo_get_preferred_pin_domain(adev, bp->domain);
        bp->flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
                AMDGPU_GEM_CREATE_CPU_GTT_USWC;
@@ -3366,14 +3363,15 @@ void amdgpu_vm_get_task_info(struct amdgpu_device *adev, unsigned int pasid,
                         struct amdgpu_task_info *task_info)
 {
        struct amdgpu_vm *vm;
+       unsigned long flags;
 
-       spin_lock(&adev->vm_manager.pasid_lock);
+       spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
 
        vm = idr_find(&adev->vm_manager.pasid_idr, pasid);
        if (vm)
                *task_info = vm->task_info;
 
-       spin_unlock(&adev->vm_manager.pasid_lock);
+       spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
 }
 
 /**
index fdace00..e4cc1d4 100644 (file)
@@ -167,19 +167,6 @@ static void dce_virtual_crtc_disable(struct drm_crtc *crtc)
        struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 
        dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
-       if (crtc->primary->fb) {
-               int r;
-               struct amdgpu_bo *abo;
-
-               abo = gem_to_amdgpu_bo(crtc->primary->fb->obj[0]);
-               r = amdgpu_bo_reserve(abo, true);
-               if (unlikely(r))
-                       DRM_ERROR("failed to reserve abo before unpin\n");
-               else {
-                       amdgpu_bo_unpin(abo);
-                       amdgpu_bo_unreserve(abo);
-               }
-       }
 
        amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
        amdgpu_crtc->encoder = NULL;
@@ -692,7 +679,9 @@ static int dce_virtual_pageflip(struct amdgpu_device *adev,
        spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
 
        drm_crtc_vblank_put(&amdgpu_crtc->base);
-       schedule_work(&works->unpin_work);
+       amdgpu_bo_unref(&works->old_abo);
+       kfree(works->shared);
+       kfree(works);
 
        return 0;
 }
index 381f593..57cb3a5 100644 (file)
@@ -4233,7 +4233,6 @@ static int gfx_v8_0_cp_gfx_resume(struct amdgpu_device *adev)
        u32 tmp;
        u32 rb_bufsz;
        u64 rb_addr, rptr_addr, wptr_gpu_addr;
-       int r;
 
        /* Set the write pointer delay */
        WREG32(mmCP_RB_WPTR_DELAY, 0);
@@ -4278,9 +4277,8 @@ static int gfx_v8_0_cp_gfx_resume(struct amdgpu_device *adev)
        amdgpu_ring_clear_ring(ring);
        gfx_v8_0_cp_gfx_start(adev);
        ring->sched.ready = true;
-       r = amdgpu_ring_test_helper(ring);
 
-       return r;
+       return 0;
 }
 
 static void gfx_v8_0_cp_compute_enable(struct amdgpu_device *adev, bool enable)
@@ -4369,10 +4367,9 @@ static int gfx_v8_0_kiq_kcq_enable(struct amdgpu_device *adev)
                amdgpu_ring_write(kiq_ring, upper_32_bits(wptr_addr));
        }
 
-       r = amdgpu_ring_test_helper(kiq_ring);
-       if (r)
-               DRM_ERROR("KCQ enable failed\n");
-       return r;
+       amdgpu_ring_commit(kiq_ring);
+
+       return 0;
 }
 
 static int gfx_v8_0_deactivate_hqd(struct amdgpu_device *adev, u32 req)
@@ -4709,16 +4706,32 @@ static int gfx_v8_0_kcq_resume(struct amdgpu_device *adev)
        if (r)
                goto done;
 
-       /* Test KCQs - reversing the order of rings seems to fix ring test failure
-        * after GPU reset
-        */
-       for (i = adev->gfx.num_compute_rings - 1; i >= 0; i--) {
+done:
+       return r;
+}
+
+static int gfx_v8_0_cp_test_all_rings(struct amdgpu_device *adev)
+{
+       int r, i;
+       struct amdgpu_ring *ring;
+
+       /* collect all the ring_tests here, gfx, kiq, compute */
+       ring = &adev->gfx.gfx_ring[0];
+       r = amdgpu_ring_test_helper(ring);
+       if (r)
+               return r;
+
+       ring = &adev->gfx.kiq.ring;
+       r = amdgpu_ring_test_helper(ring);
+       if (r)
+               return r;
+
+       for (i = 0; i < adev->gfx.num_compute_rings; i++) {
                ring = &adev->gfx.compute_ring[i];
-               r = amdgpu_ring_test_helper(ring);
+               amdgpu_ring_test_helper(ring);
        }
 
-done:
-       return r;
+       return 0;
 }
 
 static int gfx_v8_0_cp_resume(struct amdgpu_device *adev)
@@ -4739,6 +4752,11 @@ static int gfx_v8_0_cp_resume(struct amdgpu_device *adev)
        r = gfx_v8_0_kcq_resume(adev);
        if (r)
                return r;
+
+       r = gfx_v8_0_cp_test_all_rings(adev);
+       if (r)
+               return r;
+
        gfx_v8_0_enable_gui_idle_interrupt(adev, true);
 
        return 0;
@@ -5086,6 +5104,8 @@ static int gfx_v8_0_post_soft_reset(void *handle)
            REG_GET_FIELD(grbm_soft_reset, GRBM_SOFT_RESET, SOFT_RESET_GFX))
                gfx_v8_0_cp_gfx_resume(adev);
 
+       gfx_v8_0_cp_test_all_rings(adev);
+
        adev->gfx.rlc.funcs->start(adev);
 
        return 0;
index 7556716..fbca049 100644 (file)
@@ -113,7 +113,10 @@ static const struct soc15_reg_golden golden_settings_gc_9_0[] =
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_HI, 0xffffffff, 0x4a2c0e68),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_LO, 0xffffffff, 0xb5d3f197),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_CACHE_INVALIDATION, 0x3fff3af3, 0x19200000),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x00000fff, 0x000003ff)
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x00000fff, 0x000003ff),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x00000000, 0x00000800),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000000, 0x00000800),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00000000, 0x00008000)
 };
 
 static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] =
@@ -135,10 +138,7 @@ static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] =
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_UTCL1_CNTL2, 0x00030000, 0x00020000),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL_1, 0x0000000f, 0x01000107),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmTD_CNTL, 0x00001800, 0x00000800),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x08000000, 0x08000080),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x00000000, 0x00000800),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000000, 0x00000800),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00000000, 0x00008000)
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x08000000, 0x08000080)
 };
 
 static const struct soc15_reg_golden golden_settings_gc_9_0_vg20[] =
@@ -3587,6 +3587,8 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
 {
        uint32_t data, def;
 
+       amdgpu_gfx_rlc_enter_safe_mode(adev);
+
        /* It is disabled by HW by default */
        if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) {
                /* 1 - RLC_CGTT_MGCG_OVERRIDE */
@@ -3651,6 +3653,8 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
                        WREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL, data);
                }
        }
+
+       amdgpu_gfx_rlc_exit_safe_mode(adev);
 }
 
 static void gfx_v9_0_update_3d_clock_gating(struct amdgpu_device *adev,
index 8cbb465..b11a1c1 100644 (file)
@@ -174,7 +174,7 @@ static int xgpu_ai_send_access_requests(struct amdgpu_device *adev,
                        return r;
                }
                /* Retrieve checksum from mailbox2 */
-               if (req == IDH_REQ_GPU_INIT_ACCESS) {
+               if (req == IDH_REQ_GPU_INIT_ACCESS || req == IDH_REQ_GPU_RESET_ACCESS) {
                        adev->virt.fw_reserve.checksum_key =
                                RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0,
                                        mmBIF_BX_PF0_MAILBOX_MSGBUF_RCV_DW2));
index 4cd31a2..186db18 100644 (file)
@@ -93,7 +93,20 @@ static void nbio_v7_4_enable_doorbell_aperture(struct amdgpu_device *adev,
 static void nbio_v7_4_enable_doorbell_selfring_aperture(struct amdgpu_device *adev,
                                                        bool enable)
 {
+       u32 tmp = 0;
 
+       if (enable) {
+               tmp = REG_SET_FIELD(tmp, DOORBELL_SELFRING_GPA_APER_CNTL, DOORBELL_SELFRING_GPA_APER_EN, 1) |
+                     REG_SET_FIELD(tmp, DOORBELL_SELFRING_GPA_APER_CNTL, DOORBELL_SELFRING_GPA_APER_MODE, 1) |
+                     REG_SET_FIELD(tmp, DOORBELL_SELFRING_GPA_APER_CNTL, DOORBELL_SELFRING_GPA_APER_SIZE, 0);
+
+               WREG32_SOC15(NBIO, 0, mmDOORBELL_SELFRING_GPA_APER_BASE_LOW,
+                            lower_32_bits(adev->doorbell.base));
+               WREG32_SOC15(NBIO, 0, mmDOORBELL_SELFRING_GPA_APER_BASE_HIGH,
+                            upper_32_bits(adev->doorbell.base));
+       }
+
+       WREG32_SOC15(NBIO, 0, mmDOORBELL_SELFRING_GPA_APER_CNTL, tmp);
 }
 
 static void nbio_v7_4_ih_doorbell_range(struct amdgpu_device *adev,
index 0c6e7f9..189fcb0 100644 (file)
@@ -152,18 +152,22 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
 
        snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
        err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
-       if (err)
-               goto out2;
-
-       err = amdgpu_ucode_validate(adev->psp.ta_fw);
-       if (err)
-               goto out2;
-
-       ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
-       adev->psp.ta_xgmi_ucode_version = le32_to_cpu(ta_hdr->ta_xgmi_ucode_version);
-       adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes);
-       adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr +
-               le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
+       if (err) {
+               release_firmware(adev->psp.ta_fw);
+               adev->psp.ta_fw = NULL;
+               dev_info(adev->dev,
+                        "psp v11.0: Failed to load firmware \"%s\"\n", fw_name);
+       } else {
+               err = amdgpu_ucode_validate(adev->psp.ta_fw);
+               if (err)
+                       goto out2;
+
+               ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
+               adev->psp.ta_xgmi_ucode_version = le32_to_cpu(ta_hdr->ta_xgmi_ucode_version);
+               adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes);
+               adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr +
+                       le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
+       }
 
        return 0;
 
index fd0bfe1..6811a5d 100644 (file)
@@ -78,7 +78,6 @@ static const struct soc15_reg_golden golden_settings_sdma_4[] = {
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0),
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000),
-       SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CLK_CTRL, 0xffffffff, 0x3f000100),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_IB_CNTL, 0x800f0100, 0x00000100),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),
@@ -96,6 +95,7 @@ static const struct soc15_reg_golden golden_settings_sdma_4[] = {
 static const struct soc15_reg_golden golden_settings_sdma_vg10[] = {
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002),
+       SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002)
 };
@@ -103,6 +103,7 @@ static const struct soc15_reg_golden golden_settings_sdma_vg10[] = {
 static const struct soc15_reg_golden golden_settings_sdma_vg12[] = {
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00104001),
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104001),
+       SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0018773f, 0x00104001),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104001)
 };
index 8849b74..9b63997 100644 (file)
@@ -729,11 +729,13 @@ static int soc15_common_early_init(void *handle)
        case CHIP_RAVEN:
                adev->asic_funcs = &soc15_asic_funcs;
                if (adev->rev_id >= 0x8)
-                       adev->external_rev_id = adev->rev_id + 0x81;
+                       adev->external_rev_id = adev->rev_id + 0x79;
                else if (adev->pdev->device == 0x15d8)
                        adev->external_rev_id = adev->rev_id + 0x41;
+               else if (adev->rev_id == 1)
+                       adev->external_rev_id = adev->rev_id + 0x20;
                else
-                       adev->external_rev_id = 0x1;
+                       adev->external_rev_id = adev->rev_id + 0x01;
 
                if (adev->rev_id >= 0x8) {
                        adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
index fbf0ee5..c361360 100644 (file)
@@ -4,8 +4,8 @@
 
 config HSA_AMD
        bool "HSA kernel driver for AMD GPU devices"
-       depends on DRM_AMDGPU && X86_64
-       imply AMD_IOMMU_V2
+       depends on DRM_AMDGPU && (X86_64 || ARM64)
+       imply AMD_IOMMU_V2 if X86_64
        select MMU_NOTIFIER
        help
          Enable this if you want to use HSA features on AMD GPU devices.
index b7bc7d7..2e7c449 100644 (file)
@@ -863,6 +863,7 @@ static int kfd_fill_mem_info_for_cpu(int numa_node_id, int *avail_size,
        return 0;
 }
 
+#ifdef CONFIG_X86_64
 static int kfd_fill_iolink_info_for_cpu(int numa_node_id, int *avail_size,
                                uint32_t *num_entries,
                                struct crat_subtype_iolink *sub_type_hdr)
@@ -905,6 +906,7 @@ static int kfd_fill_iolink_info_for_cpu(int numa_node_id, int *avail_size,
 
        return 0;
 }
+#endif
 
 /* kfd_create_vcrat_image_cpu - Create Virtual CRAT for CPU
  *
@@ -920,7 +922,9 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
        struct crat_subtype_generic *sub_type_hdr;
        int avail_size = *size;
        int numa_node_id;
+#ifdef CONFIG_X86_64
        uint32_t entries = 0;
+#endif
        int ret = 0;
 
        if (!pcrat_image || avail_size < VCRAT_SIZE_FOR_CPU)
@@ -982,6 +986,7 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
                        sub_type_hdr->length);
 
                /* Fill in Subtype: IO Link */
+#ifdef CONFIG_X86_64
                ret = kfd_fill_iolink_info_for_cpu(numa_node_id, &avail_size,
                                &entries,
                                (struct crat_subtype_iolink *)sub_type_hdr);
@@ -992,6 +997,9 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
 
                sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +
                                sub_type_hdr->length * entries);
+#else
+               pr_info("IO link not available for non x86 platforms\n");
+#endif
 
                crat_table->num_domains++;
        }
index 5f5b2ac..09da916 100644 (file)
@@ -1093,8 +1093,6 @@ static uint32_t kfd_generate_gpu_id(struct kfd_dev *gpu)
  *             the GPU device is not already present in the topology device
  *             list then return NULL. This means a new topology device has to
  *             be created for this GPU.
- * TODO: Rather than assiging @gpu to first topology device withtout
- *             gpu attached, it will better to have more stringent check.
  */
 static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
 {
@@ -1102,12 +1100,20 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
        struct kfd_topology_device *out_dev = NULL;
 
        down_write(&topology_lock);
-       list_for_each_entry(dev, &topology_device_list, list)
+       list_for_each_entry(dev, &topology_device_list, list) {
+               /* Discrete GPUs need their own topology device list
+                * entries. Don't assign them to CPU/APU nodes.
+                */
+               if (!gpu->device_info->needs_iommu_device &&
+                   dev->node_props.cpu_cores_count)
+                       continue;
+
                if (!dev->gpu && (dev->node_props.simd_count > 0)) {
                        dev->gpu = gpu;
                        out_dev = dev;
                        break;
                }
+       }
        up_write(&topology_lock);
        return out_dev;
 }
@@ -1392,7 +1398,6 @@ int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_dev **kdev)
 
 static int kfd_cpumask_to_apic_id(const struct cpumask *cpumask)
 {
-       const struct cpuinfo_x86 *cpuinfo;
        int first_cpu_of_numa_node;
 
        if (!cpumask || cpumask == cpu_none_mask)
@@ -1400,9 +1405,11 @@ static int kfd_cpumask_to_apic_id(const struct cpumask *cpumask)
        first_cpu_of_numa_node = cpumask_first(cpumask);
        if (first_cpu_of_numa_node >= nr_cpu_ids)
                return -1;
-       cpuinfo = &cpu_data(first_cpu_of_numa_node);
-
-       return cpuinfo->apicid;
+#ifdef CONFIG_X86_64
+       return cpu_data(first_cpu_of_numa_node).apicid;
+#else
+       return first_cpu_of_numa_node;
+#endif
 }
 
 /* kfd_numa_node_to_apic_id - Returns the APIC ID of the first logical processor
index a9a28db..0b392bf 100644 (file)
@@ -699,22 +699,36 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend)
 {
        struct amdgpu_dm_connector *aconnector;
        struct drm_connector *connector;
+       struct drm_dp_mst_topology_mgr *mgr;
+       int ret;
+       bool need_hotplug = false;
 
        drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-                  aconnector = to_amdgpu_dm_connector(connector);
-                  if (aconnector->dc_link->type == dc_connection_mst_branch &&
-                                  !aconnector->mst_port) {
+       list_for_each_entry(connector, &dev->mode_config.connector_list,
+                           head) {
+               aconnector = to_amdgpu_dm_connector(connector);
+               if (aconnector->dc_link->type != dc_connection_mst_branch ||
+                   aconnector->mst_port)
+                       continue;
 
-                          if (suspend)
-                                  drm_dp_mst_topology_mgr_suspend(&aconnector->mst_mgr);
-                          else
-                                  drm_dp_mst_topology_mgr_resume(&aconnector->mst_mgr);
-                  }
+               mgr = &aconnector->mst_mgr;
+
+               if (suspend) {
+                       drm_dp_mst_topology_mgr_suspend(mgr);
+               } else {
+                       ret = drm_dp_mst_topology_mgr_resume(mgr);
+                       if (ret < 0) {
+                               drm_dp_mst_topology_mgr_set_mst(mgr, false);
+                               need_hotplug = true;
+                       }
+               }
        }
 
        drm_modeset_unlock(&dev->mode_config.connection_mutex);
+
+       if (need_hotplug)
+               drm_kms_helper_hotplug_event(dev);
 }
 
 /**
@@ -898,7 +912,6 @@ static int dm_resume(void *handle)
        struct drm_plane_state *new_plane_state;
        struct dm_plane_state *dm_new_plane_state;
        enum dc_connection_type new_connection_type = dc_connection_none;
-       int ret;
        int i;
 
        /* power on hardware */
@@ -971,13 +984,13 @@ static int dm_resume(void *handle)
                }
        }
 
-       ret = drm_atomic_helper_resume(ddev, dm->cached_state);
+       drm_atomic_helper_resume(ddev, dm->cached_state);
 
        dm->cached_state = NULL;
 
        amdgpu_dm_irq_resume_late(adev);
 
-       return ret;
+       return 0;
 }
 
 /**
@@ -1759,7 +1772,7 @@ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
                + caps.min_input_signal * 0x101;
 
        if (dc_link_set_backlight_level(dm->backlight_link,
-                       brightness, 0, 0))
+                       brightness, 0))
                return 0;
        else
                return 1;
@@ -4069,7 +4082,8 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
        }
 
        if (connector_type == DRM_MODE_CONNECTOR_HDMIA ||
-           connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
+           connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
+           connector_type == DRM_MODE_CONNECTOR_eDP) {
                drm_connector_attach_vrr_capable_property(
                        &aconnector->base);
        }
@@ -5920,7 +5934,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
                if (!drm_atomic_crtc_needs_modeset(new_crtc_state) &&
                    !new_crtc_state->color_mgmt_changed &&
-                   !new_crtc_state->vrr_enabled)
+                   old_crtc_state->vrr_enabled == new_crtc_state->vrr_enabled)
                        continue;
 
                if (!new_crtc_state->enable)
index 9a7ac58..ddd75a4 100644 (file)
@@ -671,6 +671,25 @@ static ssize_t dp_phy_test_pattern_debugfs_write(struct file *f, const char __us
        return bytes_from_user;
 }
 
+/*
+ * Returns the min and max vrr vfreq through the connector's debugfs file.
+ * Example usage: cat /sys/kernel/debug/dri/0/DP-1/vrr_range
+ */
+static int vrr_range_show(struct seq_file *m, void *data)
+{
+       struct drm_connector *connector = m->private;
+       struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
+
+       if (connector->status != connector_status_connected)
+               return -ENODEV;
+
+       seq_printf(m, "Min: %u\n", (unsigned int)aconnector->min_vfreq);
+       seq_printf(m, "Max: %u\n", (unsigned int)aconnector->max_vfreq);
+
+       return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(vrr_range);
+
 static const struct file_operations dp_link_settings_debugfs_fops = {
        .owner = THIS_MODULE,
        .read = dp_link_settings_read,
@@ -697,7 +716,8 @@ static const struct {
 } dp_debugfs_entries[] = {
                {"link_settings", &dp_link_settings_debugfs_fops},
                {"phy_settings", &dp_phy_settings_debugfs_fop},
-               {"test_pattern", &dp_phy_test_pattern_fops}
+               {"test_pattern", &dp_phy_test_pattern_fops},
+               {"vrr_range", &vrr_range_fops}
 };
 
 int connector_debugfs_init(struct amdgpu_dm_connector *connector)
index 52deacf..b0265db 100644 (file)
@@ -2190,8 +2190,7 @@ int dc_link_get_backlight_level(const struct dc_link *link)
 
 bool dc_link_set_backlight_level(const struct dc_link *link,
                uint32_t backlight_pwm_u16_16,
-               uint32_t frame_ramp,
-               const struct dc_stream_state *stream)
+               uint32_t frame_ramp)
 {
        struct dc  *core_dc = link->ctx->dc;
        struct abm *abm = core_dc->res_pool->abm;
@@ -2206,10 +2205,6 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
                (abm->funcs->set_backlight_level_pwm == NULL))
                return false;
 
-       if (stream)
-               ((struct dc_stream_state *)stream)->bl_pwm_level =
-                               backlight_pwm_u16_16;
-
        use_smooth_brightness = dmcu->funcs->is_dmcu_initialized(dmcu);
 
        DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n",
@@ -2637,11 +2632,6 @@ void core_link_enable_stream(
 
                if (dc_is_dp_signal(pipe_ctx->stream->signal))
                        enable_stream_features(pipe_ctx);
-
-               dc_link_set_backlight_level(pipe_ctx->stream->sink->link,
-                               pipe_ctx->stream->bl_pwm_level,
-                               0,
-                               pipe_ctx->stream);
        }
 
 }
index 29f19d5..b2243e0 100644 (file)
@@ -146,8 +146,7 @@ static inline struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_
  */
 bool dc_link_set_backlight_level(const struct dc_link *dc_link,
                uint32_t backlight_pwm_u16_16,
-               uint32_t frame_ramp,
-               const struct dc_stream_state *stream);
+               uint32_t frame_ramp);
 
 int dc_link_get_backlight_level(const struct dc_link *dc_link);
 
index be34d63..d70c9e1 100644 (file)
@@ -91,7 +91,6 @@ struct dc_stream_state {
 
        /* DMCU info */
        unsigned int abm_level;
-       unsigned int bl_pwm_level;
 
        /* from core_stream struct */
        struct dc_context *ctx;
index afd287f..19801bd 100644 (file)
@@ -591,7 +591,15 @@ static void dce11_pplib_apply_display_requirements(
                        dc,
                        context->bw.dce.sclk_khz);
 
-       pp_display_cfg->min_dcfclock_khz = pp_display_cfg->min_engine_clock_khz;
+       /*
+        * As workaround for >4x4K lightup set dcfclock to min_engine_clock value.
+        * This is not required for less than 5 displays,
+        * thus don't request decfclk in dc to avoid impact
+        * on power saving.
+        *
+        */
+       pp_display_cfg->min_dcfclock_khz = (context->stream_count > 4)?
+                       pp_display_cfg->min_engine_clock_khz : 0;
 
        pp_display_cfg->min_engine_clock_deep_sleep_khz
                        = context->bw.dce.sclk_deep_sleep_khz;
index 4bf2475..8f09b86 100644 (file)
@@ -1000,7 +1000,7 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
 
                pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio);
 
-               if (num_audio == 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL)
+               if (num_audio >= 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL)
                        /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
                        pp_smu->set_pme_wa_enable(&pp_smu->pp_smu);
                /* un-mute audio */
@@ -1017,6 +1017,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) {
+               struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu;
+
                if (option != KEEP_ACQUIRED_RESOURCE ||
                                !dc->debug.az_endpoint_mute_only) {
                        /*only disalbe az_endpoint if power down or free*/
@@ -1036,6 +1038,9 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)
                        update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false);
                        pipe_ctx->stream_res.audio = NULL;
                }
+               if (pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL)
+                       /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
+                       pp_smu->set_pme_wa_enable(&pp_smu->pp_smu);
 
                /* TODO: notify audio driver for if audio modes list changed
                 * add audio mode list change flag */
index dcb3c55..cd1ebe5 100644 (file)
@@ -463,7 +463,7 @@ void dpp1_set_cursor_position(
        if (src_y_offset >= (int)param->viewport.height)
                cur_en = 0;  /* not visible beyond bottom edge*/
 
-       if (src_y_offset < 0)
+       if (src_y_offset + (int)height <= 0)
                cur_en = 0;  /* not visible beyond top edge*/
 
        REG_UPDATE(CURSOR0_CONTROL,
index 345af01..d1acd71 100644 (file)
@@ -1140,7 +1140,7 @@ void hubp1_cursor_set_position(
        if (src_y_offset >= (int)param->viewport.height)
                cur_en = 0;  /* not visible beyond bottom edge*/
 
-       if (src_y_offset < 0) //+ (int)hubp->curs_attr.height
+       if (src_y_offset + (int)hubp->curs_attr.height <= 0)
                cur_en = 0;  /* not visible beyond top edge*/
 
        if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0)
index 91e015e..58a12dd 100644 (file)
@@ -2355,29 +2355,22 @@ static void dcn10_apply_ctx_for_surface(
                        top_pipe_to_program->plane_state->update_flags.bits.full_update)
                for (i = 0; i < dc->res_pool->pipe_count; i++) {
                        struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-
+                       tg = pipe_ctx->stream_res.tg;
                        /* Skip inactive pipes and ones already updated */
                        if (!pipe_ctx->stream || pipe_ctx->stream == stream
-                                       || !pipe_ctx->plane_state)
+                                       || !pipe_ctx->plane_state
+                                       || !tg->funcs->is_tg_enabled(tg))
                                continue;
 
-                       pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
+                       tg->funcs->lock(tg);
 
                        pipe_ctx->plane_res.hubp->funcs->hubp_setup_interdependent(
                                pipe_ctx->plane_res.hubp,
                                &pipe_ctx->dlg_regs,
                                &pipe_ctx->ttu_regs);
-               }
-
-       for (i = 0; i < dc->res_pool->pipe_count; i++) {
-               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
 
-               if (!pipe_ctx->stream || pipe_ctx->stream == stream
-                               || !pipe_ctx->plane_state)
-                       continue;
-
-               dcn10_pipe_control_lock(dc, pipe_ctx, false);
-       }
+                       tg->funcs->unlock(tg);
+               }
 
        if (num_planes == 0)
                false_optc_underflow_wa(dc, stream, tg);
index 00f63b7..c11a443 100644 (file)
@@ -57,6 +57,7 @@ static const unsigned char abm_config[abm_defines_max_config][abm_defines_max_le
 #define NUM_POWER_FN_SEGS 8
 #define NUM_BL_CURVE_SEGS 16
 
+#pragma pack(push, 1)
 /* NOTE: iRAM is 256B in size */
 struct iram_table_v_2 {
        /* flags                      */
@@ -100,6 +101,7 @@ struct iram_table_v_2 {
        uint8_t dummy8;                                                 /* 0xfe       */
        uint8_t dummy9;                                                 /* 0xff       */
 };
+#pragma pack(pop)
 
 static uint16_t backlight_8_to_16(unsigned int backlight_8bit)
 {
index 1479ea1..789c4f2 100644 (file)
@@ -127,12 +127,13 @@ enum amd_pp_task {
 };
 
 enum PP_SMC_POWER_PROFILE {
-       PP_SMC_POWER_PROFILE_FULLSCREEN3D = 0x0,
-       PP_SMC_POWER_PROFILE_POWERSAVING  = 0x1,
-       PP_SMC_POWER_PROFILE_VIDEO        = 0x2,
-       PP_SMC_POWER_PROFILE_VR           = 0x3,
-       PP_SMC_POWER_PROFILE_COMPUTE      = 0x4,
-       PP_SMC_POWER_PROFILE_CUSTOM       = 0x5,
+       PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT = 0x0,
+       PP_SMC_POWER_PROFILE_FULLSCREEN3D = 0x1,
+       PP_SMC_POWER_PROFILE_POWERSAVING  = 0x2,
+       PP_SMC_POWER_PROFILE_VIDEO        = 0x3,
+       PP_SMC_POWER_PROFILE_VR           = 0x4,
+       PP_SMC_POWER_PROFILE_COMPUTE      = 0x5,
+       PP_SMC_POWER_PROFILE_CUSTOM       = 0x6,
 };
 
 enum {
index 0173d04..310b102 100644 (file)
@@ -64,17 +64,19 @@ static int ci_set_asic_special_caps(struct pp_hwmgr *hwmgr);
 
 static void hwmgr_init_workload_prority(struct pp_hwmgr *hwmgr)
 {
-       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 2;
-       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 0;
-       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 1;
-       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VR] = 3;
-       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 4;
-
-       hwmgr->workload_setting[0] = PP_SMC_POWER_PROFILE_POWERSAVING;
-       hwmgr->workload_setting[1] = PP_SMC_POWER_PROFILE_VIDEO;
-       hwmgr->workload_setting[2] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
-       hwmgr->workload_setting[3] = PP_SMC_POWER_PROFILE_VR;
-       hwmgr->workload_setting[4] = PP_SMC_POWER_PROFILE_COMPUTE;
+       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
+       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
+       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;
+       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 3;
+       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VR] = 4;
+       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;
+
+       hwmgr->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+       hwmgr->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
+       hwmgr->workload_setting[2] = PP_SMC_POWER_PROFILE_POWERSAVING;
+       hwmgr->workload_setting[3] = PP_SMC_POWER_PROFILE_VIDEO;
+       hwmgr->workload_setting[4] = PP_SMC_POWER_PROFILE_VR;
+       hwmgr->workload_setting[5] = PP_SMC_POWER_PROFILE_COMPUTE;
 }
 
 int hwmgr_early_init(struct pp_hwmgr *hwmgr)
index f95c5f5..5273de3 100644 (file)
@@ -1033,6 +1033,7 @@ static int smu10_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
                break;
        case amd_pp_dpp_clock:
                pclk_vol_table = pinfo->vdd_dep_on_dppclk;
+               break;
        default:
                return -EINVAL;
        }
index d913904..c8f5c00 100644 (file)
@@ -77,8 +77,9 @@
 #define PCIE_BUS_CLK                10000
 #define TCLK                        (PCIE_BUS_CLK / 10)
 
-static const struct profile_mode_setting smu7_profiling[6] =
-                                       {{1, 0, 100, 30, 1, 0, 100, 10},
+static const struct profile_mode_setting smu7_profiling[7] =
+                                       {{0, 0, 0, 0, 0, 0, 0, 0},
+                                        {1, 0, 100, 30, 1, 0, 100, 10},
                                         {1, 10, 0, 30, 0, 0, 0, 0},
                                         {0, 0, 0, 0, 1, 10, 16, 31},
                                         {1, 0, 11, 50, 1, 0, 100, 10},
@@ -4889,7 +4890,8 @@ static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
        uint32_t i, size = 0;
        uint32_t len;
 
-       static const char *profile_name[6] = {"3D_FULL_SCREEN",
+       static const char *profile_name[7] = {"BOOTUP_DEFAULT",
+                                       "3D_FULL_SCREEN",
                                        "POWER_SAVING",
                                        "VIDEO",
                                        "VR",
index 79c8624..91e3bbe 100644 (file)
@@ -804,9 +804,9 @@ static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
 
        hwmgr->backend = data;
 
-       hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO];
-       hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
-       hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
+       hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
+       hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+       hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
 
        vega10_set_default_registry_data(hwmgr);
        data->disable_dpm_mask = 0xff;
@@ -4668,13 +4668,15 @@ static int vega10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
 {
        struct vega10_hwmgr *data = hwmgr->backend;
        uint32_t i, size = 0;
-       static const uint8_t profile_mode_setting[5][4] = {{70, 60, 1, 3,},
+       static const uint8_t profile_mode_setting[6][4] = {{70, 60, 0, 0,},
+                                               {70, 60, 1, 3,},
                                                {90, 60, 0, 0,},
                                                {70, 60, 0, 0,},
                                                {70, 90, 0, 0,},
                                                {30, 60, 0, 6,},
                                                };
-       static const char *profile_name[6] = {"3D_FULL_SCREEN",
+       static const char *profile_name[7] = {"BOOTUP_DEFAULT",
+                                       "3D_FULL_SCREEN",
                                        "POWER_SAVING",
                                        "VIDEO",
                                        "VR",
index b8747a5..99d596d 100644 (file)
@@ -32,6 +32,7 @@
 #include "vega10_pptable.h"
 
 #define NUM_DSPCLK_LEVELS 8
+#define VEGA10_ENGINECLOCK_HARDMAX 198000
 
 static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,
                enum phm_platform_caps cap)
@@ -258,7 +259,26 @@ static int init_over_drive_limits(
                struct pp_hwmgr *hwmgr,
                const ATOM_Vega10_POWERPLAYTABLE *powerplay_table)
 {
-       hwmgr->platform_descriptor.overdriveLimit.engineClock =
+       const ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table =
+                       (const ATOM_Vega10_GFXCLK_Dependency_Table *)
+                       (((unsigned long) powerplay_table) +
+                       le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset));
+       bool is_acg_enabled = false;
+       ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_v2;
+
+       if (gfxclk_dep_table->ucRevId == 1) {
+               patom_record_v2 =
+                       (ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)gfxclk_dep_table->entries;
+               is_acg_enabled =
+                       (bool)patom_record_v2[gfxclk_dep_table->ucNumEntries-1].ucACGEnable;
+       }
+
+       if (powerplay_table->ulMaxODEngineClock > VEGA10_ENGINECLOCK_HARDMAX &&
+               !is_acg_enabled)
+               hwmgr->platform_descriptor.overdriveLimit.engineClock =
+                       VEGA10_ENGINECLOCK_HARDMAX;
+       else
+               hwmgr->platform_descriptor.overdriveLimit.engineClock =
                        le32_to_cpu(powerplay_table->ulMaxODEngineClock);
        hwmgr->platform_descriptor.overdriveLimit.memoryClock =
                        le32_to_cpu(powerplay_table->ulMaxODMemoryClock);
index 5436444..0c82129 100644 (file)
@@ -753,6 +753,22 @@ static int vega12_init_smc_table(struct pp_hwmgr *hwmgr)
        return 0;
 }
 
+static int vega12_run_acg_btc(struct pp_hwmgr *hwmgr)
+{
+       uint32_t result;
+
+       PP_ASSERT_WITH_CODE(
+               smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgBtc) == 0,
+               "[Run_ACG_BTC] Attempt to run ACG BTC failed!",
+               return -EINVAL);
+
+       result = smum_get_argument(hwmgr);
+       PP_ASSERT_WITH_CODE(result == 1,
+                       "Failed to run ACG BTC!", return -EINVAL);
+
+       return 0;
+}
+
 static int vega12_set_allowed_featuresmask(struct pp_hwmgr *hwmgr)
 {
        struct vega12_hwmgr *data =
@@ -931,6 +947,11 @@ static int vega12_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
                        "Failed to initialize SMC table!",
                        result = tmp_result);
 
+       tmp_result = vega12_run_acg_btc(hwmgr);
+       PP_ASSERT_WITH_CODE(!tmp_result,
+                       "Failed to run ACG BTC!",
+                       result = tmp_result);
+
        result = vega12_enable_all_smu_features(hwmgr);
        PP_ASSERT_WITH_CODE(!result,
                        "Failed to enable all smu features!",
index 26154f9..82935a3 100644 (file)
@@ -390,9 +390,9 @@ static int vega20_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
 
        hwmgr->backend = data;
 
-       hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO];
-       hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
-       hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
+       hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
+       hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+       hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
 
        vega20_set_default_registry_data(hwmgr);
 
@@ -980,6 +980,9 @@ static int vega20_od8_set_feature_capabilities(
            pp_table->FanZeroRpmEnable)
                od_settings->overdrive8_capabilities |= OD8_FAN_ZERO_RPM_CONTROL;
 
+       if (!od_settings->overdrive8_capabilities)
+               hwmgr->od_enabled = false;
+
        return 0;
 }
 
@@ -1689,13 +1692,6 @@ static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_
                                        (PPCLK_UCLK << 16) | (min_freq & 0xffff))),
                                        "Failed to set soft min memclk !",
                                        return ret);
-
-               min_freq = data->dpm_table.mem_table.dpm_state.hard_min_level;
-               PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
-                                       hwmgr, PPSMC_MSG_SetHardMinByFreq,
-                                       (PPCLK_UCLK << 16) | (min_freq & 0xffff))),
-                                       "Failed to set hard min memclk !",
-                                       return ret);
        }
 
        if (data->smu_features[GNLD_DPM_UVD].enabled &&
@@ -2248,6 +2244,13 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
                soft_min_level = mask ? (ffs(mask) - 1) : 0;
                soft_max_level = mask ? (fls(mask) - 1) : 0;
 
+               if (soft_max_level >= data->dpm_table.gfx_table.count) {
+                       pr_err("Clock level specified %d is over max allowed %d\n",
+                                       soft_max_level,
+                                       data->dpm_table.gfx_table.count - 1);
+                       return -EINVAL;
+               }
+
                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 =
@@ -2268,6 +2271,13 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
                soft_min_level = mask ? (ffs(mask) - 1) : 0;
                soft_max_level = mask ? (fls(mask) - 1) : 0;
 
+               if (soft_max_level >= data->dpm_table.mem_table.count) {
+                       pr_err("Clock level specified %d is over max allowed %d\n",
+                                       soft_max_level,
+                                       data->dpm_table.mem_table.count - 1);
+                       return -EINVAL;
+               }
+
                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 =
@@ -3261,6 +3271,9 @@ static int conv_power_profile_to_pplib_workload(int power_profile)
        int pplib_workload = 0;
 
        switch (power_profile) {
+       case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT:
+               pplib_workload = WORKLOAD_DEFAULT_BIT;
+               break;
        case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
                pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT;
                break;
@@ -3290,6 +3303,7 @@ static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
        uint32_t i, size = 0;
        uint16_t workload_type = 0;
        static const char *profile_name[] = {
+                                       "BOOTUP_DEFAULT",
                                        "3D_FULL_SCREEN",
                                        "POWER_SAVING",
                                        "VIDEO",
index 0d298a0..8cb831b 100644 (file)
@@ -705,7 +705,7 @@ enum PP_TABLE_VERSION {
 /**
  * The main hardware manager structure.
  */
-#define Workload_Policy_Max 5
+#define Workload_Policy_Max 6
 
 struct pp_hwmgr {
        void *adev;
index 8e28e73..e6403b9 100644 (file)
@@ -98,6 +98,8 @@
 #define DP0_STARTVAL           0x064c
 #define DP0_ACTIVEVAL          0x0650
 #define DP0_SYNCVAL            0x0654
+#define SYNCVAL_HS_POL_ACTIVE_LOW      (1 << 15)
+#define SYNCVAL_VS_POL_ACTIVE_LOW      (1 << 31)
 #define DP0_MISC               0x0658
 #define TU_SIZE_RECOMMENDED            (63) /* LSCLK cycles per TU */
 #define BPC_6                          (0 << 5)
 #define DP0_LTLOOPCTRL         0x06d8
 #define DP0_SNKLTCTRL          0x06e4
 
+#define DP1_SRCCTRL            0x07a0
+
 /* PHY */
 #define DP_PHY_CTRL            0x0800
 #define DP_PHY_RST                     BIT(28)  /* DP PHY Global Soft Reset */
 #define PHY_M1_RST                     BIT(12)  /* Reset PHY1 Main Channel */
 #define PHY_RDY                                BIT(16)  /* PHY Main Channels Ready */
 #define PHY_M0_RST                     BIT(8)   /* Reset PHY0 Main Channel */
+#define PHY_2LANE                      BIT(2)   /* PHY Enable 2 lanes */
 #define PHY_A0_EN                      BIT(1)   /* PHY Aux Channel0 Enable */
 #define PHY_M0_EN                      BIT(0)   /* PHY Main Channel0 Enable */
 
@@ -540,6 +545,7 @@ static int tc_aux_link_setup(struct tc_data *tc)
        unsigned long rate;
        u32 value;
        int ret;
+       u32 dp_phy_ctrl;
 
        rate = clk_get_rate(tc->refclk);
        switch (rate) {
@@ -564,7 +570,10 @@ static int tc_aux_link_setup(struct tc_data *tc)
        value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2;
        tc_write(SYS_PLLPARAM, value);
 
-       tc_write(DP_PHY_CTRL, BGREN | PWR_SW_EN | BIT(2) | PHY_A0_EN);
+       dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN;
+       if (tc->link.base.num_lanes == 2)
+               dp_phy_ctrl |= PHY_2LANE;
+       tc_write(DP_PHY_CTRL, dp_phy_ctrl);
 
        /*
         * Initially PLLs are in bypass. Force PLL parameter update,
@@ -719,7 +728,9 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
 
        tc_write(DP0_ACTIVEVAL, (mode->vdisplay << 16) | (mode->hdisplay));
 
-       tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0));
+       tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0) |
+                ((mode->flags & DRM_MODE_FLAG_NHSYNC) ? SYNCVAL_HS_POL_ACTIVE_LOW : 0) |
+                ((mode->flags & DRM_MODE_FLAG_NVSYNC) ? SYNCVAL_VS_POL_ACTIVE_LOW : 0));
 
        tc_write(DPIPXLFMT, VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW |
                 DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888);
@@ -829,12 +840,11 @@ static int tc_main_link_setup(struct tc_data *tc)
        if (!tc->mode)
                return -EINVAL;
 
-       /* from excel file - DP0_SrcCtrl */
-       tc_write(DP0_SRCCTRL, DP0_SRCCTRL_SCRMBLDIS | DP0_SRCCTRL_EN810B |
-                DP0_SRCCTRL_LANESKEW | DP0_SRCCTRL_LANES_2 |
-                DP0_SRCCTRL_BW27 | DP0_SRCCTRL_AUTOCORRECT);
-       /* from excel file - DP1_SrcCtrl */
-       tc_write(0x07a0, 0x00003083);
+       tc_write(DP0_SRCCTRL, tc_srcctrl(tc));
+       /* SSCG and BW27 on DP1 must be set to the same as on DP0 */
+       tc_write(DP1_SRCCTRL,
+                (tc->link.spread ? DP0_SRCCTRL_SSCG : 0) |
+                ((tc->link.base.rate != 162000) ? DP0_SRCCTRL_BW27 : 0));
 
        rate = clk_get_rate(tc->refclk);
        switch (rate) {
@@ -855,8 +865,11 @@ static int tc_main_link_setup(struct tc_data *tc)
        }
        value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2;
        tc_write(SYS_PLLPARAM, value);
+
        /* Setup Main Link */
-       dp_phy_ctrl = BGREN | PWR_SW_EN | BIT(2) | PHY_A0_EN |  PHY_M0_EN;
+       dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN | PHY_M0_EN;
+       if (tc->link.base.num_lanes == 2)
+               dp_phy_ctrl |= PHY_2LANE;
        tc_write(DP_PHY_CTRL, dp_phy_ctrl);
        msleep(100);
 
@@ -1105,10 +1118,20 @@ static bool tc_bridge_mode_fixup(struct drm_bridge *bridge,
 static enum drm_mode_status tc_connector_mode_valid(struct drm_connector *connector,
                                   struct drm_display_mode *mode)
 {
+       struct tc_data *tc = connector_to_tc(connector);
+       u32 req, avail;
+       u32 bits_per_pixel = 24;
+
        /* DPI interface clock limitation: upto 154 MHz */
        if (mode->clock > 154000)
                return MODE_CLOCK_HIGH;
 
+       req = mode->clock * bits_per_pixel / 8;
+       avail = tc->link.base.num_lanes * tc->link.base.rate;
+
+       if (req > avail)
+               return MODE_BAD;
+
        return MODE_OK;
 }
 
@@ -1186,7 +1209,8 @@ static int tc_bridge_attach(struct drm_bridge *bridge)
        /* Create eDP connector */
        drm_connector_helper_add(&tc->connector, &tc_connector_helper_funcs);
        ret = drm_connector_init(drm, &tc->connector, &tc_connector_funcs,
-                                DRM_MODE_CONNECTOR_eDP);
+                                tc->panel ? DRM_MODE_CONNECTOR_eDP :
+                                DRM_MODE_CONNECTOR_DisplayPort);
        if (ret)
                return ret;
 
@@ -1195,6 +1219,10 @@ static int tc_bridge_attach(struct drm_bridge *bridge)
 
        drm_display_info_set_bus_formats(&tc->connector.display_info,
                                         &bus_format, 1);
+       tc->connector.display_info.bus_flags =
+               DRM_BUS_FLAG_DE_HIGH |
+               DRM_BUS_FLAG_PIXDATA_NEGEDGE |
+               DRM_BUS_FLAG_SYNC_NEGEDGE;
        drm_connector_attach_encoder(&tc->connector, tc->bridge.encoder);
 
        return 0;
index c408898..9a1f41a 100644 (file)
@@ -1296,12 +1296,11 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
                        (arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
                return -EINVAL;
 
-       drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
-
        state = drm_atomic_state_alloc(dev);
        if (!state)
                return -ENOMEM;
 
+       drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
        state->acquire_ctx = &ctx;
        state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
 
index 2d6c491..516e82d 100644 (file)
@@ -1273,6 +1273,8 @@ static const struct dpcd_quirk dpcd_quirk_list[] = {
        { OUI(0x00, 0x22, 0xb9), DEVICE_ID_ANY, true, BIT(DP_DPCD_QUIRK_CONSTANT_N) },
        /* LG LP140WF6-SPM1 eDP panel */
        { OUI(0x00, 0x22, 0xb9), DEVICE_ID('s', 'i', 'v', 'a', 'r', 'T'), false, BIT(DP_DPCD_QUIRK_CONSTANT_N) },
+       /* Apple panels need some additional handling to support PSR */
+       { OUI(0x00, 0x10, 0xfa), DEVICE_ID_ANY, false, BIT(DP_DPCD_QUIRK_NO_PSR) }
 };
 
 #undef OUI
index d3af098..d73703a 100644 (file)
@@ -1621,6 +1621,64 @@ static bool drm_fb_pixel_format_equal(const struct fb_var_screeninfo *var_1,
               var_1->transp.msb_right == var_2->transp.msb_right;
 }
 
+static void drm_fb_helper_fill_pixel_fmt(struct fb_var_screeninfo *var,
+                                        u8 depth)
+{
+       switch (depth) {
+       case 8:
+               var->red.offset = 0;
+               var->green.offset = 0;
+               var->blue.offset = 0;
+               var->red.length = 8; /* 8bit DAC */
+               var->green.length = 8;
+               var->blue.length = 8;
+               var->transp.offset = 0;
+               var->transp.length = 0;
+               break;
+       case 15:
+               var->red.offset = 10;
+               var->green.offset = 5;
+               var->blue.offset = 0;
+               var->red.length = 5;
+               var->green.length = 5;
+               var->blue.length = 5;
+               var->transp.offset = 15;
+               var->transp.length = 1;
+               break;
+       case 16:
+               var->red.offset = 11;
+               var->green.offset = 5;
+               var->blue.offset = 0;
+               var->red.length = 5;
+               var->green.length = 6;
+               var->blue.length = 5;
+               var->transp.offset = 0;
+               break;
+       case 24:
+               var->red.offset = 16;
+               var->green.offset = 8;
+               var->blue.offset = 0;
+               var->red.length = 8;
+               var->green.length = 8;
+               var->blue.length = 8;
+               var->transp.offset = 0;
+               var->transp.length = 0;
+               break;
+       case 32:
+               var->red.offset = 16;
+               var->green.offset = 8;
+               var->blue.offset = 0;
+               var->red.length = 8;
+               var->green.length = 8;
+               var->blue.length = 8;
+               var->transp.offset = 24;
+               var->transp.length = 8;
+               break;
+       default:
+               break;
+       }
+}
+
 /**
  * drm_fb_helper_check_var - implementation for &fb_ops.fb_check_var
  * @var: screeninfo to check
@@ -1632,9 +1690,14 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
        struct drm_fb_helper *fb_helper = info->par;
        struct drm_framebuffer *fb = fb_helper->fb;
 
-       if (var->pixclock != 0 || in_dbg_master())
+       if (in_dbg_master())
                return -EINVAL;
 
+       if (var->pixclock != 0) {
+               DRM_DEBUG("fbdev emulation doesn't support changing the pixel clock, value of pixclock is ignored\n");
+               var->pixclock = 0;
+       }
+
        if ((drm_format_info_block_width(fb->format, 0) > 1) ||
            (drm_format_info_block_height(fb->format, 0) > 1))
                return -EINVAL;
@@ -1655,6 +1718,20 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
        }
 
        /*
+        * Workaround for SDL 1.2, which is known to be setting all pixel format
+        * fields values to zero in some cases. We treat this situation as a
+        * kind of "use some reasonable autodetected values".
+        */
+       if (!var->red.offset     && !var->green.offset    &&
+           !var->blue.offset    && !var->transp.offset   &&
+           !var->red.length     && !var->green.length    &&
+           !var->blue.length    && !var->transp.length   &&
+           !var->red.msb_right  && !var->green.msb_right &&
+           !var->blue.msb_right && !var->transp.msb_right) {
+               drm_fb_helper_fill_pixel_fmt(var, fb->format->depth);
+       }
+
+       /*
         * drm fbdev emulation doesn't support changing the pixel format at all,
         * so reject all pixel format changing requests.
         */
@@ -1967,59 +2044,7 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe
        info->var.yoffset = 0;
        info->var.activate = FB_ACTIVATE_NOW;
 
-       switch (fb->format->depth) {
-       case 8:
-               info->var.red.offset = 0;
-               info->var.green.offset = 0;
-               info->var.blue.offset = 0;
-               info->var.red.length = 8; /* 8bit DAC */
-               info->var.green.length = 8;
-               info->var.blue.length = 8;
-               info->var.transp.offset = 0;
-               info->var.transp.length = 0;
-               break;
-       case 15:
-               info->var.red.offset = 10;
-               info->var.green.offset = 5;
-               info->var.blue.offset = 0;
-               info->var.red.length = 5;
-               info->var.green.length = 5;
-               info->var.blue.length = 5;
-               info->var.transp.offset = 15;
-               info->var.transp.length = 1;
-               break;
-       case 16:
-               info->var.red.offset = 11;
-               info->var.green.offset = 5;
-               info->var.blue.offset = 0;
-               info->var.red.length = 5;
-               info->var.green.length = 6;
-               info->var.blue.length = 5;
-               info->var.transp.offset = 0;
-               break;
-       case 24:
-               info->var.red.offset = 16;
-               info->var.green.offset = 8;
-               info->var.blue.offset = 0;
-               info->var.red.length = 8;
-               info->var.green.length = 8;
-               info->var.blue.length = 8;
-               info->var.transp.offset = 0;
-               info->var.transp.length = 0;
-               break;
-       case 32:
-               info->var.red.offset = 16;
-               info->var.green.offset = 8;
-               info->var.blue.offset = 0;
-               info->var.red.length = 8;
-               info->var.green.length = 8;
-               info->var.blue.length = 8;
-               info->var.transp.offset = 24;
-               info->var.transp.length = 8;
-               break;
-       default:
-               break;
-       }
+       drm_fb_helper_fill_pixel_fmt(&info->var, fb->format->depth);
 
        info->var.xres = fb_width;
        info->var.yres = fb_height;
index 99cba8e..5df1256 100644 (file)
@@ -528,7 +528,8 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
 
        object_count = cl->object_count;
 
-       object_ids = memdup_user(u64_to_user_ptr(cl->object_ids), object_count * sizeof(__u32));
+       object_ids = memdup_user(u64_to_user_ptr(cl->object_ids),
+                       array_size(object_count, sizeof(__u32)));
        if (IS_ERR(object_ids))
                return PTR_ERR(object_ids);
 
index cd9bc0c..004191d 100644 (file)
@@ -459,11 +459,11 @@ static int set_property_atomic(struct drm_mode_object *obj,
        struct drm_modeset_acquire_ctx ctx;
        int ret;
 
-       drm_modeset_acquire_init(&ctx, 0);
-
        state = drm_atomic_state_alloc(dev);
        if (!state)
                return -ENOMEM;
+
+       drm_modeset_acquire_init(&ctx, 0);
        state->acquire_ctx = &ctx;
 retry:
        if (prop == state->dev->mode_config.dpms_property) {
index 24a7504..f91e02c 100644 (file)
@@ -758,7 +758,7 @@ int drm_mode_hsync(const struct drm_display_mode *mode)
        if (mode->hsync)
                return mode->hsync;
 
-       if (mode->htotal < 0)
+       if (mode->htotal <= 0)
                return 0;
 
        calc_val = (mode->clock * 1000) / mode->htotal; /* hsync in Hz */
index a9d9df6..693748a 100644 (file)
@@ -61,8 +61,9 @@ drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t ali
                return NULL;
 
        dmah->size = size;
-       dmah->vaddr = dma_zalloc_coherent(&dev->pdev->dev, size, &dmah->busaddr,
-                                               GFP_KERNEL | __GFP_COMP);
+       dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size,
+                                        &dmah->busaddr,
+                                        GFP_KERNEL | __GFP_COMP);
 
        if (dmah->vaddr == NULL) {
                kfree(dmah);
index b5475c9..e9f343b 100644 (file)
@@ -2799,6 +2799,7 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)
        MMIO_DFH(_MMIO(0xe2a0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
        MMIO_DFH(_MMIO(0xe2b0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
        MMIO_DFH(_MMIO(0xe2c0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+       MMIO_DFH(_MMIO(0x21f0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
        return 0;
 }
 
index 5af11cf..e1675a0 100644 (file)
@@ -41,7 +41,7 @@ struct intel_gvt_mpt {
        int (*host_init)(struct device *dev, void *gvt, const void *ops);
        void (*host_exit)(struct device *dev, void *gvt);
        int (*attach_vgpu)(void *vgpu, unsigned long *handle);
-       void (*detach_vgpu)(unsigned long handle);
+       void (*detach_vgpu)(void *vgpu);
        int (*inject_msi)(unsigned long handle, u32 addr, u16 data);
        unsigned long (*from_virt_to_mfn)(void *p);
        int (*enable_page_track)(unsigned long handle, u64 gfn);
index c107214..dd3dfd0 100644 (file)
@@ -996,7 +996,7 @@ static int intel_vgpu_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
 {
        unsigned int index;
        u64 virtaddr;
-       unsigned long req_size, pgoff = 0;
+       unsigned long req_size, pgoff, req_start;
        pgprot_t pg_prot;
        struct intel_vgpu *vgpu = mdev_get_drvdata(mdev);
 
@@ -1014,7 +1014,17 @@ static int intel_vgpu_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
        pg_prot = vma->vm_page_prot;
        virtaddr = vma->vm_start;
        req_size = vma->vm_end - vma->vm_start;
-       pgoff = vgpu_aperture_pa_base(vgpu) >> PAGE_SHIFT;
+       pgoff = vma->vm_pgoff &
+               ((1U << (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT)) - 1);
+       req_start = pgoff << PAGE_SHIFT;
+
+       if (!intel_vgpu_in_aperture(vgpu, req_start))
+               return -EINVAL;
+       if (req_start + req_size >
+           vgpu_aperture_offset(vgpu) + vgpu_aperture_sz(vgpu))
+               return -EINVAL;
+
+       pgoff = (gvt_aperture_pa_base(vgpu->gvt) >> PAGE_SHIFT) + pgoff;
 
        return remap_pfn_range(vma, virtaddr, pgoff, req_size, pg_prot);
 }
@@ -1662,9 +1672,21 @@ static int kvmgt_attach_vgpu(void *vgpu, unsigned long *handle)
        return 0;
 }
 
-static void kvmgt_detach_vgpu(unsigned long handle)
+static void kvmgt_detach_vgpu(void *p_vgpu)
 {
-       /* nothing to do here */
+       int i;
+       struct intel_vgpu *vgpu = (struct intel_vgpu *)p_vgpu;
+
+       if (!vgpu->vdev.region)
+               return;
+
+       for (i = 0; i < vgpu->vdev.num_regions; i++)
+               if (vgpu->vdev.region[i].ops->release)
+                       vgpu->vdev.region[i].ops->release(vgpu,
+                                       &vgpu->vdev.region[i]);
+       vgpu->vdev.num_regions = 0;
+       kfree(vgpu->vdev.region);
+       vgpu->vdev.region = NULL;
 }
 
 static int kvmgt_inject_msi(unsigned long handle, u32 addr, u16 data)
index 67f1999..3ed3412 100644 (file)
@@ -101,7 +101,7 @@ static inline void intel_gvt_hypervisor_detach_vgpu(struct intel_vgpu *vgpu)
        if (!intel_gvt_host.mpt->detach_vgpu)
                return;
 
-       intel_gvt_host.mpt->detach_vgpu(vgpu->handle);
+       intel_gvt_host.mpt->detach_vgpu(vgpu);
 }
 
 #define MSI_CAP_CONTROL(offset) (offset + 2)
index 1ad8c5e..55bb788 100644 (file)
@@ -332,6 +332,9 @@ static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
 
        i915_gem_object_unpin_map(wa_ctx->indirect_ctx.obj);
        i915_gem_object_put(wa_ctx->indirect_ctx.obj);
+
+       wa_ctx->indirect_ctx.obj = NULL;
+       wa_ctx->indirect_ctx.shadow_va = NULL;
 }
 
 static int set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload,
@@ -356,6 +359,33 @@ static int set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload,
        return 0;
 }
 
+static int
+intel_gvt_workload_req_alloc(struct intel_vgpu_workload *workload)
+{
+       struct intel_vgpu *vgpu = workload->vgpu;
+       struct intel_vgpu_submission *s = &vgpu->submission;
+       struct i915_gem_context *shadow_ctx = s->shadow_ctx;
+       struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+       struct intel_engine_cs *engine = dev_priv->engine[workload->ring_id];
+       struct i915_request *rq;
+       int ret = 0;
+
+       lockdep_assert_held(&dev_priv->drm.struct_mutex);
+
+       if (workload->req)
+               goto out;
+
+       rq = i915_request_alloc(engine, shadow_ctx);
+       if (IS_ERR(rq)) {
+               gvt_vgpu_err("fail to allocate gem request\n");
+               ret = PTR_ERR(rq);
+               goto out;
+       }
+       workload->req = i915_request_get(rq);
+out:
+       return ret;
+}
+
 /**
  * intel_gvt_scan_and_shadow_workload - audit the workload by scanning and
  * shadow it as well, include ringbuffer,wa_ctx and ctx.
@@ -372,12 +402,11 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload)
        struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
        struct intel_engine_cs *engine = dev_priv->engine[workload->ring_id];
        struct intel_context *ce;
-       struct i915_request *rq;
        int ret;
 
        lockdep_assert_held(&dev_priv->drm.struct_mutex);
 
-       if (workload->req)
+       if (workload->shadow)
                return 0;
 
        ret = set_context_ppgtt_from_shadow(workload, shadow_ctx);
@@ -417,22 +446,8 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload)
                        goto err_shadow;
        }
 
-       rq = i915_request_alloc(engine, shadow_ctx);
-       if (IS_ERR(rq)) {
-               gvt_vgpu_err("fail to allocate gem request\n");
-               ret = PTR_ERR(rq);
-               goto err_shadow;
-       }
-       workload->req = i915_request_get(rq);
-
-       ret = populate_shadow_context(workload);
-       if (ret)
-               goto err_req;
-
+       workload->shadow = true;
        return 0;
-err_req:
-       rq = fetch_and_zero(&workload->req);
-       i915_request_put(rq);
 err_shadow:
        release_shadow_wa_ctx(&workload->wa_ctx);
 err_unpin:
@@ -671,23 +686,31 @@ static int dispatch_workload(struct intel_vgpu_workload *workload)
        mutex_lock(&vgpu->vgpu_lock);
        mutex_lock(&dev_priv->drm.struct_mutex);
 
+       ret = intel_gvt_workload_req_alloc(workload);
+       if (ret)
+               goto err_req;
+
        ret = intel_gvt_scan_and_shadow_workload(workload);
        if (ret)
                goto out;
 
-       ret = prepare_workload(workload);
+       ret = populate_shadow_context(workload);
+       if (ret) {
+               release_shadow_wa_ctx(&workload->wa_ctx);
+               goto out;
+       }
 
+       ret = prepare_workload(workload);
 out:
-       if (ret)
-               workload->status = ret;
-
        if (!IS_ERR_OR_NULL(workload->req)) {
                gvt_dbg_sched("ring id %d submit workload to i915 %p\n",
                                ring_id, workload->req);
                i915_request_add(workload->req);
                workload->dispatched = true;
        }
-
+err_req:
+       if (ret)
+               workload->status = ret;
        mutex_unlock(&dev_priv->drm.struct_mutex);
        mutex_unlock(&vgpu->vgpu_lock);
        return ret;
@@ -891,11 +914,6 @@ static void complete_current_workload(struct intel_gvt *gvt, int ring_id)
 
        list_del_init(&workload->list);
 
-       if (!workload->status) {
-               release_shadow_batch_buffer(workload);
-               release_shadow_wa_ctx(&workload->wa_ctx);
-       }
-
        if (workload->status || (vgpu->resetting_eng & ENGINE_MASK(ring_id))) {
                /* if workload->status is not successful means HW GPU
                 * has occurred GPU hang or something wrong with i915/GVT,
@@ -1263,6 +1281,9 @@ void intel_vgpu_destroy_workload(struct intel_vgpu_workload *workload)
 {
        struct intel_vgpu_submission *s = &workload->vgpu->submission;
 
+       release_shadow_batch_buffer(workload);
+       release_shadow_wa_ctx(&workload->wa_ctx);
+
        if (workload->shadow_mm)
                intel_vgpu_mm_put(workload->shadow_mm);
 
index ca5529d..2065cba 100644 (file)
@@ -83,6 +83,7 @@ struct intel_vgpu_workload {
        struct i915_request *req;
        /* if this workload has been dispatched to i915? */
        bool dispatched;
+       bool shadow;      /* if workload has done shadow of guest request */
        int status;
 
        struct intel_vgpu_mm *shadow_mm;
index 38dcee1..40a61ef 100644 (file)
@@ -984,8 +984,8 @@ static int i915_gpu_info_open(struct inode *inode, struct file *file)
        intel_runtime_pm_get(i915);
        gpu = i915_capture_gpu_state(i915);
        intel_runtime_pm_put(i915);
-       if (!gpu)
-               return -ENOMEM;
+       if (IS_ERR(gpu))
+               return PTR_ERR(gpu);
 
        file->private_data = gpu;
        return 0;
@@ -1018,7 +1018,13 @@ i915_error_state_write(struct file *filp,
 
 static int i915_error_state_open(struct inode *inode, struct file *file)
 {
-       file->private_data = i915_first_error_state(inode->i_private);
+       struct i915_gpu_state *error;
+
+       error = i915_first_error_state(inode->i_private);
+       if (IS_ERR(error))
+               return PTR_ERR(error);
+
+       file->private_data  = error;
        return 0;
 }
 
index 216f52b..c882ea9 100644 (file)
@@ -1824,6 +1824,16 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
        return 0;
 }
 
+static inline bool
+__vma_matches(struct vm_area_struct *vma, struct file *filp,
+             unsigned long addr, unsigned long size)
+{
+       if (vma->vm_file != filp)
+               return false;
+
+       return vma->vm_start == addr && (vma->vm_end - vma->vm_start) == size;
+}
+
 /**
  * i915_gem_mmap_ioctl - Maps the contents of an object, returning the address
  *                      it is mapped to.
@@ -1882,7 +1892,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
                        return -EINTR;
                }
                vma = find_vma(mm, addr);
-               if (vma)
+               if (vma && __vma_matches(vma, obj->base.filp, addr, args->size))
                        vma->vm_page_prot =
                                pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
                else
index add1fe7..bd17dd1 100644 (file)
@@ -2075,6 +2075,7 @@ static struct i915_vma *pd_vma_create(struct gen6_hw_ppgtt *ppgtt, int size)
 int gen6_ppgtt_pin(struct i915_hw_ppgtt *base)
 {
        struct gen6_hw_ppgtt *ppgtt = to_gen6_ppgtt(base);
+       int err;
 
        /*
         * Workaround the limited maximum vma->pin_count and the aliasing_ppgtt
@@ -2090,9 +2091,17 @@ int gen6_ppgtt_pin(struct i915_hw_ppgtt *base)
         * allocator works in address space sizes, so it's multiplied by page
         * size. We allocate at the top of the GTT to avoid fragmentation.
         */
-       return i915_vma_pin(ppgtt->vma,
-                           0, GEN6_PD_ALIGN,
-                           PIN_GLOBAL | PIN_HIGH);
+       err = i915_vma_pin(ppgtt->vma,
+                          0, GEN6_PD_ALIGN,
+                          PIN_GLOBAL | PIN_HIGH);
+       if (err)
+               goto unpin;
+
+       return 0;
+
+unpin:
+       ppgtt->pin_count = 0;
+       return err;
 }
 
 void gen6_ppgtt_unpin(struct i915_hw_ppgtt *base)
index 0746512..3f9ce40 100644 (file)
@@ -1907,9 +1907,16 @@ i915_capture_gpu_state(struct drm_i915_private *i915)
 {
        struct i915_gpu_state *error;
 
+       /* Check if GPU capture has been disabled */
+       error = READ_ONCE(i915->gpu_error.first_error);
+       if (IS_ERR(error))
+               return error;
+
        error = kzalloc(sizeof(*error), GFP_ATOMIC);
-       if (!error)
-               return NULL;
+       if (!error) {
+               i915_disable_error_state(i915, -ENOMEM);
+               return ERR_PTR(-ENOMEM);
+       }
 
        kref_init(&error->ref);
        error->i915 = i915;
@@ -1945,11 +1952,8 @@ void i915_capture_error_state(struct drm_i915_private *i915,
                return;
 
        error = i915_capture_gpu_state(i915);
-       if (!error) {
-               DRM_DEBUG_DRIVER("out of memory, not capturing error state\n");
-               i915_disable_error_state(i915, -ENOMEM);
+       if (IS_ERR(error))
                return;
-       }
 
        i915_error_capture_msg(i915, error, engine_mask, error_msg);
        DRM_INFO("%s\n", error->error_msg);
@@ -1987,7 +1991,7 @@ i915_first_error_state(struct drm_i915_private *i915)
 
        spin_lock_irq(&i915->gpu_error.lock);
        error = i915->gpu_error.first_error;
-       if (error)
+       if (!IS_ERR_OR_NULL(error))
                i915_gpu_state_get(error);
        spin_unlock_irq(&i915->gpu_error.lock);
 
@@ -2000,10 +2004,11 @@ void i915_reset_error_state(struct drm_i915_private *i915)
 
        spin_lock_irq(&i915->gpu_error.lock);
        error = i915->gpu_error.first_error;
-       i915->gpu_error.first_error = NULL;
+       if (error != ERR_PTR(-ENODEV)) /* if disabled, always disabled */
+               i915->gpu_error.first_error = NULL;
        spin_unlock_irq(&i915->gpu_error.lock);
 
-       if (!IS_ERR(error))
+       if (!IS_ERR_OR_NULL(error))
                i915_gpu_state_put(error);
 }
 
index d6c8f8f..017fc60 100644 (file)
@@ -594,7 +594,8 @@ static void i915_pmu_enable(struct perf_event *event)
         * Update the bitmask of enabled events and increment
         * the event reference counter.
         */
-       GEM_BUG_ON(bit >= I915_PMU_MASK_BITS);
+       BUILD_BUG_ON(ARRAY_SIZE(i915->pmu.enable_count) != I915_PMU_MASK_BITS);
+       GEM_BUG_ON(bit >= ARRAY_SIZE(i915->pmu.enable_count));
        GEM_BUG_ON(i915->pmu.enable_count[bit] == ~0);
        i915->pmu.enable |= BIT_ULL(bit);
        i915->pmu.enable_count[bit]++;
@@ -615,11 +616,16 @@ static void i915_pmu_enable(struct perf_event *event)
                engine = intel_engine_lookup_user(i915,
                                                  engine_event_class(event),
                                                  engine_event_instance(event));
-               GEM_BUG_ON(!engine);
-               engine->pmu.enable |= BIT(sample);
 
-               GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS);
+               BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.enable_count) !=
+                            I915_ENGINE_SAMPLE_COUNT);
+               BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.sample) !=
+                            I915_ENGINE_SAMPLE_COUNT);
+               GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count));
+               GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample));
                GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0);
+
+               engine->pmu.enable |= BIT(sample);
                engine->pmu.enable_count[sample]++;
        }
 
@@ -649,9 +655,11 @@ static void i915_pmu_disable(struct perf_event *event)
                engine = intel_engine_lookup_user(i915,
                                                  engine_event_class(event),
                                                  engine_event_instance(event));
-               GEM_BUG_ON(!engine);
-               GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS);
+
+               GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count));
+               GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample));
                GEM_BUG_ON(engine->pmu.enable_count[sample] == 0);
+
                /*
                 * Decrement the reference count and clear the enabled
                 * bitmask when the last listener on an event goes away.
@@ -660,7 +668,7 @@ static void i915_pmu_disable(struct perf_event *event)
                        engine->pmu.enable &= ~BIT(sample);
        }
 
-       GEM_BUG_ON(bit >= I915_PMU_MASK_BITS);
+       GEM_BUG_ON(bit >= ARRAY_SIZE(i915->pmu.enable_count));
        GEM_BUG_ON(i915->pmu.enable_count[bit] == 0);
        /*
         * Decrement the reference count and clear the enabled
index 7f164ca..b3728c5 100644 (file)
@@ -31,6 +31,8 @@ enum {
        ((1 << I915_PMU_SAMPLE_BITS) + \
         (I915_PMU_LAST + 1 - __I915_PMU_OTHER(0)))
 
+#define I915_ENGINE_SAMPLE_COUNT (I915_SAMPLE_SEMA + 1)
+
 struct i915_pmu_sample {
        u64 cur;
 };
index 0a7d605..067054c 100644 (file)
@@ -1790,7 +1790,7 @@ enum i915_power_well_id {
 #define _CNL_PORT_TX_C_LN0_OFFSET              0x162C40
 #define _CNL_PORT_TX_D_LN0_OFFSET              0x162E40
 #define _CNL_PORT_TX_F_LN0_OFFSET              0x162840
-#define _CNL_PORT_TX_DW_GRP(port, dw)  (_PICK((port), \
+#define _CNL_PORT_TX_DW_GRP(dw, port)  (_PICK((port), \
                                               _CNL_PORT_TX_AE_GRP_OFFSET, \
                                               _CNL_PORT_TX_B_GRP_OFFSET, \
                                               _CNL_PORT_TX_B_GRP_OFFSET, \
@@ -1798,7 +1798,7 @@ enum i915_power_well_id {
                                               _CNL_PORT_TX_AE_GRP_OFFSET, \
                                               _CNL_PORT_TX_F_GRP_OFFSET) + \
                                               4 * (dw))
-#define _CNL_PORT_TX_DW_LN0(port, dw)  (_PICK((port), \
+#define _CNL_PORT_TX_DW_LN0(dw, port)  (_PICK((port), \
                                               _CNL_PORT_TX_AE_LN0_OFFSET, \
                                               _CNL_PORT_TX_B_LN0_OFFSET, \
                                               _CNL_PORT_TX_B_LN0_OFFSET, \
@@ -1834,9 +1834,9 @@ enum i915_power_well_id {
 
 #define _CNL_PORT_TX_DW4_LN0_AE                0x162450
 #define _CNL_PORT_TX_DW4_LN1_AE                0x1624D0
-#define CNL_PORT_TX_DW4_GRP(port)      _MMIO(_CNL_PORT_TX_DW_GRP((port), 4))
-#define CNL_PORT_TX_DW4_LN0(port)      _MMIO(_CNL_PORT_TX_DW_LN0((port), 4))
-#define CNL_PORT_TX_DW4_LN(port, ln)   _MMIO(_CNL_PORT_TX_DW_LN0((port), 4) + \
+#define CNL_PORT_TX_DW4_GRP(port)      _MMIO(_CNL_PORT_TX_DW_GRP(4, (port)))
+#define CNL_PORT_TX_DW4_LN0(port)      _MMIO(_CNL_PORT_TX_DW_LN0(4, (port)))
+#define CNL_PORT_TX_DW4_LN(port, ln)   _MMIO(_CNL_PORT_TX_DW_LN0(4, (port)) + \
                                           ((ln) * (_CNL_PORT_TX_DW4_LN1_AE - \
                                                    _CNL_PORT_TX_DW4_LN0_AE)))
 #define ICL_PORT_TX_DW4_AUX(port)      _MMIO(_ICL_PORT_TX_DW_AUX(4, port))
@@ -1864,8 +1864,12 @@ enum i915_power_well_id {
 #define   RTERM_SELECT(x)              ((x) << 3)
 #define   RTERM_SELECT_MASK            (0x7 << 3)
 
-#define CNL_PORT_TX_DW7_GRP(port)      _MMIO(_CNL_PORT_TX_DW_GRP((port), 7))
-#define CNL_PORT_TX_DW7_LN0(port)      _MMIO(_CNL_PORT_TX_DW_LN0((port), 7))
+#define CNL_PORT_TX_DW7_GRP(port)      _MMIO(_CNL_PORT_TX_DW_GRP(7, (port)))
+#define CNL_PORT_TX_DW7_LN0(port)      _MMIO(_CNL_PORT_TX_DW_LN0(7, (port)))
+#define ICL_PORT_TX_DW7_AUX(port)      _MMIO(_ICL_PORT_TX_DW_AUX(7, port))
+#define ICL_PORT_TX_DW7_GRP(port)      _MMIO(_ICL_PORT_TX_DW_GRP(7, port))
+#define ICL_PORT_TX_DW7_LN0(port)      _MMIO(_ICL_PORT_TX_DW_LN(7, 0, port))
+#define ICL_PORT_TX_DW7_LN(port, ln)   _MMIO(_ICL_PORT_TX_DW_LN(7, ln, port))
 #define   N_SCALAR(x)                  ((x) << 24)
 #define   N_SCALAR_MASK                        (0x7F << 24)
 
index 535caeb..c0cfe7a 100644 (file)
@@ -521,7 +521,9 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
        ssize_t ret;
 
        gpu = i915_first_error_state(i915);
-       if (gpu) {
+       if (IS_ERR(gpu)) {
+               ret = PTR_ERR(gpu);
+       } else if (gpu) {
                ret = i915_gpu_state_copy_to_buffer(gpu, buf, off, count);
                i915_gpu_state_put(gpu);
        } else {
index f3e1d6a..7edce1b 100644 (file)
@@ -494,103 +494,58 @@ static const struct cnl_ddi_buf_trans cnl_ddi_translations_edp_1_05V[] = {
        { 0x2, 0x7F, 0x3F, 0x00, 0x00 },        /* 400   400      0.0   */
 };
 
-struct icl_combo_phy_ddi_buf_trans {
-       u32 dw2_swing_select;
-       u32 dw2_swing_scalar;
-       u32 dw4_scaling;
-};
-
-/* Voltage Swing Programming for VccIO 0.85V for DP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_0_85V[] = {
-                               /* Voltage mV  db    */
-       { 0x2, 0x98, 0x0018 },  /* 400         0.0   */
-       { 0x2, 0x98, 0x3015 },  /* 400         3.5   */
-       { 0x2, 0x98, 0x6012 },  /* 400         6.0   */
-       { 0x2, 0x98, 0x900F },  /* 400         9.5   */
-       { 0xB, 0x70, 0x0018 },  /* 600         0.0   */
-       { 0xB, 0x70, 0x3015 },  /* 600         3.5   */
-       { 0xB, 0x70, 0x6012 },  /* 600         6.0   */
-       { 0x5, 0x00, 0x0018 },  /* 800         0.0   */
-       { 0x5, 0x00, 0x3015 },  /* 800         3.5   */
-       { 0x6, 0x98, 0x0018 },  /* 1200        0.0   */
-};
-
-/* FIXME - After table is updated in Bspec */
-/* Voltage Swing Programming for VccIO 0.85V for eDP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_0_85V[] = {
-                               /* Voltage mV  db    */
-       { 0x0, 0x00, 0x00 },    /* 200         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 200         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         6.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 250         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 350         0.0   */
-};
-
-/* Voltage Swing Programming for VccIO 0.95V for DP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_0_95V[] = {
-                               /* Voltage mV  db    */
-       { 0x2, 0x98, 0x0018 },  /* 400         0.0   */
-       { 0x2, 0x98, 0x3015 },  /* 400         3.5   */
-       { 0x2, 0x98, 0x6012 },  /* 400         6.0   */
-       { 0x2, 0x98, 0x900F },  /* 400         9.5   */
-       { 0x4, 0x98, 0x0018 },  /* 600         0.0   */
-       { 0x4, 0x98, 0x3015 },  /* 600         3.5   */
-       { 0x4, 0x98, 0x6012 },  /* 600         6.0   */
-       { 0x5, 0x76, 0x0018 },  /* 800         0.0   */
-       { 0x5, 0x76, 0x3015 },  /* 800         3.5   */
-       { 0x6, 0x98, 0x0018 },  /* 1200        0.0   */
+/* icl_combo_phy_ddi_translations */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hbr2[] = {
+                                               /* NT mV Trans mV db    */
+       { 0xA, 0x35, 0x3F, 0x00, 0x00 },        /* 350   350      0.0   */
+       { 0xA, 0x4F, 0x37, 0x00, 0x08 },        /* 350   500      3.1   */
+       { 0xC, 0x71, 0x2F, 0x00, 0x10 },        /* 350   700      6.0   */
+       { 0x6, 0x7F, 0x2B, 0x00, 0x14 },        /* 350   900      8.2   */
+       { 0xA, 0x4C, 0x3F, 0x00, 0x00 },        /* 500   500      0.0   */
+       { 0xC, 0x73, 0x34, 0x00, 0x0B },        /* 500   700      2.9   */
+       { 0x6, 0x7F, 0x2F, 0x00, 0x10 },        /* 500   900      5.1   */
+       { 0xC, 0x6C, 0x3C, 0x00, 0x03 },        /* 650   700      0.6   */
+       { 0x6, 0x7F, 0x35, 0x00, 0x0A },        /* 600   900      3.5   */
+       { 0x6, 0x7F, 0x3F, 0x00, 0x00 },        /* 900   900      0.0   */
 };
 
-/* FIXME - After table is updated in Bspec */
-/* Voltage Swing Programming for VccIO 0.95V for eDP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_0_95V[] = {
-                               /* Voltage mV  db    */
-       { 0x0, 0x00, 0x00 },    /* 200         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 200         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         6.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 250         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 350         0.0   */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_edp_hbr2[] = {
+                                               /* NT mV Trans mV db    */
+       { 0x0, 0x7F, 0x3F, 0x00, 0x00 },        /* 200   200      0.0   */
+       { 0x8, 0x7F, 0x38, 0x00, 0x07 },        /* 200   250      1.9   */
+       { 0x1, 0x7F, 0x33, 0x00, 0x0C },        /* 200   300      3.5   */
+       { 0x9, 0x7F, 0x31, 0x00, 0x0E },        /* 200   350      4.9   */
+       { 0x8, 0x7F, 0x3F, 0x00, 0x00 },        /* 250   250      0.0   */
+       { 0x1, 0x7F, 0x38, 0x00, 0x07 },        /* 250   300      1.6   */
+       { 0x9, 0x7F, 0x35, 0x00, 0x0A },        /* 250   350      2.9   */
+       { 0x1, 0x7F, 0x3F, 0x00, 0x00 },        /* 300   300      0.0   */
+       { 0x9, 0x7F, 0x38, 0x00, 0x07 },        /* 300   350      1.3   */
+       { 0x9, 0x7F, 0x3F, 0x00, 0x00 },        /* 350   350      0.0   */
 };
 
-/* Voltage Swing Programming for VccIO 1.05V for DP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_1_05V[] = {
-                               /* Voltage mV  db    */
-       { 0x2, 0x98, 0x0018 },  /* 400         0.0   */
-       { 0x2, 0x98, 0x3015 },  /* 400         3.5   */
-       { 0x2, 0x98, 0x6012 },  /* 400         6.0   */
-       { 0x2, 0x98, 0x900F },  /* 400         9.5   */
-       { 0x4, 0x98, 0x0018 },  /* 600         0.0   */
-       { 0x4, 0x98, 0x3015 },  /* 600         3.5   */
-       { 0x4, 0x98, 0x6012 },  /* 600         6.0   */
-       { 0x5, 0x71, 0x0018 },  /* 800         0.0   */
-       { 0x5, 0x71, 0x3015 },  /* 800         3.5   */
-       { 0x6, 0x98, 0x0018 },  /* 1200        0.0   */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_edp_hbr3[] = {
+                                               /* NT mV Trans mV db    */
+       { 0xA, 0x35, 0x3F, 0x00, 0x00 },        /* 350   350      0.0   */
+       { 0xA, 0x4F, 0x37, 0x00, 0x08 },        /* 350   500      3.1   */
+       { 0xC, 0x71, 0x2F, 0x00, 0x10 },        /* 350   700      6.0   */
+       { 0x6, 0x7F, 0x2B, 0x00, 0x14 },        /* 350   900      8.2   */
+       { 0xA, 0x4C, 0x3F, 0x00, 0x00 },        /* 500   500      0.0   */
+       { 0xC, 0x73, 0x34, 0x00, 0x0B },        /* 500   700      2.9   */
+       { 0x6, 0x7F, 0x2F, 0x00, 0x10 },        /* 500   900      5.1   */
+       { 0xC, 0x6C, 0x3C, 0x00, 0x03 },        /* 650   700      0.6   */
+       { 0x6, 0x7F, 0x35, 0x00, 0x0A },        /* 600   900      3.5   */
+       { 0x6, 0x7F, 0x3F, 0x00, 0x00 },        /* 900   900      0.0   */
 };
 
-/* FIXME - After table is updated in Bspec */
-/* Voltage Swing Programming for VccIO 1.05V for eDP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_1_05V[] = {
-                               /* Voltage mV  db    */
-       { 0x0, 0x00, 0x00 },    /* 200         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 200         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         6.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 250         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 350         0.0   */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_hdmi[] = {
+                                               /* NT mV Trans mV db    */
+       { 0xA, 0x60, 0x3F, 0x00, 0x00 },        /* 450   450      0.0   */
+       { 0xB, 0x73, 0x36, 0x00, 0x09 },        /* 450   650      3.2   */
+       { 0x6, 0x7F, 0x31, 0x00, 0x0E },        /* 450   850      5.5   */
+       { 0xB, 0x73, 0x3F, 0x00, 0x00 },        /* 650   650      0.0   ALS */
+       { 0x6, 0x7F, 0x37, 0x00, 0x08 },        /* 650   850      2.3   */
+       { 0x6, 0x7F, 0x3F, 0x00, 0x00 },        /* 850   850      0.0   */
+       { 0x6, 0x7F, 0x35, 0x00, 0x0A },        /* 600   850      3.0   */
 };
 
 struct icl_mg_phy_ddi_buf_trans {
@@ -871,43 +826,23 @@ cnl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)
        }
 }
 
-static const struct icl_combo_phy_ddi_buf_trans *
+static const struct cnl_ddi_buf_trans *
 icl_get_combo_buf_trans(struct drm_i915_private *dev_priv, enum port port,
-                       int type, int *n_entries)
+                       int type, int rate, int *n_entries)
 {
-       u32 voltage = I915_READ(ICL_PORT_COMP_DW3(port)) & VOLTAGE_INFO_MASK;
-
-       if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) {
-               switch (voltage) {
-               case VOLTAGE_INFO_0_85V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_85V);
-                       return icl_combo_phy_ddi_translations_edp_0_85V;
-               case VOLTAGE_INFO_0_95V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_95V);
-                       return icl_combo_phy_ddi_translations_edp_0_95V;
-               case VOLTAGE_INFO_1_05V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_1_05V);
-                       return icl_combo_phy_ddi_translations_edp_1_05V;
-               default:
-                       MISSING_CASE(voltage);
-                       return NULL;
-               }
-       } else {
-               switch (voltage) {
-               case VOLTAGE_INFO_0_85V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_85V);
-                       return icl_combo_phy_ddi_translations_dp_hdmi_0_85V;
-               case VOLTAGE_INFO_0_95V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_95V);
-                       return icl_combo_phy_ddi_translations_dp_hdmi_0_95V;
-               case VOLTAGE_INFO_1_05V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_1_05V);
-                       return icl_combo_phy_ddi_translations_dp_hdmi_1_05V;
-               default:
-                       MISSING_CASE(voltage);
-                       return NULL;
-               }
+       if (type == INTEL_OUTPUT_HDMI) {
+               *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_hdmi);
+               return icl_combo_phy_ddi_translations_hdmi;
+       } else if (rate > 540000 && type == INTEL_OUTPUT_EDP) {
+               *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr3);
+               return icl_combo_phy_ddi_translations_edp_hbr3;
+       } else if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) {
+               *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr2);
+               return icl_combo_phy_ddi_translations_edp_hbr2;
        }
+
+       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hbr2);
+       return icl_combo_phy_ddi_translations_dp_hbr2;
 }
 
 static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port port)
@@ -918,8 +853,8 @@ static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port por
 
        if (IS_ICELAKE(dev_priv)) {
                if (intel_port_is_combophy(dev_priv, port))
-                       icl_get_combo_buf_trans(dev_priv, port,
-                                               INTEL_OUTPUT_HDMI, &n_entries);
+                       icl_get_combo_buf_trans(dev_priv, port, INTEL_OUTPUT_HDMI,
+                                               0, &n_entries);
                else
                        n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations);
                default_entry = n_entries - 1;
@@ -1086,7 +1021,7 @@ static uint32_t icl_pll_to_ddi_pll_sel(struct intel_encoder *encoder,
                        return DDI_CLK_SEL_TBT_810;
                default:
                        MISSING_CASE(clock);
-                       break;
+                       return DDI_CLK_SEL_NONE;
                }
        case DPLL_ID_ICL_MGPLL1:
        case DPLL_ID_ICL_MGPLL2:
@@ -2275,13 +2210,14 @@ static void bxt_ddi_vswing_sequence(struct intel_encoder *encoder,
 u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+       struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
        enum port port = encoder->port;
        int n_entries;
 
        if (IS_ICELAKE(dev_priv)) {
                if (intel_port_is_combophy(dev_priv, port))
                        icl_get_combo_buf_trans(dev_priv, port, encoder->type,
-                                               &n_entries);
+                                               intel_dp->link_rate, &n_entries);
                else
                        n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations);
        } else if (IS_CANNONLAKE(dev_priv)) {
@@ -2462,14 +2398,15 @@ static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder,
 }
 
 static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
-                                        u32 level, enum port port, int type)
+                                       u32 level, enum port port, int type,
+                                       int rate)
 {
-       const struct icl_combo_phy_ddi_buf_trans *ddi_translations = NULL;
+       const struct cnl_ddi_buf_trans *ddi_translations = NULL;
        u32 n_entries, val;
        int ln;
 
        ddi_translations = icl_get_combo_buf_trans(dev_priv, port, type,
-                                                  &n_entries);
+                                                  rate, &n_entries);
        if (!ddi_translations)
                return;
 
@@ -2478,34 +2415,23 @@ static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
                level = n_entries - 1;
        }
 
-       /* Set PORT_TX_DW5 Rterm Sel to 110b. */
+       /* Set PORT_TX_DW5 */
        val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
-       val &= ~RTERM_SELECT_MASK;
+       val &= ~(SCALING_MODE_SEL_MASK | RTERM_SELECT_MASK |
+                 TAP2_DISABLE | TAP3_DISABLE);
+       val |= SCALING_MODE_SEL(0x2);
        val |= RTERM_SELECT(0x6);
-       I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
-
-       /* Program PORT_TX_DW5 */
-       val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
-       /* Set DisableTap2 and DisableTap3 if MIPI DSI
-        * Clear DisableTap2 and DisableTap3 for all other Ports
-        */
-       if (type == INTEL_OUTPUT_DSI) {
-               val |= TAP2_DISABLE;
-               val |= TAP3_DISABLE;
-       } else {
-               val &= ~TAP2_DISABLE;
-               val &= ~TAP3_DISABLE;
-       }
+       val |= TAP3_DISABLE;
        I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
 
        /* Program PORT_TX_DW2 */
        val = I915_READ(ICL_PORT_TX_DW2_LN0(port));
        val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK |
                 RCOMP_SCALAR_MASK);
-       val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_select);
-       val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_select);
+       val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_sel);
+       val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_sel);
        /* Program Rcomp scalar for every table entry */
-       val |= RCOMP_SCALAR(ddi_translations[level].dw2_swing_scalar);
+       val |= RCOMP_SCALAR(0x98);
        I915_WRITE(ICL_PORT_TX_DW2_GRP(port), val);
 
        /* Program PORT_TX_DW4 */
@@ -2514,9 +2440,17 @@ static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
                val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
                val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK |
                         CURSOR_COEFF_MASK);
-               val |= ddi_translations[level].dw4_scaling;
+               val |= POST_CURSOR_1(ddi_translations[level].dw4_post_cursor_1);
+               val |= POST_CURSOR_2(ddi_translations[level].dw4_post_cursor_2);
+               val |= CURSOR_COEFF(ddi_translations[level].dw4_cursor_coeff);
                I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val);
        }
+
+       /* Program PORT_TX_DW7 */
+       val = I915_READ(ICL_PORT_TX_DW7_LN0(port));
+       val &= ~N_SCALAR_MASK;
+       val |= N_SCALAR(ddi_translations[level].dw7_n_scalar);
+       I915_WRITE(ICL_PORT_TX_DW7_GRP(port), val);
 }
 
 static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
@@ -2581,7 +2515,7 @@ static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
        I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
 
        /* 5. Program swing and de-emphasis */
-       icl_ddi_combo_vswing_program(dev_priv, level, port, type);
+       icl_ddi_combo_vswing_program(dev_priv, level, port, type, rate);
 
        /* 6. Set training enable to trigger update */
        val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
index 3da9c0f..2481281 100644 (file)
@@ -15415,16 +15415,45 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
        }
 }
 
+static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+
+       /*
+        * Some SNB BIOSen (eg. ASUS K53SV) are known to misprogram
+        * the hardware when a high res displays plugged in. DPLL P
+        * divider is zero, and the pipe timings are bonkers. We'll
+        * try to disable everything in that case.
+        *
+        * FIXME would be nice to be able to sanitize this state
+        * without several WARNs, but for now let's take the easy
+        * road.
+        */
+       return IS_GEN6(dev_priv) &&
+               crtc_state->base.active &&
+               crtc_state->shared_dpll &&
+               crtc_state->port_clock == 0;
+}
+
 static void intel_sanitize_encoder(struct intel_encoder *encoder)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_connector *connector;
+       struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+       struct intel_crtc_state *crtc_state = crtc ?
+               to_intel_crtc_state(crtc->base.state) : NULL;
 
        /* We need to check both for a crtc link (meaning that the
         * encoder is active and trying to read from a pipe) and the
         * pipe itself being active. */
-       bool has_active_crtc = encoder->base.crtc &&
-               to_intel_crtc(encoder->base.crtc)->active;
+       bool has_active_crtc = crtc_state &&
+               crtc_state->base.active;
+
+       if (crtc_state && has_bogus_dpll_config(crtc_state)) {
+               DRM_DEBUG_KMS("BIOS has misprogrammed the hardware. Disabling pipe %c\n",
+                             pipe_name(crtc->pipe));
+               has_active_crtc = false;
+       }
 
        connector = intel_encoder_find_connector(encoder);
        if (connector && !has_active_crtc) {
@@ -15435,16 +15464,25 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
                /* Connector is active, but has no active pipe. This is
                 * fallout from our resume register restoring. Disable
                 * the encoder manually again. */
-               if (encoder->base.crtc) {
-                       struct drm_crtc_state *crtc_state = encoder->base.crtc->state;
+               if (crtc_state) {
+                       struct drm_encoder *best_encoder;
 
                        DRM_DEBUG_KMS("[ENCODER:%d:%s] manually disabled\n",
                                      encoder->base.base.id,
                                      encoder->base.name);
+
+                       /* avoid oopsing in case the hooks consult best_encoder */
+                       best_encoder = connector->base.state->best_encoder;
+                       connector->base.state->best_encoder = &encoder->base;
+
                        if (encoder->disable)
-                               encoder->disable(encoder, to_intel_crtc_state(crtc_state), connector->base.state);
+                               encoder->disable(encoder, crtc_state,
+                                                connector->base.state);
                        if (encoder->post_disable)
-                               encoder->post_disable(encoder, to_intel_crtc_state(crtc_state), connector->base.state);
+                               encoder->post_disable(encoder, crtc_state,
+                                                     connector->base.state);
+
+                       connector->base.state->best_encoder = best_encoder;
                }
                encoder->base.crtc = NULL;
 
index fdd2cbc..22a7460 100644 (file)
@@ -304,9 +304,11 @@ static int cnl_max_source_rate(struct intel_dp *intel_dp)
 static int icl_max_source_rate(struct intel_dp *intel_dp)
 {
        struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+       struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
        enum port port = dig_port->base.port;
 
-       if (port == PORT_B)
+       if (intel_port_is_combophy(dev_priv, port) &&
+           !intel_dp_is_edp(intel_dp))
                return 540000;
 
        return 810000;
index f94a04b..e9ddeaf 100644 (file)
@@ -209,6 +209,16 @@ struct intel_fbdev {
        unsigned long vma_flags;
        async_cookie_t cookie;
        int preferred_bpp;
+
+       /* Whether or not fbdev hpd processing is temporarily suspended */
+       bool hpd_suspended : 1;
+       /* Set when a hotplug was received while HPD processing was
+        * suspended
+        */
+       bool hpd_waiting : 1;
+
+       /* Protects hpd_suspended */
+       struct mutex hpd_lock;
 };
 
 struct intel_encoder {
index fb5bb5b..7f365ac 100644 (file)
@@ -679,6 +679,7 @@ int intel_fbdev_init(struct drm_device *dev)
        if (ifbdev == NULL)
                return -ENOMEM;
 
+       mutex_init(&ifbdev->hpd_lock);
        drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);
 
        if (!intel_fbdev_init_bios(dev, ifbdev))
@@ -752,6 +753,26 @@ void intel_fbdev_fini(struct drm_i915_private *dev_priv)
        intel_fbdev_destroy(ifbdev);
 }
 
+/* Suspends/resumes fbdev processing of incoming HPD events. When resuming HPD
+ * processing, fbdev will perform a full connector reprobe if a hotplug event
+ * was received while HPD was suspended.
+ */
+static void intel_fbdev_hpd_set_suspend(struct intel_fbdev *ifbdev, int state)
+{
+       bool send_hpd = false;
+
+       mutex_lock(&ifbdev->hpd_lock);
+       ifbdev->hpd_suspended = state == FBINFO_STATE_SUSPENDED;
+       send_hpd = !ifbdev->hpd_suspended && ifbdev->hpd_waiting;
+       ifbdev->hpd_waiting = false;
+       mutex_unlock(&ifbdev->hpd_lock);
+
+       if (send_hpd) {
+               DRM_DEBUG_KMS("Handling delayed fbcon HPD event\n");
+               drm_fb_helper_hotplug_event(&ifbdev->helper);
+       }
+}
+
 void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -773,6 +794,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
                 */
                if (state != FBINFO_STATE_RUNNING)
                        flush_work(&dev_priv->fbdev_suspend_work);
+
                console_lock();
        } else {
                /*
@@ -800,17 +822,26 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
 
        drm_fb_helper_set_suspend(&ifbdev->helper, state);
        console_unlock();
+
+       intel_fbdev_hpd_set_suspend(ifbdev, state);
 }
 
 void intel_fbdev_output_poll_changed(struct drm_device *dev)
 {
        struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
+       bool send_hpd;
 
        if (!ifbdev)
                return;
 
        intel_fbdev_sync(ifbdev);
-       if (ifbdev->vma || ifbdev->helper.deferred_setup)
+
+       mutex_lock(&ifbdev->hpd_lock);
+       send_hpd = !ifbdev->hpd_suspended;
+       ifbdev->hpd_waiting = true;
+       mutex_unlock(&ifbdev->hpd_lock);
+
+       if (send_hpd && (ifbdev->vma || ifbdev->helper.deferred_setup))
                drm_fb_helper_hotplug_event(&ifbdev->helper);
 }
 
index 4be167d..eab9341 100644 (file)
@@ -303,6 +303,7 @@ static void __unwind_incomplete_requests(struct intel_engine_cs *engine)
         */
        if (!(prio & I915_PRIORITY_NEWCLIENT)) {
                prio |= I915_PRIORITY_NEWCLIENT;
+               active->sched.attr.priority = prio;
                list_move_tail(&active->sched.link,
                               i915_sched_lookup_priolist(engine, prio));
        }
@@ -645,6 +646,9 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
                int i;
 
                priolist_for_each_request_consume(rq, rn, p, i) {
+                       GEM_BUG_ON(last &&
+                                  need_preempt(engine, last, rq_prio(rq)));
+
                        /*
                         * Can we combine this request with the current port?
                         * It has to be the same context/ringbuffer and not
@@ -2244,6 +2248,8 @@ static int logical_ring_init(struct intel_engine_cs *engine)
        if (ret)
                return ret;
 
+       intel_engine_init_workarounds(engine);
+
        if (HAS_LOGICAL_RING_ELSQ(i915)) {
                execlists->submit_reg = i915->regs +
                        i915_mmio_reg_offset(RING_EXECLIST_SQ_CONTENTS(engine));
@@ -2310,7 +2316,6 @@ int logical_render_ring_init(struct intel_engine_cs *engine)
        }
 
        intel_engine_init_whitelist(engine);
-       intel_engine_init_workarounds(engine);
 
        return 0;
 }
index b8f106d..3ac2015 100644 (file)
 struct opregion_header {
        u8 signature[16];
        u32 size;
-       u32 opregion_ver;
+       struct {
+               u8 rsvd;
+               u8 revision;
+               u8 minor;
+               u8 major;
+       }  __packed over;
        u8 bios_ver[32];
        u8 vbios_ver[16];
        u8 driver_ver[16];
@@ -119,7 +124,8 @@ struct opregion_asle {
        u64 fdss;
        u32 fdsp;
        u32 stat;
-       u64 rvda;       /* Physical address of raw vbt data */
+       u64 rvda;       /* Physical (2.0) or relative from opregion (2.1+)
+                        * address of raw VBT data. */
        u32 rvds;       /* Size of raw vbt data */
        u8 rsvd[58];
 } __packed;
@@ -925,6 +931,11 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
        opregion->header = base;
        opregion->lid_state = base + ACPI_CLID;
 
+       DRM_DEBUG_DRIVER("ACPI OpRegion version %u.%u.%u\n",
+                        opregion->header->over.major,
+                        opregion->header->over.minor,
+                        opregion->header->over.revision);
+
        mboxes = opregion->header->mboxes;
        if (mboxes & MBOX_ACPI) {
                DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
@@ -953,11 +964,26 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
        if (dmi_check_system(intel_no_opregion_vbt))
                goto out;
 
-       if (opregion->header->opregion_ver >= 2 && opregion->asle &&
+       if (opregion->header->over.major >= 2 && opregion->asle &&
            opregion->asle->rvda && opregion->asle->rvds) {
-               opregion->rvda = memremap(opregion->asle->rvda,
-                                         opregion->asle->rvds,
+               resource_size_t rvda = opregion->asle->rvda;
+
+               /*
+                * opregion 2.0: rvda is the physical VBT address.
+                *
+                * opregion 2.1+: rvda is unsigned, relative offset from
+                * opregion base, and should never point within opregion.
+                */
+               if (opregion->header->over.major > 2 ||
+                   opregion->header->over.minor >= 1) {
+                       WARN_ON(rvda < OPREGION_SIZE);
+
+                       rvda += asls;
+               }
+
+               opregion->rvda = memremap(rvda, opregion->asle->rvds,
                                          MEMREMAP_WB);
+
                vbt = opregion->rvda;
                vbt_size = opregion->asle->rvds;
                if (intel_bios_is_valid_vbt(vbt, vbt_size)) {
@@ -967,6 +993,8 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
                        goto out;
                } else {
                        DRM_DEBUG_KMS("Invalid VBT in ACPI OpRegion (RVDA)\n");
+                       memunmap(opregion->rvda);
+                       opregion->rvda = NULL;
                }
        }
 
index 419e563..f71970d 100644 (file)
@@ -274,10 +274,16 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
        DRM_DEBUG_KMS("eDP panel supports PSR version %x\n",
                      intel_dp->psr_dpcd[0]);
 
+       if (drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_NO_PSR)) {
+               DRM_DEBUG_KMS("PSR support not currently available for this panel\n");
+               return;
+       }
+
        if (!(intel_dp->edp_dpcd[1] & DP_EDP_SET_POWER_CAP)) {
                DRM_DEBUG_KMS("Panel lacks power state control, PSR cannot be enabled\n");
                return;
        }
+
        dev_priv->psr.sink_support = true;
        dev_priv->psr.sink_sync_latency =
                intel_dp_get_sink_sync_latency(intel_dp);
index 72edaa7..a1a7cc2 100644 (file)
@@ -415,16 +415,17 @@ struct intel_engine_cs {
                /**
                 * @enable_count: Reference count for the enabled samplers.
                 *
-                * Index number corresponds to the bit number from @enable.
+                * Index number corresponds to @enum drm_i915_pmu_engine_sample.
                 */
-               unsigned int enable_count[I915_PMU_SAMPLE_BITS];
+               unsigned int enable_count[I915_ENGINE_SAMPLE_COUNT];
                /**
                 * @sample: Counter values for sampling events.
                 *
                 * Our internal timer stores the current counters in this field.
+                *
+                * Index number corresponds to @enum drm_i915_pmu_engine_sample.
                 */
-#define I915_ENGINE_SAMPLE_MAX (I915_SAMPLE_SEMA + 1)
-               struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX];
+               struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_COUNT];
        } pmu;
 
        /*
index d2e003d..5170a0f 100644 (file)
@@ -494,7 +494,7 @@ skl_program_plane(struct intel_plane *plane,
 
        keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
 
-       keymsk = key->channel_mask & 0x3ffffff;
+       keymsk = key->channel_mask & 0x7ffffff;
        if (alpha < 0xff)
                keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
 
index 2c5bbe3..e31e263 100644 (file)
@@ -643,8 +643,10 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
                int bus_format;
 
                ret = of_property_read_u32(child, "reg", &i);
-               if (ret || i < 0 || i > 1)
-                       return -EINVAL;
+               if (ret || i < 0 || i > 1) {
+                       ret = -EINVAL;
+                       goto free_child;
+               }
 
                if (!of_device_is_available(child))
                        continue;
@@ -657,7 +659,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
                channel = &imx_ldb->channel[i];
                channel->ldb = imx_ldb;
                channel->chno = i;
-               channel->child = child;
 
                /*
                 * The output port is port@4 with an external 4-port mux or
@@ -667,13 +668,13 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
                                                  imx_ldb->lvds_mux ? 4 : 2, 0,
                                                  &channel->panel, &channel->bridge);
                if (ret && ret != -ENODEV)
-                       return ret;
+                       goto free_child;
 
                /* panel ddc only if there is no bridge */
                if (!channel->bridge) {
                        ret = imx_ldb_panel_ddc(dev, channel, child);
                        if (ret)
-                               return ret;
+                               goto free_child;
                }
 
                bus_format = of_get_bus_format(dev, child);
@@ -689,18 +690,26 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
                if (bus_format < 0) {
                        dev_err(dev, "could not determine data mapping: %d\n",
                                bus_format);
-                       return bus_format;
+                       ret = bus_format;
+                       goto free_child;
                }
                channel->bus_format = bus_format;
+               channel->child = child;
 
                ret = imx_ldb_register(drm, channel);
-               if (ret)
-                       return ret;
+               if (ret) {
+                       channel->child = NULL;
+                       goto free_child;
+               }
        }
 
        dev_set_drvdata(dev, imx_ldb);
 
        return 0;
+
+free_child:
+       of_node_put(child);
+       return ret;
 }
 
 static void imx_ldb_unbind(struct device *dev, struct device *master,
index c390924..21e964f 100644 (file)
@@ -370,9 +370,9 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
        if (ret)
                return ret;
 
-       /* CRTC should be enabled */
+       /* nothing to check when disabling or disabled */
        if (!crtc_state->enable)
-               return -EINVAL;
+               return 0;
 
        switch (plane->type) {
        case DRM_PLANE_TYPE_PRIMARY:
index 75d97f1..4f5c67f 100644 (file)
@@ -46,7 +46,6 @@ struct meson_crtc {
        struct drm_crtc base;
        struct drm_pending_vblank_event *event;
        struct meson_drm *priv;
-       bool enabled;
 };
 #define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
 
@@ -82,7 +81,8 @@ static const struct drm_crtc_funcs meson_crtc_funcs = {
 
 };
 
-static void meson_crtc_enable(struct drm_crtc *crtc)
+static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
+                                    struct drm_crtc_state *old_state)
 {
        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
        struct drm_crtc_state *crtc_state = crtc->state;
@@ -108,20 +108,6 @@ static void meson_crtc_enable(struct drm_crtc *crtc)
 
        drm_crtc_vblank_on(crtc);
 
-       meson_crtc->enabled = true;
-}
-
-static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
-                                    struct drm_crtc_state *old_state)
-{
-       struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
-       struct meson_drm *priv = meson_crtc->priv;
-
-       DRM_DEBUG_DRIVER("\n");
-
-       if (!meson_crtc->enabled)
-               meson_crtc_enable(crtc);
-
        priv->viu.osd1_enabled = true;
 }
 
@@ -153,8 +139,6 @@ static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
 
                crtc->state->event = NULL;
        }
-
-       meson_crtc->enabled = false;
 }
 
 static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -163,9 +147,6 @@ static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
        unsigned long flags;
 
-       if (crtc->state->enable && !meson_crtc->enabled)
-               meson_crtc_enable(crtc);
-
        if (crtc->state->event) {
                WARN_ON(drm_crtc_vblank_get(crtc) != 0);
 
index 3ee4d4a..12ff47b 100644 (file)
@@ -75,6 +75,10 @@ static const struct drm_mode_config_funcs meson_mode_config_funcs = {
        .fb_create           = drm_gem_fb_create,
 };
 
+static const struct drm_mode_config_helper_funcs meson_mode_config_helpers = {
+       .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
+};
+
 static irqreturn_t meson_irq(int irq, void *arg)
 {
        struct drm_device *dev = arg;
@@ -266,6 +270,7 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
        drm->mode_config.max_width = 3840;
        drm->mode_config.max_height = 2160;
        drm->mode_config.funcs = &meson_mode_config_funcs;
+       drm->mode_config.helper_private = &meson_mode_config_helpers;
 
        /* Hardware Initialization */
 
@@ -388,8 +393,10 @@ static int meson_probe_remote(struct platform_device *pdev,
                remote_node = of_graph_get_remote_port_parent(ep);
                if (!remote_node ||
                    remote_node == parent || /* Ignore parent endpoint */
-                   !of_device_is_available(remote_node))
+                   !of_device_is_available(remote_node)) {
+                       of_node_put(remote_node);
                        continue;
+               }
 
                count += meson_probe_remote(pdev, match, remote, remote_node);
 
@@ -408,10 +415,13 @@ static int meson_drv_probe(struct platform_device *pdev)
 
        for_each_endpoint_of_node(np, ep) {
                remote = of_graph_get_remote_port_parent(ep);
-               if (!remote || !of_device_is_available(remote))
+               if (!remote || !of_device_is_available(remote)) {
+                       of_node_put(remote);
                        continue;
+               }
 
                count += meson_probe_remote(pdev, &match, np, remote);
+               of_node_put(remote);
        }
 
        if (count && !match)
index 5beb83d..ce1b3cc 100644 (file)
@@ -944,7 +944,7 @@ static u32 a6xx_gmu_get_arc_level(struct device *dev, unsigned long freq)
        np = dev_pm_opp_get_of_node(opp);
 
        if (np) {
-               of_property_read_u32(np, "qcom,level", &val);
+               of_property_read_u32(np, "opp-level", &val);
                of_node_put(np);
        }
 
index 2e4372e..2cfee1a 100644 (file)
@@ -765,7 +765,6 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
        adreno_gpu->rev = config->rev;
 
        adreno_gpu_config.ioname = "kgsl_3d0_reg_memory";
-       adreno_gpu_config.irqname = "kgsl_3d0_irq";
 
        adreno_gpu_config.va_start = SZ_16M;
        adreno_gpu_config.va_end = 0xffffffff;
index fd75870..6aefcd6 100644 (file)
@@ -365,19 +365,6 @@ static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane,
                        &pdpu->pipe_qos_cfg);
 }
 
-static void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
-{
-       struct dpu_plane *pdpu = to_dpu_plane(plane);
-       struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
-
-       if (!pdpu->is_rt_pipe)
-               return;
-
-       pm_runtime_get_sync(&dpu_kms->pdev->dev);
-       _dpu_plane_set_qos_ctrl(plane, enable, DPU_PLANE_QOS_PANIC_CTRL);
-       pm_runtime_put_sync(&dpu_kms->pdev->dev);
-}
-
 /**
  * _dpu_plane_set_ot_limit - set OT limit for the given plane
  * @plane:             Pointer to drm plane
@@ -1248,6 +1235,19 @@ static void dpu_plane_reset(struct drm_plane *plane)
 }
 
 #ifdef CONFIG_DEBUG_FS
+static void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
+{
+       struct dpu_plane *pdpu = to_dpu_plane(plane);
+       struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
+
+       if (!pdpu->is_rt_pipe)
+               return;
+
+       pm_runtime_get_sync(&dpu_kms->pdev->dev);
+       _dpu_plane_set_qos_ctrl(plane, enable, DPU_PLANE_QOS_PANIC_CTRL);
+       pm_runtime_put_sync(&dpu_kms->pdev->dev);
+}
+
 static ssize_t _dpu_plane_danger_read(struct file *file,
                        char __user *buff, size_t count, loff_t *ppos)
 {
index 9cd6a96..927e5d8 100644 (file)
@@ -250,7 +250,8 @@ void msm_gem_purge_vma(struct msm_gem_address_space *aspace,
 void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
                struct msm_gem_vma *vma);
 int msm_gem_map_vma(struct msm_gem_address_space *aspace,
-               struct msm_gem_vma *vma, struct sg_table *sgt, int npages);
+               struct msm_gem_vma *vma, int prot,
+               struct sg_table *sgt, int npages);
 void msm_gem_close_vma(struct msm_gem_address_space *aspace,
                struct msm_gem_vma *vma);
 
@@ -333,6 +334,7 @@ void msm_gem_kernel_put(struct drm_gem_object *bo,
 struct drm_gem_object *msm_gem_import(struct drm_device *dev,
                struct dma_buf *dmabuf, struct sg_table *sgt);
 
+__printf(2, 3)
 void msm_gem_object_set_name(struct drm_gem_object *bo, const char *fmt, ...);
 
 int msm_framebuffer_prepare(struct drm_framebuffer *fb,
@@ -396,12 +398,14 @@ void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m);
 int msm_debugfs_late_init(struct drm_device *dev);
 int msm_rd_debugfs_init(struct drm_minor *minor);
 void msm_rd_debugfs_cleanup(struct msm_drm_private *priv);
+__printf(3, 4)
 void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit,
                const char *fmt, ...);
 int msm_perf_debugfs_init(struct drm_minor *minor);
 void msm_perf_debugfs_cleanup(struct msm_drm_private *priv);
 #else
 static inline int msm_debugfs_late_init(struct drm_device *dev) { return 0; }
+__printf(3, 4)
 static inline void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit,
                const char *fmt, ...) {}
 static inline void msm_rd_debugfs_cleanup(struct msm_drm_private *priv) {}
index 51a95da..c8886d3 100644 (file)
@@ -391,6 +391,10 @@ static int msm_gem_pin_iova(struct drm_gem_object *obj,
        struct msm_gem_object *msm_obj = to_msm_bo(obj);
        struct msm_gem_vma *vma;
        struct page **pages;
+       int prot = IOMMU_READ;
+
+       if (!(msm_obj->flags & MSM_BO_GPU_READONLY))
+               prot |= IOMMU_WRITE;
 
        WARN_ON(!mutex_is_locked(&msm_obj->lock));
 
@@ -405,8 +409,8 @@ static int msm_gem_pin_iova(struct drm_gem_object *obj,
        if (IS_ERR(pages))
                return PTR_ERR(pages);
 
-       return msm_gem_map_vma(aspace, vma, msm_obj->sgt,
-                       obj->size >> PAGE_SHIFT);
+       return msm_gem_map_vma(aspace, vma, prot,
+                       msm_obj->sgt, obj->size >> PAGE_SHIFT);
 }
 
 /* get iova and pin it. Should have a matching put */
index 5573607..49c0482 100644 (file)
@@ -68,7 +68,8 @@ void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
 
 int
 msm_gem_map_vma(struct msm_gem_address_space *aspace,
-               struct msm_gem_vma *vma, struct sg_table *sgt, int npages)
+               struct msm_gem_vma *vma, int prot,
+               struct sg_table *sgt, int npages)
 {
        unsigned size = npages << PAGE_SHIFT;
        int ret = 0;
@@ -86,7 +87,7 @@ msm_gem_map_vma(struct msm_gem_address_space *aspace,
 
        if (aspace->mmu)
                ret = aspace->mmu->funcs->map(aspace->mmu, vma->iova, sgt,
-                               size, IOMMU_READ | IOMMU_WRITE);
+                               size, prot);
 
        if (ret)
                vma->mapped = false;
index 5f3eff3..10babd1 100644 (file)
@@ -900,7 +900,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
        }
 
        /* Get Interrupt: */
-       gpu->irq = platform_get_irq_byname(pdev, config->irqname);
+       gpu->irq = platform_get_irq(pdev, 0);
        if (gpu->irq < 0) {
                ret = gpu->irq;
                DRM_DEV_ERROR(drm->dev, "failed to get irq: %d\n", ret);
index efb49bb..ca17086 100644 (file)
@@ -31,7 +31,6 @@ struct msm_gpu_state;
 
 struct msm_gpu_config {
        const char *ioname;
-       const char *irqname;
        uint64_t va_start;
        uint64_t va_end;
        unsigned int nr_rings;
@@ -63,7 +62,7 @@ struct msm_gpu_funcs {
        struct msm_ringbuffer *(*active_ring)(struct msm_gpu *gpu);
        void (*recover)(struct msm_gpu *gpu);
        void (*destroy)(struct msm_gpu *gpu);
-#ifdef CONFIG_DEBUG_FS
+#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)
        /* show GPU status in debugfs: */
        void (*show)(struct msm_gpu *gpu, struct msm_gpu_state *state,
                        struct drm_printer *p);
index 90e9d0a..d211729 100644 (file)
@@ -115,7 +115,9 @@ static void rd_write(struct msm_rd_state *rd, const void *buf, int sz)
                char *fptr = &fifo->buf[fifo->head];
                int n;
 
-               wait_event(rd->fifo_event, circ_space(&rd->fifo) > 0);
+               wait_event(rd->fifo_event, circ_space(&rd->fifo) > 0 || !rd->open);
+               if (!rd->open)
+                       return;
 
                /* Note that smp_load_acquire() is not strictly required
                 * as CIRC_SPACE_TO_END() does not access the tail more
@@ -213,7 +215,10 @@ out:
 static int rd_release(struct inode *inode, struct file *file)
 {
        struct msm_rd_state *rd = inode->i_private;
+
        rd->open = false;
+       wake_up_all(&rd->fifo_event);
+
        return 0;
 }
 
index 5f5be63..c7a94c9 100644 (file)
@@ -253,6 +253,9 @@ nouveau_backlight_init(struct drm_connector *connector)
        case NV_DEVICE_INFO_V0_FERMI:
        case NV_DEVICE_INFO_V0_KEPLER:
        case NV_DEVICE_INFO_V0_MAXWELL:
+       case NV_DEVICE_INFO_V0_PASCAL:
+       case NV_DEVICE_INFO_V0_VOLTA:
+       case NV_DEVICE_INFO_V0_TURING:
                ret = nv50_backlight_init(nv_encoder, &props, &ops);
                break;
        default:
index bfbc934..d9edb57 100644 (file)
@@ -2435,6 +2435,38 @@ nv140_chipset = {
 };
 
 static const struct nvkm_device_chip
+nv162_chipset = {
+       .name = "TU102",
+       .bar = tu104_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .devinit = tu104_devinit_new,
+       .fault = tu104_fault_new,
+       .fb = gv100_fb_new,
+       .fuse = gm107_fuse_new,
+       .gpio = gk104_gpio_new,
+       .i2c = gm200_i2c_new,
+       .ibus = gm200_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gp102_ltc_new,
+       .mc = tu104_mc_new,
+       .mmu = tu104_mmu_new,
+       .pci = gp100_pci_new,
+       .pmu = gp102_pmu_new,
+       .therm = gp100_therm_new,
+       .timer = gk20a_timer_new,
+       .top = gk104_top_new,
+       .ce[0] = tu104_ce_new,
+       .ce[1] = tu104_ce_new,
+       .ce[2] = tu104_ce_new,
+       .ce[3] = tu104_ce_new,
+       .ce[4] = tu104_ce_new,
+       .disp = tu104_disp_new,
+       .dma = gv100_dma_new,
+       .fifo = tu104_fifo_new,
+};
+
+static const struct nvkm_device_chip
 nv164_chipset = {
        .name = "TU104",
        .bar = tu104_bar_new,
@@ -2950,6 +2982,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
                case 0x138: device->chip = &nv138_chipset; break;
                case 0x13b: device->chip = &nv13b_chipset; break;
                case 0x140: device->chip = &nv140_chipset; break;
+               case 0x162: device->chip = &nv162_chipset; break;
                case 0x164: device->chip = &nv164_chipset; break;
                case 0x166: device->chip = &nv166_chipset; break;
                default:
index 816ccae..8675613 100644 (file)
@@ -22,6 +22,7 @@
 #include <engine/falcon.h>
 
 #include <core/gpuobj.h>
+#include <subdev/mc.h>
 #include <subdev/timer.h>
 #include <engine/fifo.h>
 
@@ -107,8 +108,10 @@ nvkm_falcon_fini(struct nvkm_engine *engine, bool suspend)
                }
        }
 
-       nvkm_mask(device, base + 0x048, 0x00000003, 0x00000000);
-       nvkm_wr32(device, base + 0x014, 0xffffffff);
+       if (nvkm_mc_enabled(device, engine->subdev.index)) {
+               nvkm_mask(device, base + 0x048, 0x00000003, 0x00000000);
+               nvkm_wr32(device, base + 0x014, 0xffffffff);
+       }
        return 0;
 }
 
index 3695cde..07914e3 100644 (file)
@@ -132,11 +132,12 @@ nvkm_therm_update(struct nvkm_therm *therm, int mode)
                        duty = nvkm_therm_update_linear(therm);
                        break;
                case NVBIOS_THERM_FAN_OTHER:
-                       if (therm->cstate)
+                       if (therm->cstate) {
                                duty = therm->cstate;
-                       else
+                               poll = false;
+                       } else {
                                duty = nvkm_therm_update_linear_fallback(therm);
-                       poll = false;
+                       }
                        break;
                }
                immd = false;
index 00a9c2a..64fb788 100644 (file)
@@ -1406,7 +1406,7 @@ static void dsi_pll_disable(struct dss_pll *pll)
 
 static int dsi_dump_dsi_clocks(struct seq_file *s, void *p)
 {
-       struct dsi_data *dsi = p;
+       struct dsi_data *dsi = s->private;
        struct dss_pll_clock_info *cinfo = &dsi->pll.cinfo;
        enum dss_clk_source dispc_clk_src, dsi_clk_src;
        int dsi_module = dsi->module_id;
@@ -1467,7 +1467,7 @@ static int dsi_dump_dsi_clocks(struct seq_file *s, void *p)
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
 static int dsi_dump_dsi_irqs(struct seq_file *s, void *p)
 {
-       struct dsi_data *dsi = p;
+       struct dsi_data *dsi = s->private;
        unsigned long flags;
        struct dsi_irq_stats stats;
 
@@ -1558,7 +1558,7 @@ static int dsi_dump_dsi_irqs(struct seq_file *s, void *p)
 
 static int dsi_dump_dsi_regs(struct seq_file *s, void *p)
 {
-       struct dsi_data *dsi = p;
+       struct dsi_data *dsi = s->private;
 
        if (dsi_runtime_get(dsi))
                return 0;
@@ -4751,6 +4751,17 @@ static int dsi_set_config(struct omap_dss_device *dssdev,
        dsi->vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH;
        dsi->vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW;
        dsi->vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH;
+       /*
+        * HACK: These flags should be handled through the omap_dss_device bus
+        * flags, but this will only be possible when the DSI encoder will be
+        * converted to the omapdrm-managed encoder model.
+        */
+       dsi->vm.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE;
+       dsi->vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
+       dsi->vm.flags &= ~DISPLAY_FLAGS_DE_LOW;
+       dsi->vm.flags |= DISPLAY_FLAGS_DE_HIGH;
+       dsi->vm.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE;
+       dsi->vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE;
 
        dss_mgr_set_timings(&dsi->output, &dsi->vm);
 
@@ -5083,15 +5094,15 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
 
        snprintf(name, sizeof(name), "dsi%u_regs", dsi->module_id + 1);
        dsi->debugfs.regs = dss_debugfs_create_file(dss, name,
-                                                   dsi_dump_dsi_regs, &dsi);
+                                                   dsi_dump_dsi_regs, dsi);
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
        snprintf(name, sizeof(name), "dsi%u_irqs", dsi->module_id + 1);
        dsi->debugfs.irqs = dss_debugfs_create_file(dss, name,
-                                                   dsi_dump_dsi_irqs, &dsi);
+                                                   dsi_dump_dsi_irqs, dsi);
 #endif
        snprintf(name, sizeof(name), "dsi%u_clks", dsi->module_id + 1);
        dsi->debugfs.clks = dss_debugfs_create_file(dss, name,
-                                                   dsi_dump_dsi_clocks, &dsi);
+                                                   dsi_dump_dsi_clocks, dsi);
 
        return 0;
 }
@@ -5104,8 +5115,6 @@ static void dsi_unbind(struct device *dev, struct device *master, void *data)
        dss_debugfs_remove_file(dsi->debugfs.irqs);
        dss_debugfs_remove_file(dsi->debugfs.regs);
 
-       of_platform_depopulate(dev);
-
        WARN_ON(dsi->scp_clk_refcount > 0);
 
        dss_pll_unregister(&dsi->pll);
@@ -5457,6 +5466,8 @@ static int dsi_remove(struct platform_device *pdev)
 
        dsi_uninit_output(dsi);
 
+       of_platform_depopulate(&pdev->dev);
+
        pm_runtime_disable(&pdev->dev);
 
        if (dsi->vdds_dsi_reg != NULL && dsi->vdds_dsi_enabled) {
index 13c8a66..ccb090f 100644 (file)
@@ -250,14 +250,10 @@ static struct drm_driver qxl_driver = {
 #if defined(CONFIG_DEBUG_FS)
        .debugfs_init = qxl_debugfs_init,
 #endif
-       .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_pin = qxl_gem_prime_pin,
        .gem_prime_unpin = qxl_gem_prime_unpin,
-       .gem_prime_get_sg_table = qxl_gem_prime_get_sg_table,
-       .gem_prime_import_sg_table = qxl_gem_prime_import_sg_table,
        .gem_prime_vmap = qxl_gem_prime_vmap,
        .gem_prime_vunmap = qxl_gem_prime_vunmap,
        .gem_prime_mmap = qxl_gem_prime_mmap,
index a55dece..df65d3c 100644 (file)
@@ -38,20 +38,6 @@ void qxl_gem_prime_unpin(struct drm_gem_object *obj)
        WARN_ONCE(1, "not implemented");
 }
 
-struct sg_table *qxl_gem_prime_get_sg_table(struct drm_gem_object *obj)
-{
-       WARN_ONCE(1, "not implemented");
-       return ERR_PTR(-ENOSYS);
-}
-
-struct drm_gem_object *qxl_gem_prime_import_sg_table(
-       struct drm_device *dev, struct dma_buf_attachment *attach,
-       struct sg_table *table)
-{
-       WARN_ONCE(1, "not implemented");
-       return ERR_PTR(-ENOSYS);
-}
-
 void *qxl_gem_prime_vmap(struct drm_gem_object *obj)
 {
        WARN_ONCE(1, "not implemented");
index d587779..a97294a 100644 (file)
@@ -5676,7 +5676,7 @@ int ci_dpm_init(struct radeon_device *rdev)
        u16 data_offset, size;
        u8 frev, crev;
        struct ci_power_info *pi;
-       enum pci_bus_speed speed_cap;
+       enum pci_bus_speed speed_cap = PCI_SPEED_UNKNOWN;
        struct pci_dev *root = rdev->pdev->bus->self;
        int ret;
 
@@ -5685,7 +5685,8 @@ int ci_dpm_init(struct radeon_device *rdev)
                return -ENOMEM;
        rdev->pm.dpm.priv = pi;
 
-       speed_cap = pcie_get_speed_cap(root);
+       if (!pci_is_root_bus(rdev->pdev->bus))
+               speed_cap = pcie_get_speed_cap(root);
        if (speed_cap == PCI_SPEED_UNKNOWN) {
                pi->sys_pcie_mask = 0;
        } else {
index 8fb60b3..0a785ef 100644 (file)
@@ -6899,7 +6899,7 @@ int si_dpm_init(struct radeon_device *rdev)
        struct ni_power_info *ni_pi;
        struct si_power_info *si_pi;
        struct atom_clock_dividers dividers;
-       enum pci_bus_speed speed_cap;
+       enum pci_bus_speed speed_cap = PCI_SPEED_UNKNOWN;
        struct pci_dev *root = rdev->pdev->bus->self;
        int ret;
 
@@ -6911,7 +6911,8 @@ int si_dpm_init(struct radeon_device *rdev)
        eg_pi = &ni_pi->eg;
        pi = &eg_pi->rv7xx;
 
-       speed_cap = pcie_get_speed_cap(root);
+       if (!pci_is_root_bus(rdev->pdev->bus))
+               speed_cap = pcie_get_speed_cap(root);
        if (speed_cap == PCI_SPEED_UNKNOWN) {
                si_pi->sys_pcie_mask = 0;
        } else {
index 96ac145..c0351ab 100644 (file)
@@ -1,17 +1,8 @@
-//SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
  * Author:
  *      Sandy Huang <hjc@rock-chips.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.  See the
- * GNU General Public License for more details.
  */
 
 #include <drm/drmP.h>
@@ -113,8 +104,10 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev,
                child_count++;
                ret = drm_of_find_panel_or_bridge(dev->of_node, 0, endpoint_id,
                                                  &panel, &bridge);
-               if (!ret)
+               if (!ret) {
+                       of_node_put(endpoint);
                        break;
+               }
        }
 
        of_node_put(port);
index 38b52e6..27b9635 100644 (file)
@@ -1,17 +1,8 @@
-//SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
  * Author:
  *      Sandy Huang <hjc@rock-chips.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.  See the
- * GNU General Public License for more details.
  */
 
 #ifdef CONFIG_ROCKCHIP_RGB
index 4463d38..e2942c9 100644 (file)
@@ -440,13 +440,10 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)
 
        while ((entity->dependency =
                        sched->ops->dependency(sched_job, entity))) {
+               trace_drm_sched_job_wait_dep(sched_job, entity->dependency);
 
-               if (drm_sched_entity_add_dependency_cb(entity)) {
-
-                       trace_drm_sched_job_wait_dep(sched_job,
-                                                    entity->dependency);
+               if (drm_sched_entity_add_dependency_cb(entity))
                        return NULL;
-               }
        }
 
        /* skip jobs from entity that marked guilty */
index 9e9255e..a021bab 100644 (file)
@@ -786,17 +786,18 @@ static struct sun4i_frontend *sun4i_backend_find_frontend(struct sun4i_drv *drv,
                remote = of_graph_get_remote_port_parent(ep);
                if (!remote)
                        continue;
+               of_node_put(remote);
 
                /* does this node match any registered engines? */
                list_for_each_entry(frontend, &drv->frontend_list, list) {
                        if (remote == frontend->node) {
-                               of_node_put(remote);
                                of_node_put(port);
+                               of_node_put(ep);
                                return frontend;
                        }
                }
        }
-
+       of_node_put(port);
        return ERR_PTR(-EINVAL);
 }
 
index 061d2e0..416da53 100644 (file)
@@ -92,6 +92,8 @@ static void sun4i_hdmi_disable(struct drm_encoder *encoder)
        val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
        val &= ~SUN4I_HDMI_VID_CTRL_ENABLE;
        writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
+
+       clk_disable_unprepare(hdmi->tmds_clk);
 }
 
 static void sun4i_hdmi_enable(struct drm_encoder *encoder)
@@ -102,6 +104,8 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder)
 
        DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
 
+       clk_prepare_enable(hdmi->tmds_clk);
+
        sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
        val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
        val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
index 0420f5c..cf45d0f 100644 (file)
@@ -761,6 +761,7 @@ static int sun4i_tcon_init_clocks(struct device *dev,
                        return PTR_ERR(tcon->sclk0);
                }
        }
+       clk_prepare_enable(tcon->sclk0);
 
        if (tcon->quirks->has_channel_1) {
                tcon->sclk1 = devm_clk_get(dev, "tcon-ch1");
@@ -775,6 +776,7 @@ static int sun4i_tcon_init_clocks(struct device *dev,
 
 static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)
 {
+       clk_disable_unprepare(tcon->sclk0);
        clk_disable_unprepare(tcon->clk);
 }
 
index f7f32a8..2d1aaca 100644 (file)
@@ -127,14 +127,10 @@ static struct drm_driver driver = {
 #if defined(CONFIG_DEBUG_FS)
        .debugfs_init = virtio_gpu_debugfs_init,
 #endif
-       .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_pin = virtgpu_gem_prime_pin,
        .gem_prime_unpin = virtgpu_gem_prime_unpin,
-       .gem_prime_get_sg_table = virtgpu_gem_prime_get_sg_table,
-       .gem_prime_import_sg_table = virtgpu_gem_prime_import_sg_table,
        .gem_prime_vmap = virtgpu_gem_prime_vmap,
        .gem_prime_vunmap = virtgpu_gem_prime_vunmap,
        .gem_prime_mmap = virtgpu_gem_prime_mmap,
index 1deb41d..0c15000 100644 (file)
@@ -372,10 +372,6 @@ int virtio_gpu_object_wait(struct virtio_gpu_object *bo, bool no_wait);
 /* virtgpu_prime.c */
 int virtgpu_gem_prime_pin(struct drm_gem_object *obj);
 void virtgpu_gem_prime_unpin(struct drm_gem_object *obj);
-struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj);
-struct drm_gem_object *virtgpu_gem_prime_import_sg_table(
-       struct drm_device *dev, struct dma_buf_attachment *attach,
-       struct sg_table *sgt);
 void *virtgpu_gem_prime_vmap(struct drm_gem_object *obj);
 void virtgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
 int virtgpu_gem_prime_mmap(struct drm_gem_object *obj,
index 86ce0ae..c59ec34 100644 (file)
@@ -39,20 +39,6 @@ void virtgpu_gem_prime_unpin(struct drm_gem_object *obj)
        WARN_ONCE(1, "not implemented");
 }
 
-struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj)
-{
-       WARN_ONCE(1, "not implemented");
-       return ERR_PTR(-ENODEV);
-}
-
-struct drm_gem_object *virtgpu_gem_prime_import_sg_table(
-       struct drm_device *dev, struct dma_buf_attachment *attach,
-       struct sg_table *table)
-{
-       WARN_ONCE(1, "not implemented");
-       return ERR_PTR(-ENODEV);
-}
-
 void *virtgpu_gem_prime_vmap(struct drm_gem_object *obj)
 {
        struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
index 9d9e814..d7b409a 100644 (file)
@@ -1,4 +1,5 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
+
 #include "vkms_drv.h"
 #include <linux/crc32.h>
 #include <drm/drm_atomic.h>
index 177bbcb..eb56ee8 100644 (file)
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include "vkms_drv.h"
 #include <drm/drm_atomic_helper.h>
index 8308787..7dcbecb 100644 (file)
@@ -1,9 +1,4 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 /**
  * DOC: vkms (Virtual Kernel Modesetting)
index e4469cd..81f1cfb 100644 (file)
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
 #ifndef _VKMS_DRV_H_
 #define _VKMS_DRV_H_
 
index 80311da..138b0bb 100644 (file)
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include <linux/shmem_fs.h>
 
index 271a0eb..4173e4f 100644 (file)
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include "vkms_drv.h"
 #include <drm/drm_crtc_helper.h>
index 4188176..0e67d2d 100644 (file)
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include "vkms_drv.h"
 #include <drm/drm_plane_helper.h>
index 25afb1d..7ef5dcb 100644 (file)
@@ -26,6 +26,7 @@
  **************************************************************************/
 #include <linux/module.h>
 #include <linux/console.h>
+#include <linux/dma-mapping.h>
 
 #include <drm/drmP.h>
 #include "vmwgfx_drv.h"
@@ -34,7 +35,6 @@
 #include <drm/ttm/ttm_placement.h>
 #include <drm/ttm/ttm_bo_driver.h>
 #include <drm/ttm/ttm_module.h>
-#include <linux/intel-iommu.h>
 
 #define VMWGFX_DRIVER_DESC "Linux drm driver for VMware graphics devices"
 #define VMWGFX_CHIP_SVGAII 0
@@ -546,6 +546,21 @@ static void vmw_get_initial_size(struct vmw_private *dev_priv)
 }
 
 /**
+ * vmw_assume_iommu - Figure out whether coherent dma-remapping might be
+ * taking place.
+ * @dev: Pointer to the struct drm_device.
+ *
+ * Return: true if iommu present, false otherwise.
+ */
+static bool vmw_assume_iommu(struct drm_device *dev)
+{
+       const struct dma_map_ops *ops = get_dma_ops(dev->dev);
+
+       return !dma_is_direct(ops) && ops &&
+               ops->map_page != dma_direct_map_page;
+}
+
+/**
  * vmw_dma_select_mode - Determine how DMA mappings should be set up for this
  * system.
  *
@@ -565,55 +580,27 @@ static int vmw_dma_select_mode(struct vmw_private *dev_priv)
                [vmw_dma_alloc_coherent] = "Using coherent TTM pages.",
                [vmw_dma_map_populate] = "Keeping DMA mappings.",
                [vmw_dma_map_bind] = "Giving up DMA mappings early."};
-#ifdef CONFIG_X86
-       const struct dma_map_ops *dma_ops = get_dma_ops(dev_priv->dev->dev);
 
-#ifdef CONFIG_INTEL_IOMMU
-       if (intel_iommu_enabled) {
+       if (vmw_force_coherent)
+               dev_priv->map_mode = vmw_dma_alloc_coherent;
+       else if (vmw_assume_iommu(dev_priv->dev))
                dev_priv->map_mode = vmw_dma_map_populate;
-               goto out_fixup;
-       }
-#endif
-
-       if (!(vmw_force_iommu || vmw_force_coherent)) {
+       else if (!vmw_force_iommu)
                dev_priv->map_mode = vmw_dma_phys;
-               DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]);
-               return 0;
-       }
-
-       dev_priv->map_mode = vmw_dma_map_populate;
-
-       if (dma_ops && dma_ops->sync_single_for_cpu)
+       else if (IS_ENABLED(CONFIG_SWIOTLB) && swiotlb_nr_tbl())
                dev_priv->map_mode = vmw_dma_alloc_coherent;
-#ifdef CONFIG_SWIOTLB
-       if (swiotlb_nr_tbl() == 0)
+       else
                dev_priv->map_mode = vmw_dma_map_populate;
-#endif
 
-#ifdef CONFIG_INTEL_IOMMU
-out_fixup:
-#endif
-       if (dev_priv->map_mode == vmw_dma_map_populate &&
-           vmw_restrict_iommu)
+       if (dev_priv->map_mode == vmw_dma_map_populate && vmw_restrict_iommu)
                dev_priv->map_mode = vmw_dma_map_bind;
 
-       if (vmw_force_coherent)
-               dev_priv->map_mode = vmw_dma_alloc_coherent;
-
-#if !defined(CONFIG_SWIOTLB) && !defined(CONFIG_INTEL_IOMMU)
-       /*
-        * No coherent page pool
-        */
-       if (dev_priv->map_mode == vmw_dma_alloc_coherent)
+       /* No TTM coherent page pool? FIXME: Ask TTM instead! */
+        if (!(IS_ENABLED(CONFIG_SWIOTLB) || IS_ENABLED(CONFIG_INTEL_IOMMU)) &&
+           (dev_priv->map_mode == vmw_dma_alloc_coherent))
                return -EINVAL;
-#endif
-
-#else /* CONFIG_X86 */
-       dev_priv->map_mode = vmw_dma_map_populate;
-#endif /* CONFIG_X86 */
 
        DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]);
-
        return 0;
 }
 
@@ -625,24 +612,20 @@ out_fixup:
  * With 32-bit we can only handle 32 bit PFNs. Optionally set that
  * restriction also for 64-bit systems.
  */
-#ifdef CONFIG_INTEL_IOMMU
 static int vmw_dma_masks(struct vmw_private *dev_priv)
 {
        struct drm_device *dev = dev_priv->dev;
+       int ret = 0;
 
-       if (intel_iommu_enabled &&
+       ret = dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64));
+       if (dev_priv->map_mode != vmw_dma_phys &&
            (sizeof(unsigned long) == 4 || vmw_restrict_dma_mask)) {
                DRM_INFO("Restricting DMA addresses to 44 bits.\n");
-               return dma_set_mask(dev->dev, DMA_BIT_MASK(44));
+               return dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(44));
        }
-       return 0;
-}
-#else
-static int vmw_dma_masks(struct vmw_private *dev_priv)
-{
-       return 0;
+
+       return ret;
 }
-#endif
 
 static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 {
index f2d13a7..88b8178 100644 (file)
@@ -3570,7 +3570,7 @@ int vmw_execbuf_fence_commands(struct drm_file *file_priv,
                *p_fence = NULL;
        }
 
-       return 0;
+       return ret;
 }
 
 /**
index b351fb5..ed2f678 100644 (file)
@@ -1646,7 +1646,7 @@ static int vmw_kms_check_topology(struct drm_device *dev,
                struct drm_connector_state *conn_state;
                struct vmw_connector_state *vmw_conn_state;
 
-               if (!du->pref_active) {
+               if (!du->pref_active && new_crtc_state->enable) {
                        ret = -EINVAL;
                        goto clean;
                }
@@ -2554,8 +2554,8 @@ void vmw_kms_helper_validation_finish(struct vmw_private *dev_priv,
                                      user_fence_rep)
 {
        struct vmw_fence_obj *fence = NULL;
-       uint32_t handle;
-       int ret;
+       uint32_t handle = 0;
+       int ret = 0;
 
        if (file_priv || user_fence_rep || vmw_validation_has_bos(ctx) ||
            out_fence)
index 474b00e..0a7d439 100644 (file)
@@ -898,8 +898,8 @@ static struct ipu_devtype ipu_type_imx51 = {
        .cpmem_ofs = 0x1f000000,
        .srm_ofs = 0x1f040000,
        .tpm_ofs = 0x1f060000,
-       .csi0_ofs = 0x1f030000,
-       .csi1_ofs = 0x1f038000,
+       .csi0_ofs = 0x1e030000,
+       .csi1_ofs = 0x1e038000,
        .ic_ofs = 0x1e020000,
        .disp0_ofs = 0x1e040000,
        .disp1_ofs = 0x1e048000,
@@ -914,8 +914,8 @@ static struct ipu_devtype ipu_type_imx53 = {
        .cpmem_ofs = 0x07000000,
        .srm_ofs = 0x07040000,
        .tpm_ofs = 0x07060000,
-       .csi0_ofs = 0x07030000,
-       .csi1_ofs = 0x07038000,
+       .csi0_ofs = 0x06030000,
+       .csi1_ofs = 0x06038000,
        .ic_ofs = 0x06020000,
        .disp0_ofs = 0x06040000,
        .disp1_ofs = 0x06048000,
index 2f8db9d..4a28f3f 100644 (file)
@@ -106,6 +106,7 @@ struct ipu_pre {
        void                    *buffer_virt;
        bool                    in_use;
        unsigned int            safe_window_end;
+       unsigned int            last_bufaddr;
 };
 
 static DEFINE_MUTEX(ipu_pre_list_mutex);
@@ -185,6 +186,7 @@ void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
 
        writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF);
        writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
+       pre->last_bufaddr = bufaddr;
 
        val = IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(0) |
              IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(active_bpp) |
@@ -242,7 +244,11 @@ void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr)
        unsigned short current_yblock;
        u32 val;
 
+       if (bufaddr == pre->last_bufaddr)
+               return;
+
        writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
+       pre->last_bufaddr = bufaddr;
 
        do {
                if (time_after(jiffies, timeout)) {
index b677e5d..d5f1d8e 100644 (file)
@@ -21,6 +21,7 @@ config VGA_SWITCHEROO
        bool "Laptop Hybrid Graphics - GPU switching support"
        depends on X86
        depends on ACPI
+       depends on PCI
        select VGA_ARB
        help
          Many laptops released in 2008/9/10 have two GPUs with a multiplexer
index f41d5fe..9993b69 100644 (file)
@@ -125,6 +125,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
 {
        struct hid_collection *collection;
        unsigned usage;
+       int collection_index;
 
        usage = parser->local.usage[0];
 
@@ -167,13 +168,13 @@ static int open_collection(struct hid_parser *parser, unsigned type)
        parser->collection_stack[parser->collection_stack_ptr++] =
                parser->device->maxcollection;
 
-       collection = parser->device->collection +
-               parser->device->maxcollection++;
+       collection_index = parser->device->maxcollection++;
+       collection = parser->device->collection + collection_index;
        collection->type = type;
        collection->usage = usage;
        collection->level = parser->collection_stack_ptr - 1;
-       collection->parent = parser->active_collection;
-       parser->active_collection = collection;
+       collection->parent_idx = (collection->level == 0) ? -1 :
+               parser->collection_stack[collection->level - 1];
 
        if (type == HID_COLLECTION_APPLICATION)
                parser->device->maxapplication++;
@@ -192,8 +193,6 @@ static int close_collection(struct hid_parser *parser)
                return -EINVAL;
        }
        parser->collection_stack_ptr--;
-       if (parser->active_collection)
-               parser->active_collection = parser->active_collection->parent;
        return 0;
 }
 
@@ -1006,10 +1005,12 @@ static void hid_apply_multiplier_to_field(struct hid_device *hid,
                usage = &field->usage[i];
 
                collection = &hid->collection[usage->collection_index];
-               while (collection && collection != multiplier_collection)
-                       collection = collection->parent;
+               while (collection->parent_idx != -1 &&
+                      collection != multiplier_collection)
+                       collection = &hid->collection[collection->parent_idx];
 
-               if (collection || multiplier_collection == NULL)
+               if (collection->parent_idx != -1 ||
+                   multiplier_collection == NULL)
                        usage->resolution_multiplier = effective_multiplier;
 
        }
@@ -1044,9 +1045,9 @@ static void hid_apply_multiplier(struct hid_device *hid,
         * applicable fields later.
         */
        multiplier_collection = &hid->collection[multiplier->usage->collection_index];
-       while (multiplier_collection &&
+       while (multiplier_collection->parent_idx != -1 &&
               multiplier_collection->type != HID_COLLECTION_LOGICAL)
-               multiplier_collection = multiplier_collection->parent;
+               multiplier_collection = &hid->collection[multiplier_collection->parent_idx];
 
        effective_multiplier = hid_calculate_multiplier(hid, multiplier);
 
index c530476..ac9fda1 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
+#include <linux/kfifo.h>
 #include <linux/sched/signal.h>
 #include <linux/export.h>
 #include <linux/slab.h>
@@ -661,17 +662,12 @@ EXPORT_SYMBOL_GPL(hid_dump_device);
 /* enqueue string to 'events' ring buffer */
 void hid_debug_event(struct hid_device *hdev, char *buf)
 {
-       unsigned i;
        struct hid_debug_list *list;
        unsigned long flags;
 
        spin_lock_irqsave(&hdev->debug_list_lock, flags);
-       list_for_each_entry(list, &hdev->debug_list, node) {
-               for (i = 0; buf[i]; i++)
-                       list->hid_debug_buf[(list->tail + i) % HID_DEBUG_BUFSIZE] =
-                               buf[i];
-               list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE;
-        }
+       list_for_each_entry(list, &hdev->debug_list, node)
+               kfifo_in(&list->hid_debug_fifo, buf, strlen(buf));
        spin_unlock_irqrestore(&hdev->debug_list_lock, flags);
 
        wake_up_interruptible(&hdev->debug_wait);
@@ -722,8 +718,7 @@ void hid_dump_input(struct hid_device *hdev, struct hid_usage *usage, __s32 valu
        hid_debug_event(hdev, buf);
 
        kfree(buf);
-        wake_up_interruptible(&hdev->debug_wait);
-
+       wake_up_interruptible(&hdev->debug_wait);
 }
 EXPORT_SYMBOL_GPL(hid_dump_input);
 
@@ -1083,8 +1078,8 @@ static int hid_debug_events_open(struct inode *inode, struct file *file)
                goto out;
        }
 
-       if (!(list->hid_debug_buf = kzalloc(HID_DEBUG_BUFSIZE, GFP_KERNEL))) {
-               err = -ENOMEM;
+       err = kfifo_alloc(&list->hid_debug_fifo, HID_DEBUG_FIFOSIZE, GFP_KERNEL);
+       if (err) {
                kfree(list);
                goto out;
        }
@@ -1104,77 +1099,57 @@ static ssize_t hid_debug_events_read(struct file *file, char __user *buffer,
                size_t count, loff_t *ppos)
 {
        struct hid_debug_list *list = file->private_data;
-       int ret = 0, len;
+       int ret = 0, copied;
        DECLARE_WAITQUEUE(wait, current);
 
        mutex_lock(&list->read_mutex);
-       while (ret == 0) {
-               if (list->head == list->tail) {
-                       add_wait_queue(&list->hdev->debug_wait, &wait);
-                       set_current_state(TASK_INTERRUPTIBLE);
-
-                       while (list->head == list->tail) {
-                               if (file->f_flags & O_NONBLOCK) {
-                                       ret = -EAGAIN;
-                                       break;
-                               }
-                               if (signal_pending(current)) {
-                                       ret = -ERESTARTSYS;
-                                       break;
-                               }
+       if (kfifo_is_empty(&list->hid_debug_fifo)) {
+               add_wait_queue(&list->hdev->debug_wait, &wait);
+               set_current_state(TASK_INTERRUPTIBLE);
+
+               while (kfifo_is_empty(&list->hid_debug_fifo)) {
+                       if (file->f_flags & O_NONBLOCK) {
+                               ret = -EAGAIN;
+                               break;
+                       }
 
-                               if (!list->hdev || !list->hdev->debug) {
-                                       ret = -EIO;
-                                       set_current_state(TASK_RUNNING);
-                                       goto out;
-                               }
+                       if (signal_pending(current)) {
+                               ret = -ERESTARTSYS;
+                               break;
+                       }
 
-                               /* allow O_NONBLOCK from other threads */
-                               mutex_unlock(&list->read_mutex);
-                               schedule();
-                               mutex_lock(&list->read_mutex);
-                               set_current_state(TASK_INTERRUPTIBLE);
+                       /* if list->hdev is NULL we cannot remove_wait_queue().
+                        * if list->hdev->debug is 0 then hid_debug_unregister()
+                        * was already called and list->hdev is being destroyed.
+                        * if we add remove_wait_queue() here we can hit a race.
+                        */
+                       if (!list->hdev || !list->hdev->debug) {
+                               ret = -EIO;
+                               set_current_state(TASK_RUNNING);
+                               goto out;
                        }
 
-                       set_current_state(TASK_RUNNING);
-                       remove_wait_queue(&list->hdev->debug_wait, &wait);
+                       /* allow O_NONBLOCK from other threads */
+                       mutex_unlock(&list->read_mutex);
+                       schedule();
+                       mutex_lock(&list->read_mutex);
+                       set_current_state(TASK_INTERRUPTIBLE);
                }
 
-               if (ret)
-                       goto out;
+               __set_current_state(TASK_RUNNING);
+               remove_wait_queue(&list->hdev->debug_wait, &wait);
 
-               /* pass the ringbuffer contents to userspace */
-copy_rest:
-               if (list->tail == list->head)
+               if (ret)
                        goto out;
-               if (list->tail > list->head) {
-                       len = list->tail - list->head;
-                       if (len > count)
-                               len = count;
-
-                       if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) {
-                               ret = -EFAULT;
-                               goto out;
-                       }
-                       ret += len;
-                       list->head += len;
-               } else {
-                       len = HID_DEBUG_BUFSIZE - list->head;
-                       if (len > count)
-                               len = count;
-
-                       if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) {
-                               ret = -EFAULT;
-                               goto out;
-                       }
-                       list->head = 0;
-                       ret += len;
-                       count -= len;
-                       if (count > 0)
-                               goto copy_rest;
-               }
-
        }
+
+       /* pass the fifo content to userspace, locking is not needed with only
+        * one concurrent reader and one concurrent writer
+        */
+       ret = kfifo_to_user(&list->hid_debug_fifo, buffer, count, &copied);
+       if (ret)
+               goto out;
+       ret = copied;
 out:
        mutex_unlock(&list->read_mutex);
        return ret;
@@ -1185,7 +1160,7 @@ static __poll_t hid_debug_events_poll(struct file *file, poll_table *wait)
        struct hid_debug_list *list = file->private_data;
 
        poll_wait(file, &list->hdev->debug_wait, wait);
-       if (list->head != list->tail)
+       if (!kfifo_is_empty(&list->hid_debug_fifo))
                return EPOLLIN | EPOLLRDNORM;
        if (!list->hdev->debug)
                return EPOLLERR | EPOLLHUP;
@@ -1200,7 +1175,7 @@ static int hid_debug_events_release(struct inode *inode, struct file *file)
        spin_lock_irqsave(&list->hdev->debug_list_lock, flags);
        list_del(&list->node);
        spin_unlock_irqrestore(&list->hdev->debug_list_lock, flags);
-       kfree(list->hid_debug_buf);
+       kfifo_free(&list->hid_debug_fifo);
        kfree(list);
 
        return 0;
@@ -1246,4 +1221,3 @@ void hid_debug_exit(void)
 {
        debugfs_remove_recursive(hid_debug_root);
 }
-
index 518fa76..24f846d 100644 (file)
 #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A 0x010a
 #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100 0xe100
 
+#define I2C_VENDOR_ID_GOODIX           0x27c6
+#define I2C_DEVICE_ID_GOODIX_01F0      0x01f0
+
 #define USB_VENDOR_ID_GOODTOUCH                0x1aad
 #define USB_DEVICE_ID_GOODTOUCH_000f   0x000f
 
index 8555ce7..c5edfa9 100644 (file)
@@ -179,6 +179,8 @@ static const struct i2c_hid_quirks {
                I2C_HID_QUIRK_DELAY_AFTER_SLEEP },
        { USB_VENDOR_ID_LG, I2C_DEVICE_ID_LG_8001,
                I2C_HID_QUIRK_NO_RUNTIME_PM },
+       { I2C_VENDOR_ID_GOODIX, I2C_DEVICE_ID_GOODIX_01F0,
+               I2C_HID_QUIRK_NO_RUNTIME_PM },
        { 0, 0 }
 };
 
index ce0ba20..bea4c98 100644 (file)
@@ -701,19 +701,12 @@ static int vmbus_close_internal(struct vmbus_channel *channel)
 int vmbus_disconnect_ring(struct vmbus_channel *channel)
 {
        struct vmbus_channel *cur_channel, *tmp;
-       unsigned long flags;
-       LIST_HEAD(list);
        int ret;
 
        if (channel->primary_channel != NULL)
                return -EINVAL;
 
-       /* Snapshot the list of subchannels */
-       spin_lock_irqsave(&channel->lock, flags);
-       list_splice_init(&channel->sc_list, &list);
-       spin_unlock_irqrestore(&channel->lock, flags);
-
-       list_for_each_entry_safe(cur_channel, tmp, &list, sc_list) {
+       list_for_each_entry_safe(cur_channel, tmp, &channel->sc_list, sc_list) {
                if (cur_channel->rescind)
                        wait_for_completion(&cur_channel->rescind_event);
 
index 5301fef..7c6349a 100644 (file)
@@ -888,12 +888,14 @@ static unsigned long handle_pg_range(unsigned long pg_start,
                        pfn_cnt -= pgs_ol;
                        /*
                         * Check if the corresponding memory block is already
-                        * online by checking its last previously backed page.
-                        * In case it is we need to bring rest (which was not
-                        * backed previously) online too.
+                        * online. It is possible to observe struct pages still
+                        * being uninitialized here so check section instead.
+                        * In case the section is online we need to bring the
+                        * rest of pfns (which were not backed previously)
+                        * online too.
                         */
                        if (start_pfn > has->start_pfn &&
-                           !PageReserved(pfn_to_page(start_pfn - 1)))
+                           online_section_nr(pfn_to_section_nr(start_pfn)))
                                hv_bring_pgs_online(has, start_pfn, pgs_ol);
 
                }
index 64d0c85..1f1a55e 100644 (file)
@@ -164,26 +164,25 @@ hv_get_ringbuffer_availbytes(const struct hv_ring_buffer_info *rbi,
 }
 
 /* Get various debug metrics for the specified ring buffer. */
-void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
-                                struct hv_ring_buffer_debug_info *debug_info)
+int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
+                               struct hv_ring_buffer_debug_info *debug_info)
 {
        u32 bytes_avail_towrite;
        u32 bytes_avail_toread;
 
-       if (ring_info->ring_buffer) {
-               hv_get_ringbuffer_availbytes(ring_info,
-                                       &bytes_avail_toread,
-                                       &bytes_avail_towrite);
-
-               debug_info->bytes_avail_toread = bytes_avail_toread;
-               debug_info->bytes_avail_towrite = bytes_avail_towrite;
-               debug_info->current_read_index =
-                       ring_info->ring_buffer->read_index;
-               debug_info->current_write_index =
-                       ring_info->ring_buffer->write_index;
-               debug_info->current_interrupt_mask =
-                       ring_info->ring_buffer->interrupt_mask;
-       }
+       if (!ring_info->ring_buffer)
+               return -EINVAL;
+
+       hv_get_ringbuffer_availbytes(ring_info,
+                                    &bytes_avail_toread,
+                                    &bytes_avail_towrite);
+       debug_info->bytes_avail_toread = bytes_avail_toread;
+       debug_info->bytes_avail_towrite = bytes_avail_towrite;
+       debug_info->current_read_index = ring_info->ring_buffer->read_index;
+       debug_info->current_write_index = ring_info->ring_buffer->write_index;
+       debug_info->current_interrupt_mask
+               = ring_info->ring_buffer->interrupt_mask;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(hv_ringbuffer_get_debuginfo);
 
index d0ff656..403fee0 100644 (file)
@@ -313,12 +313,16 @@ static ssize_t out_intr_mask_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info outbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+                                         &outbound);
+       if (ret < 0)
+               return ret;
+
        return sprintf(buf, "%d\n", outbound.current_interrupt_mask);
 }
 static DEVICE_ATTR_RO(out_intr_mask);
@@ -328,12 +332,15 @@ static ssize_t out_read_index_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info outbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+                                         &outbound);
+       if (ret < 0)
+               return ret;
        return sprintf(buf, "%d\n", outbound.current_read_index);
 }
 static DEVICE_ATTR_RO(out_read_index);
@@ -344,12 +351,15 @@ static ssize_t out_write_index_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info outbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+                                         &outbound);
+       if (ret < 0)
+               return ret;
        return sprintf(buf, "%d\n", outbound.current_write_index);
 }
 static DEVICE_ATTR_RO(out_write_index);
@@ -360,12 +370,15 @@ static ssize_t out_read_bytes_avail_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info outbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+                                         &outbound);
+       if (ret < 0)
+               return ret;
        return sprintf(buf, "%d\n", outbound.bytes_avail_toread);
 }
 static DEVICE_ATTR_RO(out_read_bytes_avail);
@@ -376,12 +389,15 @@ static ssize_t out_write_bytes_avail_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info outbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+                                         &outbound);
+       if (ret < 0)
+               return ret;
        return sprintf(buf, "%d\n", outbound.bytes_avail_towrite);
 }
 static DEVICE_ATTR_RO(out_write_bytes_avail);
@@ -391,12 +407,15 @@ static ssize_t in_intr_mask_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info inbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+       if (ret < 0)
+               return ret;
+
        return sprintf(buf, "%d\n", inbound.current_interrupt_mask);
 }
 static DEVICE_ATTR_RO(in_intr_mask);
@@ -406,12 +425,15 @@ static ssize_t in_read_index_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info inbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+       if (ret < 0)
+               return ret;
+
        return sprintf(buf, "%d\n", inbound.current_read_index);
 }
 static DEVICE_ATTR_RO(in_read_index);
@@ -421,12 +443,15 @@ static ssize_t in_write_index_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info inbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+       if (ret < 0)
+               return ret;
+
        return sprintf(buf, "%d\n", inbound.current_write_index);
 }
 static DEVICE_ATTR_RO(in_write_index);
@@ -437,12 +462,15 @@ static ssize_t in_read_bytes_avail_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info inbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+       if (ret < 0)
+               return ret;
+
        return sprintf(buf, "%d\n", inbound.bytes_avail_toread);
 }
 static DEVICE_ATTR_RO(in_read_bytes_avail);
@@ -453,12 +481,15 @@ static ssize_t in_write_bytes_avail_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info inbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+       if (ret < 0)
+               return ret;
+
        return sprintf(buf, "%d\n", inbound.bytes_avail_towrite);
 }
 static DEVICE_ATTR_RO(in_write_bytes_avail);
index 0e30fa0..f9b8e3e 100644 (file)
@@ -393,8 +393,10 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
        }
 
        rv = lm80_read_value(client, LM80_REG_FANDIV);
-       if (rv < 0)
+       if (rv < 0) {
+               mutex_unlock(&data->update_lock);
                return rv;
+       }
        reg = (rv & ~(3 << (2 * (nr + 1))))
            | (data->fan_div[nr] << (2 * (nr + 1)));
        lm80_write_value(client, LM80_REG_FANDIV, reg);
index c304007..59ee01f 100644 (file)
@@ -44,8 +44,8 @@
  * nct6796d    14      7       7       2+6    0xd420 0xc1    0x5ca3
  * nct6797d    14      7       7       2+6    0xd450 0xc1    0x5ca3
  *                                           (0xd451)
- * nct6798d    14      7       7       2+6    0xd458 0xc1    0x5ca3
- *                                           (0xd459)
+ * nct6798d    14      7       7       2+6    0xd428 0xc1    0x5ca3
+ *                                           (0xd429)
  *
  * #temp lists the number of monitored temperature sources (first value) plus
  * the number of directly connectable temperature sensors (second value).
@@ -138,7 +138,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
 #define SIO_NCT6795_ID         0xd350
 #define SIO_NCT6796_ID         0xd420
 #define SIO_NCT6797_ID         0xd450
-#define SIO_NCT6798_ID         0xd458
+#define SIO_NCT6798_ID         0xd428
 #define SIO_ID_MASK            0xFFF8
 
 enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
@@ -3594,7 +3594,8 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
                        fan5pin |= cr1b & BIT(5);
                        fan5pin |= creb & BIT(5);
 
-                       fan6pin = creb & BIT(3);
+                       fan6pin = !dsw_en && (cr2d & BIT(1));
+                       fan6pin |= creb & BIT(3);
 
                        pwm5pin |= cr2d & BIT(7);
                        pwm5pin |= (creb & BIT(4)) && !(cr2a & BIT(0));
@@ -4508,7 +4509,8 @@ static int __maybe_unused nct6775_resume(struct device *dev)
 
        if (data->kind == nct6791 || data->kind == nct6792 ||
            data->kind == nct6793 || data->kind == nct6795 ||
-           data->kind == nct6796)
+           data->kind == nct6796 || data->kind == nct6797 ||
+           data->kind == nct6798)
                nct6791_enable_io_mapping(sioreg);
 
        superio_exit(sioreg);
@@ -4644,7 +4646,8 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
 
        if (sio_data->kind == nct6791 || sio_data->kind == nct6792 ||
            sio_data->kind == nct6793 || sio_data->kind == nct6795 ||
-           sio_data->kind == nct6796)
+           sio_data->kind == nct6796 || sio_data->kind == nct6797 ||
+           sio_data->kind == nct6798)
                nct6791_enable_io_mapping(sioaddr);
 
        superio_exit(sioaddr);
index 423903f..391118c 100644 (file)
@@ -380,8 +380,8 @@ static ssize_t occ_show_power_1(struct device *dev,
                val *= 1000000ULL;
                break;
        case 2:
-               val = get_unaligned_be32(&power->update_tag) *
-                       occ->powr_sample_time_us;
+               val = (u64)get_unaligned_be32(&power->update_tag) *
+                          occ->powr_sample_time_us;
                break;
        case 3:
                val = get_unaligned_be16(&power->value) * 1000000ULL;
@@ -425,8 +425,8 @@ static ssize_t occ_show_power_2(struct device *dev,
                                       &power->update_tag);
                break;
        case 2:
-               val = get_unaligned_be32(&power->update_tag) *
-                       occ->powr_sample_time_us;
+               val = (u64)get_unaligned_be32(&power->update_tag) *
+                          occ->powr_sample_time_us;
                break;
        case 3:
                val = get_unaligned_be16(&power->value) * 1000000ULL;
@@ -463,8 +463,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
                                       &power->system.update_tag);
                break;
        case 2:
-               val = get_unaligned_be32(&power->system.update_tag) *
-                       occ->powr_sample_time_us;
+               val = (u64)get_unaligned_be32(&power->system.update_tag) *
+                          occ->powr_sample_time_us;
                break;
        case 3:
                val = get_unaligned_be16(&power->system.value) * 1000000ULL;
@@ -477,8 +477,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
                                       &power->proc.update_tag);
                break;
        case 6:
-               val = get_unaligned_be32(&power->proc.update_tag) *
-                       occ->powr_sample_time_us;
+               val = (u64)get_unaligned_be32(&power->proc.update_tag) *
+                          occ->powr_sample_time_us;
                break;
        case 7:
                val = get_unaligned_be16(&power->proc.value) * 1000000ULL;
@@ -491,8 +491,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
                                       &power->vdd.update_tag);
                break;
        case 10:
-               val = get_unaligned_be32(&power->vdd.update_tag) *
-                       occ->powr_sample_time_us;
+               val = (u64)get_unaligned_be32(&power->vdd.update_tag) *
+                          occ->powr_sample_time_us;
                break;
        case 11:
                val = get_unaligned_be16(&power->vdd.value) * 1000000ULL;
@@ -505,8 +505,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
                                       &power->vdn.update_tag);
                break;
        case 14:
-               val = get_unaligned_be32(&power->vdn.update_tag) *
-                       occ->powr_sample_time_us;
+               val = (u64)get_unaligned_be32(&power->vdn.update_tag) *
+                          occ->powr_sample_time_us;
                break;
        case 15:
                val = get_unaligned_be16(&power->vdn.value) * 1000000ULL;
index 8844c95..7053be5 100644 (file)
@@ -88,7 +88,7 @@ static const struct of_device_id tmp421_of_match[] = {
                .data = (void *)2
        },
        {
-               .compatible = "ti,tmp422",
+               .compatible = "ti,tmp442",
                .data = (void *)3
        },
        { },
index ec6e69a..d2fbb4b 100644 (file)
@@ -183,6 +183,15 @@ static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev)
        bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c);
 }
 
+static void bcm2835_i2c_finish_transfer(struct bcm2835_i2c_dev *i2c_dev)
+{
+       i2c_dev->curr_msg = NULL;
+       i2c_dev->num_msgs = 0;
+
+       i2c_dev->msg_buf = NULL;
+       i2c_dev->msg_buf_remaining = 0;
+}
+
 /*
  * Note about I2C_C_CLEAR on error:
  * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in
@@ -283,6 +292,9 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
 
        time_left = wait_for_completion_timeout(&i2c_dev->completion,
                                                adap->timeout);
+
+       bcm2835_i2c_finish_transfer(i2c_dev);
+
        if (!time_left) {
                bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C,
                                   BCM2835_I2C_C_CLEAR);
index b136057..d917cef 100644 (file)
@@ -382,8 +382,10 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id)
         * Check for the message size against FIFO depth and set the
         * 'hold bus' bit if it is greater than FIFO depth.
         */
-       if (id->recv_count > CDNS_I2C_FIFO_DEPTH)
+       if ((id->recv_count > CDNS_I2C_FIFO_DEPTH)  || id->bus_hold_flag)
                ctrl_reg |= CDNS_I2C_CR_HOLD;
+       else
+               ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD;
 
        cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
 
@@ -440,8 +442,11 @@ static void cdns_i2c_msend(struct cdns_i2c *id)
         * Check for the message size against FIFO depth and set the
         * 'hold bus' bit if it is greater than FIFO depth.
         */
-       if (id->send_count > CDNS_I2C_FIFO_DEPTH)
+       if ((id->send_count > CDNS_I2C_FIFO_DEPTH) || id->bus_hold_flag)
                ctrl_reg |= CDNS_I2C_CR_HOLD;
+       else
+               ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD;
+
        cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
 
        /* Clear the interrupts in interrupt status register. */
index b1086bf..cd9c65f 100644 (file)
@@ -1500,8 +1500,7 @@ static int omap_i2c_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int omap_i2c_runtime_suspend(struct device *dev)
+static int __maybe_unused omap_i2c_runtime_suspend(struct device *dev)
 {
        struct omap_i2c_dev *omap = dev_get_drvdata(dev);
 
@@ -1527,7 +1526,7 @@ static int omap_i2c_runtime_suspend(struct device *dev)
        return 0;
 }
 
-static int omap_i2c_runtime_resume(struct device *dev)
+static int __maybe_unused omap_i2c_runtime_resume(struct device *dev)
 {
        struct omap_i2c_dev *omap = dev_get_drvdata(dev);
 
@@ -1542,20 +1541,18 @@ static int omap_i2c_runtime_resume(struct device *dev)
 }
 
 static const struct dev_pm_ops omap_i2c_pm_ops = {
+       SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+                                     pm_runtime_force_resume)
        SET_RUNTIME_PM_OPS(omap_i2c_runtime_suspend,
                           omap_i2c_runtime_resume, NULL)
 };
-#define OMAP_I2C_PM_OPS (&omap_i2c_pm_ops)
-#else
-#define OMAP_I2C_PM_OPS NULL
-#endif /* CONFIG_PM */
 
 static struct platform_driver omap_i2c_driver = {
        .probe          = omap_i2c_probe,
        .remove         = omap_i2c_remove,
        .driver         = {
                .name   = "omap_i2c",
-               .pm     = OMAP_I2C_PM_OPS,
+               .pm     = &omap_i2c_pm_ops,
                .of_match_table = of_match_ptr(omap_i2c_of_match),
        },
 };
index e417ebf..c77adbb 100644 (file)
@@ -155,6 +155,8 @@ enum msg_end_type {
  * @has_mst_fifo: The I2C controller contains the new MST FIFO interface that
  *             provides additional features and allows for longer messages to
  *             be transferred in one go.
+ * @quirks: i2c adapter quirks for limiting write/read transfer size and not
+ *             allowing 0 length transfers.
  */
 struct tegra_i2c_hw_feature {
        bool has_continue_xfer_support;
@@ -167,6 +169,7 @@ struct tegra_i2c_hw_feature {
        bool has_multi_master_mode;
        bool has_slcg_override_reg;
        bool has_mst_fifo;
+       const struct i2c_adapter_quirks *quirks;
 };
 
 /**
@@ -837,6 +840,10 @@ static const struct i2c_adapter_quirks tegra_i2c_quirks = {
        .max_write_len = 4096,
 };
 
+static const struct i2c_adapter_quirks tegra194_i2c_quirks = {
+       .flags = I2C_AQ_NO_ZERO_LEN,
+};
+
 static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
        .has_continue_xfer_support = false,
        .has_per_pkt_xfer_complete_irq = false,
@@ -848,6 +855,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
        .has_multi_master_mode = false,
        .has_slcg_override_reg = false,
        .has_mst_fifo = false,
+       .quirks = &tegra_i2c_quirks,
 };
 
 static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
@@ -861,6 +869,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
        .has_multi_master_mode = false,
        .has_slcg_override_reg = false,
        .has_mst_fifo = false,
+       .quirks = &tegra_i2c_quirks,
 };
 
 static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
@@ -874,6 +883,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
        .has_multi_master_mode = false,
        .has_slcg_override_reg = false,
        .has_mst_fifo = false,
+       .quirks = &tegra_i2c_quirks,
 };
 
 static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
@@ -887,6 +897,7 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
        .has_multi_master_mode = false,
        .has_slcg_override_reg = true,
        .has_mst_fifo = false,
+       .quirks = &tegra_i2c_quirks,
 };
 
 static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
@@ -900,6 +911,7 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
        .has_multi_master_mode = true,
        .has_slcg_override_reg = true,
        .has_mst_fifo = false,
+       .quirks = &tegra_i2c_quirks,
 };
 
 static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
@@ -913,6 +925,7 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
        .has_multi_master_mode = true,
        .has_slcg_override_reg = true,
        .has_mst_fifo = true,
+       .quirks = &tegra194_i2c_quirks,
 };
 
 /* Match table for of_platform binding */
@@ -964,7 +977,6 @@ static int tegra_i2c_probe(struct platform_device *pdev)
        i2c_dev->base = base;
        i2c_dev->div_clk = div_clk;
        i2c_dev->adapter.algo = &tegra_i2c_algo;
-       i2c_dev->adapter.quirks = &tegra_i2c_quirks;
        i2c_dev->irq = irq;
        i2c_dev->cont_id = pdev->id;
        i2c_dev->dev = &pdev->dev;
@@ -980,6 +992,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
        i2c_dev->hw = of_device_get_match_data(&pdev->dev);
        i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node,
                                                  "nvidia,tegra20-i2c-dvc");
+       i2c_dev->adapter.quirks = i2c_dev->hw->quirks;
        init_completion(&i2c_dev->msg_complete);
        spin_lock_init(&i2c_dev->xfer_lock);
 
index 1aca742..ccd76c7 100644 (file)
@@ -470,9 +470,15 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                                          data_arg.data);
        }
        case I2C_RETRIES:
+               if (arg > INT_MAX)
+                       return -EINVAL;
+
                client->adapter->retries = arg;
                break;
        case I2C_TIMEOUT:
+               if (arg > INT_MAX)
+                       return -EINVAL;
+
                /* For historical reasons, user-space sets the timeout
                 * value in units of 10 ms.
                 */
index c39f89d..2dc628d 100644 (file)
@@ -1828,7 +1828,7 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
 
        ret = i3c_master_retrieve_dev_info(newdev);
        if (ret)
-               goto err_free_dev;
+               goto err_detach_dev;
 
        olddev = i3c_master_search_i3c_dev_duplicate(newdev);
        if (olddev) {
index b532e2c..bb03079 100644 (file)
@@ -419,12 +419,9 @@ static void dw_i3c_master_enqueue_xfer(struct dw_i3c_master *master,
        spin_unlock_irqrestore(&master->xferqueue.lock, flags);
 }
 
-static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master,
-                                      struct dw_i3c_xfer *xfer)
+static void dw_i3c_master_dequeue_xfer_locked(struct dw_i3c_master *master,
+                                             struct dw_i3c_xfer *xfer)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&master->xferqueue.lock, flags);
        if (master->xferqueue.cur == xfer) {
                u32 status;
 
@@ -439,6 +436,15 @@ static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master,
        } else {
                list_del_init(&xfer->node);
        }
+}
+
+static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master,
+                                      struct dw_i3c_xfer *xfer)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&master->xferqueue.lock, flags);
+       dw_i3c_master_dequeue_xfer_locked(master, xfer);
        spin_unlock_irqrestore(&master->xferqueue.lock, flags);
 }
 
@@ -494,7 +500,7 @@ static void dw_i3c_master_end_xfer_locked(struct dw_i3c_master *master, u32 isr)
        complete(&xfer->comp);
 
        if (ret < 0) {
-               dw_i3c_master_dequeue_xfer(master, xfer);
+               dw_i3c_master_dequeue_xfer_locked(master, xfer);
                writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_RESUME,
                       master->regs + DEVICE_CTRL);
        }
@@ -901,9 +907,6 @@ static int dw_i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
               master->regs +
               DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));
 
-       if (!old_dyn_addr)
-               return 0;
-
        master->addrs[data->index] = dev->info.dyn_addr;
 
        return 0;
@@ -925,11 +928,11 @@ static int dw_i3c_master_attach_i3c_dev(struct i3c_dev_desc *dev)
                return -ENOMEM;
 
        data->index = pos;
-       master->addrs[pos] = dev->info.dyn_addr;
+       master->addrs[pos] = dev->info.dyn_addr ? : dev->info.static_addr;
        master->free_pos &= ~BIT(pos);
        i3c_dev_set_master_data(dev, data);
 
-       writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(dev->info.dyn_addr),
+       writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(master->addrs[pos]),
               master->regs +
               DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));
 
index bbd79b8..8889a4f 100644 (file)
@@ -1556,8 +1556,8 @@ static int cdns_i3c_master_probe(struct platform_device *pdev)
                return PTR_ERR(master->pclk);
 
        master->sysclk = devm_clk_get(&pdev->dev, "sysclk");
-       if (IS_ERR(master->pclk))
-               return PTR_ERR(master->pclk);
+       if (IS_ERR(master->sysclk))
+               return PTR_ERR(master->sysclk);
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0)
index da58020..33a28cd 100644 (file)
@@ -235,21 +235,28 @@ EXPORT_SYMBOL_GPL(ide_prep_sense);
 
 int ide_queue_sense_rq(ide_drive_t *drive, void *special)
 {
-       struct request *sense_rq = drive->sense_rq;
+       ide_hwif_t *hwif = drive->hwif;
+       struct request *sense_rq;
+       unsigned long flags;
+
+       spin_lock_irqsave(&hwif->lock, flags);
 
        /* deferred failure from ide_prep_sense() */
        if (!drive->sense_rq_armed) {
                printk(KERN_WARNING PFX "%s: error queuing a sense request\n",
                       drive->name);
+               spin_unlock_irqrestore(&hwif->lock, flags);
                return -ENOMEM;
        }
 
+       sense_rq = drive->sense_rq;
        ide_req(sense_rq)->special = special;
        drive->sense_rq_armed = false;
 
        drive->hwif->rq = NULL;
 
        ide_insert_request_head(drive, sense_rq);
+       spin_unlock_irqrestore(&hwif->lock, flags);
        return 0;
 }
 EXPORT_SYMBOL_GPL(ide_queue_sense_rq);
index 8445b48..b137f27 100644 (file)
@@ -68,8 +68,10 @@ int ide_end_rq(ide_drive_t *drive, struct request *rq, blk_status_t error,
        }
 
        if (!blk_update_request(rq, error, nr_bytes)) {
-               if (rq == drive->sense_rq)
+               if (rq == drive->sense_rq) {
                        drive->sense_rq = NULL;
+                       drive->sense_rq_active = false;
+               }
 
                __blk_mq_end_request(rq, error);
                return 0;
@@ -451,16 +453,11 @@ void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq)
                blk_mq_delay_run_hw_queue(q->queue_hw_ctx[0], 3);
 }
 
-/*
- * Issue a new request to a device.
- */
-blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx,
-                         const struct blk_mq_queue_data *bd)
+blk_status_t ide_issue_rq(ide_drive_t *drive, struct request *rq,
+                         bool local_requeue)
 {
-       ide_drive_t     *drive = hctx->queue->queuedata;
-       ide_hwif_t      *hwif = drive->hwif;
+       ide_hwif_t *hwif = drive->hwif;
        struct ide_host *host = hwif->host;
-       struct request  *rq = bd->rq;
        ide_startstop_t startstop;
 
        if (!blk_rq_is_passthrough(rq) && !(rq->rq_flags & RQF_DONTPREP)) {
@@ -474,8 +471,6 @@ blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx,
        if (ide_lock_host(host, hwif))
                return BLK_STS_DEV_RESOURCE;
 
-       blk_mq_start_request(rq);
-
        spin_lock_irq(&hwif->lock);
 
        if (!ide_lock_port(hwif)) {
@@ -511,18 +506,6 @@ repeat:
                drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED);
 
                /*
-                * we know that the queue isn't empty, but this can happen
-                * if ->prep_rq() decides to kill a request
-                */
-               if (!rq) {
-                       rq = bd->rq;
-                       if (!rq) {
-                               ide_unlock_port(hwif);
-                               goto out;
-                       }
-               }
-
-               /*
                 * Sanity: don't accept a request that isn't a PM request
                 * if we are currently power managed. This is very important as
                 * blk_stop_queue() doesn't prevent the blk_fetch_request()
@@ -560,9 +543,12 @@ repeat:
                }
        } else {
 plug_device:
+               if (local_requeue)
+                       list_add(&rq->queuelist, &drive->rq_list);
                spin_unlock_irq(&hwif->lock);
                ide_unlock_host(host);
-               ide_requeue_and_plug(drive, rq);
+               if (!local_requeue)
+                       ide_requeue_and_plug(drive, rq);
                return BLK_STS_OK;
        }
 
@@ -573,6 +559,26 @@ out:
        return BLK_STS_OK;
 }
 
+/*
+ * Issue a new request to a device.
+ */
+blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx,
+                         const struct blk_mq_queue_data *bd)
+{
+       ide_drive_t *drive = hctx->queue->queuedata;
+       ide_hwif_t *hwif = drive->hwif;
+
+       spin_lock_irq(&hwif->lock);
+       if (drive->sense_rq_active) {
+               spin_unlock_irq(&hwif->lock);
+               return BLK_STS_DEV_RESOURCE;
+       }
+       spin_unlock_irq(&hwif->lock);
+
+       blk_mq_start_request(bd->rq);
+       return ide_issue_rq(drive, bd->rq, false);
+}
+
 static int drive_is_ready(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
@@ -893,13 +899,8 @@ EXPORT_SYMBOL_GPL(ide_pad_transfer);
 
 void ide_insert_request_head(ide_drive_t *drive, struct request *rq)
 {
-       ide_hwif_t *hwif = drive->hwif;
-       unsigned long flags;
-
-       spin_lock_irqsave(&hwif->lock, flags);
+       drive->sense_rq_active = true;
        list_add_tail(&rq->queuelist, &drive->rq_list);
-       spin_unlock_irqrestore(&hwif->lock, flags);
-
        kblockd_schedule_work(&drive->rq_work);
 }
 EXPORT_SYMBOL_GPL(ide_insert_request_head);
index 102aa3b..8af7af6 100644 (file)
@@ -54,7 +54,9 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
        scsi_req(rq)->cmd[0] = REQ_UNPARK_HEADS;
        scsi_req(rq)->cmd_len = 1;
        ide_req(rq)->type = ATA_PRIV_MISC;
+       spin_lock_irq(&hwif->lock);
        ide_insert_request_head(drive, rq);
+       spin_unlock_irq(&hwif->lock);
 
 out:
        return;
index 63627be..5aeaca2 100644 (file)
@@ -1159,18 +1159,27 @@ static void drive_rq_insert_work(struct work_struct *work)
        ide_drive_t *drive = container_of(work, ide_drive_t, rq_work);
        ide_hwif_t *hwif = drive->hwif;
        struct request *rq;
+       blk_status_t ret;
        LIST_HEAD(list);
 
-       spin_lock_irq(&hwif->lock);
-       if (!list_empty(&drive->rq_list))
-               list_splice_init(&drive->rq_list, &list);
-       spin_unlock_irq(&hwif->lock);
+       blk_mq_quiesce_queue(drive->queue);
 
-       while (!list_empty(&list)) {
-               rq = list_first_entry(&list, struct request, queuelist);
+       ret = BLK_STS_OK;
+       spin_lock_irq(&hwif->lock);
+       while (!list_empty(&drive->rq_list)) {
+               rq = list_first_entry(&drive->rq_list, struct request, queuelist);
                list_del_init(&rq->queuelist);
-               blk_execute_rq_nowait(drive->queue, rq->rq_disk, rq, true, NULL);
+
+               spin_unlock_irq(&hwif->lock);
+               ret = ide_issue_rq(drive, rq, true);
+               spin_lock_irq(&hwif->lock);
        }
+       spin_unlock_irq(&hwif->lock);
+
+       blk_mq_unquiesce_queue(drive->queue);
+
+       if (ret != BLK_STS_OK)
+               kblockd_schedule_work(&drive->rq_work);
 }
 
 static const u8 ide_hwif_to_major[] =
index 4c8c7a6..a5dc135 100644 (file)
@@ -544,7 +544,7 @@ void ide_proc_port_register_devices(ide_hwif_t *hwif)
                drive->proc = proc_mkdir(drive->name, parent);
                if (drive->proc) {
                        ide_add_proc_entries(drive->proc, generic_drive_entries, drive);
-                       proc_create_data("setting", S_IFREG|S_IRUSR|S_IWUSR,
+                       proc_create_data("settings", S_IFREG|S_IRUSR|S_IWUSR,
                                        drive->proc, &ide_settings_proc_fops,
                                        drive);
                }
index 031d568..4e339cf 100644 (file)
 #include <linux/iio/machine.h>
 #include <linux/iio/driver.h>
 
-#define AXP288_ADC_EN_MASK             0xF1
-#define AXP288_ADC_TS_PIN_GPADC                0xF2
-#define AXP288_ADC_TS_PIN_ON           0xF3
+/*
+ * This mask enables all ADCs except for the battery temp-sensor (TS), that is
+ * left as-is to avoid breaking charging on devices without a temp-sensor.
+ */
+#define AXP288_ADC_EN_MASK                             0xF0
+#define AXP288_ADC_TS_ENABLE                           0x01
+
+#define AXP288_ADC_TS_CURRENT_ON_OFF_MASK              GENMASK(1, 0)
+#define AXP288_ADC_TS_CURRENT_OFF                      (0 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_WHEN_CHARGING         (1 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_ONDEMAND              (2 << 0)
+#define AXP288_ADC_TS_CURRENT_ON                       (3 << 0)
 
 enum axp288_adc_id {
        AXP288_ADC_TS,
@@ -44,6 +53,7 @@ enum axp288_adc_id {
 struct axp288_adc_info {
        int irq;
        struct regmap *regmap;
+       bool ts_enabled;
 };
 
 static const struct iio_chan_spec axp288_adc_channels[] = {
@@ -115,21 +125,33 @@ static int axp288_adc_read_channel(int *val, unsigned long address,
        return IIO_VAL_INT;
 }
 
-static int axp288_adc_set_ts(struct regmap *regmap, unsigned int mode,
-                               unsigned long address)
+/*
+ * The current-source used for the battery temp-sensor (TS) is shared
+ * with the GPADC. For proper fuel-gauge and charger operation the TS
+ * current-source needs to be permanently on. But to read the GPADC we
+ * need to temporary switch the TS current-source to ondemand, so that
+ * the GPADC can use it, otherwise we will always read an all 0 value.
+ */
+static int axp288_adc_set_ts(struct axp288_adc_info *info,
+                            unsigned int mode, unsigned long address)
 {
        int ret;
 
-       /* channels other than GPADC do not need to switch TS pin */
+       /* No need to switch the current-source if the TS pin is disabled */
+       if (!info->ts_enabled)
+               return 0;
+
+       /* Channels other than GPADC do not need the current source */
        if (address != AXP288_GP_ADC_H)
                return 0;
 
-       ret = regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, mode);
+       ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL,
+                                AXP288_ADC_TS_CURRENT_ON_OFF_MASK, mode);
        if (ret)
                return ret;
 
        /* When switching to the GPADC pin give things some time to settle */
-       if (mode == AXP288_ADC_TS_PIN_GPADC)
+       if (mode == AXP288_ADC_TS_CURRENT_ON_ONDEMAND)
                usleep_range(6000, 10000);
 
        return 0;
@@ -145,14 +167,14 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev,
        mutex_lock(&indio_dev->mlock);
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
-               if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_GPADC,
+               if (axp288_adc_set_ts(info, AXP288_ADC_TS_CURRENT_ON_ONDEMAND,
                                        chan->address)) {
                        dev_err(&indio_dev->dev, "GPADC mode\n");
                        ret = -EINVAL;
                        break;
                }
                ret = axp288_adc_read_channel(val, chan->address, info->regmap);
-               if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_ON,
+               if (axp288_adc_set_ts(info, AXP288_ADC_TS_CURRENT_ON,
                                                chan->address))
                        dev_err(&indio_dev->dev, "TS pin restore\n");
                break;
@@ -164,13 +186,35 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev,
        return ret;
 }
 
-static int axp288_adc_set_state(struct regmap *regmap)
+static int axp288_adc_initialize(struct axp288_adc_info *info)
 {
-       /* ADC should be always enabled for internal FG to function */
-       if (regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON))
-               return -EIO;
+       int ret, adc_enable_val;
+
+       /*
+        * Determine if the TS pin is enabled and set the TS current-source
+        * accordingly.
+        */
+       ret = regmap_read(info->regmap, AXP20X_ADC_EN1, &adc_enable_val);
+       if (ret)
+               return ret;
+
+       if (adc_enable_val & AXP288_ADC_TS_ENABLE) {
+               info->ts_enabled = true;
+               ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL,
+                                        AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+                                        AXP288_ADC_TS_CURRENT_ON);
+       } else {
+               info->ts_enabled = false;
+               ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL,
+                                        AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+                                        AXP288_ADC_TS_CURRENT_OFF);
+       }
+       if (ret)
+               return ret;
 
-       return regmap_write(regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK);
+       /* Turn on the ADC for all channels except TS, leave TS as is */
+       return regmap_update_bits(info->regmap, AXP20X_ADC_EN1,
+                                 AXP288_ADC_EN_MASK, AXP288_ADC_EN_MASK);
 }
 
 static const struct iio_info axp288_adc_iio_info = {
@@ -200,7 +244,7 @@ static int axp288_adc_probe(struct platform_device *pdev)
         * Set ADC to enabled state at all time, including system suspend.
         * otherwise internal fuel gauge functionality may be affected.
         */
-       ret = axp288_adc_set_state(axp20x->regmap);
+       ret = axp288_adc_initialize(info);
        if (ret) {
                dev_err(&pdev->dev, "unable to enable ADC device\n");
                return ret;
index 184d686..8b4568e 100644 (file)
@@ -41,6 +41,7 @@
 
 #define ADS8688_VREF_MV                        4096
 #define ADS8688_REALBITS               16
+#define ADS8688_MAX_CHANNELS           8
 
 /*
  * enum ads8688_range - ADS8688 reference voltage range
@@ -385,7 +386,7 @@ static irqreturn_t ads8688_trigger_handler(int irq, void *p)
 {
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
-       u16 buffer[8];
+       u16 buffer[ADS8688_MAX_CHANNELS + sizeof(s64)/sizeof(u16)];
        int i, j = 0;
 
        for (i = 0; i < indio_dev->masklength; i++) {
index cafb1dc..9d984f2 100644 (file)
@@ -142,7 +142,10 @@ static void tiadc_step_config(struct iio_dev *indio_dev)
                        stepconfig |= STEPCONFIG_MODE_SWCNT;
 
                tiadc_writel(adc_dev, REG_STEPCONFIG(steps),
-                               stepconfig | STEPCONFIG_INP(chan));
+                               stepconfig | STEPCONFIG_INP(chan) |
+                               STEPCONFIG_INM_ADCREFM |
+                               STEPCONFIG_RFP_VREFP |
+                               STEPCONFIG_RFM_VREFN);
 
                if (adc_dev->open_delay[i] > STEPDELAY_OPEN_MASK) {
                        dev_warn(dev, "chan %d open delay truncating to 0x3FFFF\n",
index a406ad3..3a20cb5 100644 (file)
@@ -444,9 +444,8 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_TEMP:
-                       *val = 1; /* 0.01 */
-                       *val2 = 100;
-                       break;
+                       *val = 10;
+                       return IIO_VAL_INT;
                case IIO_PH:
                        *val = 1; /* 0.001 */
                        *val2 = 1000;
@@ -477,7 +476,7 @@ static int atlas_write_raw(struct iio_dev *indio_dev,
                           int val, int val2, long mask)
 {
        struct atlas_data *data = iio_priv(indio_dev);
-       __be32 reg = cpu_to_be32(val);
+       __be32 reg = cpu_to_be32(val / 10);
 
        if (val2 != 0 || val < 0 || val > 20000)
                return -EINVAL;
index 63a7cc0..84f077b 100644 (file)
@@ -494,7 +494,10 @@ static void _cma_attach_to_dev(struct rdma_id_private *id_priv,
        id_priv->id.route.addr.dev_addr.transport =
                rdma_node_get_transport(cma_dev->device->node_type);
        list_add_tail(&id_priv->list, &cma_dev->id_list);
-       rdma_restrack_kadd(&id_priv->res);
+       if (id_priv->res.kern_name)
+               rdma_restrack_kadd(&id_priv->res);
+       else
+               rdma_restrack_uadd(&id_priv->res);
 }
 
 static void cma_attach_to_dev(struct rdma_id_private *id_priv,
index 3cd830d..6167343 100644 (file)
@@ -267,7 +267,6 @@ static inline int ib_mad_enforce_security(struct ib_mad_agent_private *map,
 #endif
 
 struct ib_device *ib_device_get_by_index(u32 ifindex);
-void ib_device_put(struct ib_device *device);
 /* RDMA device netlink */
 void nldev_init(void);
 void nldev_exit(void);
index 8872453..238ec42 100644 (file)
@@ -156,19 +156,26 @@ struct ib_device *ib_device_get_by_index(u32 index)
        down_read(&lists_rwsem);
        device = __ib_device_get_by_index(index);
        if (device) {
-               /* Do not return a device if unregistration has started. */
-               if (!refcount_inc_not_zero(&device->refcount))
+               if (!ib_device_try_get(device))
                        device = NULL;
        }
        up_read(&lists_rwsem);
        return device;
 }
 
+/**
+ * ib_device_put - Release IB device reference
+ * @device: device whose reference to be released
+ *
+ * ib_device_put() releases reference to the IB device to allow it to be
+ * unregistered and eventually free.
+ */
 void ib_device_put(struct ib_device *device)
 {
        if (refcount_dec_and_test(&device->refcount))
                complete(&device->unreg_completion);
 }
+EXPORT_SYMBOL(ib_device_put);
 
 static struct ib_device *__ib_device_get_by_name(const char *name)
 {
@@ -303,7 +310,6 @@ struct ib_device *ib_alloc_device(size_t size)
        rwlock_init(&device->client_data_lock);
        INIT_LIST_HEAD(&device->client_data_list);
        INIT_LIST_HEAD(&device->port_list);
-       refcount_set(&device->refcount, 1);
        init_completion(&device->unreg_completion);
 
        return device;
@@ -620,6 +626,7 @@ int ib_register_device(struct ib_device *device, const char *name,
                goto cg_cleanup;
        }
 
+       refcount_set(&device->refcount, 1);
        device->reg_state = IB_DEV_REGISTERED;
 
        list_for_each_entry(client, &client_list, list)
index e600fc2..3c97a8b 100644 (file)
@@ -584,10 +584,6 @@ static int fill_res_pd_entry(struct sk_buff *msg, struct netlink_callback *cb,
        if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_RES_USECNT,
                              atomic_read(&pd->usecnt), RDMA_NLDEV_ATTR_PAD))
                goto err;
-       if ((pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY) &&
-           nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY,
-                       pd->unsafe_global_rkey))
-               goto err;
 
        if (fill_res_name_pid(msg, res))
                goto err;
index be6b8e1..69f8db6 100644 (file)
@@ -106,6 +106,8 @@ int uverbs_finalize_object(struct ib_uobject *uobj,
                           enum uverbs_obj_access access,
                           bool commit);
 
+int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx);
+
 void setup_ufile_idr_uobject(struct ib_uverbs_file *ufile);
 void release_ufile_idr_uobject(struct ib_uverbs_file *ufile);
 
index a4ec430..acb882f 100644 (file)
@@ -352,6 +352,8 @@ struct ib_umem_odp *ib_alloc_odp_umem(struct ib_ucontext_per_mm *per_mm,
        umem->writable   = 1;
        umem->is_odp = 1;
        odp_data->per_mm = per_mm;
+       umem->owning_mm  = per_mm->mm;
+       mmgrab(umem->owning_mm);
 
        mutex_init(&odp_data->umem_mutex);
        init_completion(&odp_data->notifier_completion);
@@ -384,6 +386,7 @@ struct ib_umem_odp *ib_alloc_odp_umem(struct ib_ucontext_per_mm *per_mm,
 out_page_list:
        vfree(odp_data->page_list);
 out_odp_data:
+       mmdrop(umem->owning_mm);
        kfree(odp_data);
        return ERR_PTR(ret);
 }
index 6b12cc5..3317300 100644 (file)
@@ -60,6 +60,10 @@ static int uverbs_response(struct uverbs_attr_bundle *attrs, const void *resp,
 {
        int ret;
 
+       if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_CORE_OUT))
+               return uverbs_copy_to_struct_or_zero(
+                       attrs, UVERBS_ATTR_CORE_OUT, resp, resp_len);
+
        if (copy_to_user(attrs->ucore.outbuf, resp,
                         min(attrs->ucore.outlen, resp_len)))
                return -EFAULT;
@@ -1181,6 +1185,9 @@ static int ib_uverbs_poll_cq(struct uverbs_attr_bundle *attrs)
                goto out_put;
        }
 
+       if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_CORE_OUT))
+               ret = uverbs_output_written(attrs, UVERBS_ATTR_CORE_OUT);
+
        ret = 0;
 
 out_put:
@@ -2012,8 +2019,10 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs)
                return -ENOMEM;
 
        qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
-       if (!qp)
+       if (!qp) {
+               ret = -EINVAL;
                goto out;
+       }
 
        is_ud = qp->qp_type == IB_QPT_UD;
        sg_ind = 0;
index 8c81ff6..0ca04d2 100644 (file)
@@ -144,6 +144,21 @@ static bool uverbs_is_attr_cleared(const struct ib_uverbs_attr *uattr,
                           0, uattr->len - len);
 }
 
+static int uverbs_set_output(const struct uverbs_attr_bundle *bundle,
+                            const struct uverbs_attr *attr)
+{
+       struct bundle_priv *pbundle =
+               container_of(bundle, struct bundle_priv, bundle);
+       u16 flags;
+
+       flags = pbundle->uattrs[attr->ptr_attr.uattr_idx].flags |
+               UVERBS_ATTR_F_VALID_OUTPUT;
+       if (put_user(flags,
+                    &pbundle->user_attrs[attr->ptr_attr.uattr_idx].flags))
+               return -EFAULT;
+       return 0;
+}
+
 static int uverbs_process_idrs_array(struct bundle_priv *pbundle,
                                     const struct uverbs_api_attr *attr_uapi,
                                     struct uverbs_objs_arr_attr *attr,
@@ -456,6 +471,19 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
        }
 
        /*
+        * Until the drivers are revised to use the bundle directly we have to
+        * assume that the driver wrote to its UHW_OUT and flag userspace
+        * appropriately.
+        */
+       if (!ret && pbundle->method_elm->has_udata) {
+               const struct uverbs_attr *attr =
+                       uverbs_attr_get(&pbundle->bundle, UVERBS_ATTR_UHW_OUT);
+
+               if (!IS_ERR(attr))
+                       ret = uverbs_set_output(&pbundle->bundle, attr);
+       }
+
+       /*
         * EPROTONOSUPPORT is ONLY to be returned if the ioctl framework can
         * not invoke the method because the request is not supported.  No
         * other cases should return this code.
@@ -706,10 +734,7 @@ void uverbs_fill_udata(struct uverbs_attr_bundle *bundle,
 int uverbs_copy_to(const struct uverbs_attr_bundle *bundle, size_t idx,
                   const void *from, size_t size)
 {
-       struct bundle_priv *pbundle =
-               container_of(bundle, struct bundle_priv, bundle);
        const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx);
-       u16 flags;
        size_t min_size;
 
        if (IS_ERR(attr))
@@ -719,16 +744,25 @@ int uverbs_copy_to(const struct uverbs_attr_bundle *bundle, size_t idx,
        if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size))
                return -EFAULT;
 
-       flags = pbundle->uattrs[attr->ptr_attr.uattr_idx].flags |
-               UVERBS_ATTR_F_VALID_OUTPUT;
-       if (put_user(flags,
-                    &pbundle->user_attrs[attr->ptr_attr.uattr_idx].flags))
-               return -EFAULT;
-
-       return 0;
+       return uverbs_set_output(bundle, attr);
 }
 EXPORT_SYMBOL(uverbs_copy_to);
 
+
+/*
+ * This is only used if the caller has directly used copy_to_use to write the
+ * data.  It signals to user space that the buffer is filled in.
+ */
+int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx)
+{
+       const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx);
+
+       if (IS_ERR(attr))
+               return PTR_ERR(attr);
+
+       return uverbs_set_output(bundle, attr);
+}
+
 int _uverbs_get_const(s64 *to, const struct uverbs_attr_bundle *attrs_bundle,
                      size_t idx, s64 lower_bound, u64 upper_bound,
                      s64  *def_val)
@@ -757,8 +791,10 @@ int uverbs_copy_to_struct_or_zero(const struct uverbs_attr_bundle *bundle,
 {
        const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx);
 
-       if (clear_user(u64_to_user_ptr(attr->ptr_attr.data),
-                      attr->ptr_attr.len))
-               return -EFAULT;
+       if (size < attr->ptr_attr.len) {
+               if (clear_user(u64_to_user_ptr(attr->ptr_attr.data) + size,
+                              attr->ptr_attr.len - size))
+                       return -EFAULT;
+       }
        return uverbs_copy_to(bundle, idx, from, size);
 }
index fb0007a..5f36683 100644 (file)
@@ -204,6 +204,9 @@ void ib_uverbs_release_file(struct kref *ref)
        if (atomic_dec_and_test(&file->device->refcount))
                ib_uverbs_comp_dev(file->device);
 
+       if (file->async_file)
+               kref_put(&file->async_file->ref,
+                        ib_uverbs_release_async_event_file);
        put_device(&file->device->dev);
        kfree(file);
 }
@@ -690,6 +693,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
 
        buf += sizeof(hdr);
 
+       memset(bundle.attr_present, 0, sizeof(bundle.attr_present));
        bundle.ufile = file;
        if (!method_elm->is_ex) {
                size_t in_len = hdr.in_words * 4 - sizeof(hdr);
@@ -963,11 +967,19 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
 
                /* Get an arbitrary mm pointer that hasn't been cleaned yet */
                mutex_lock(&ufile->umap_lock);
-               if (!list_empty(&ufile->umaps)) {
-                       mm = list_first_entry(&ufile->umaps,
-                                             struct rdma_umap_priv, list)
-                                    ->vma->vm_mm;
-                       mmget(mm);
+               while (!list_empty(&ufile->umaps)) {
+                       int ret;
+
+                       priv = list_first_entry(&ufile->umaps,
+                                               struct rdma_umap_priv, list);
+                       mm = priv->vma->vm_mm;
+                       ret = mmget_not_zero(mm);
+                       if (!ret) {
+                               list_del_init(&priv->list);
+                               mm = NULL;
+                               continue;
+                       }
+                       break;
                }
                mutex_unlock(&ufile->umap_lock);
                if (!mm)
@@ -1095,10 +1107,6 @@ static int ib_uverbs_close(struct inode *inode, struct file *filp)
        list_del_init(&file->list);
        mutex_unlock(&file->device->lists_mutex);
 
-       if (file->async_file)
-               kref_put(&file->async_file->ref,
-                        ib_uverbs_release_async_event_file);
-
        kref_put(&file->ref, ib_uverbs_release_file);
 
        return 0;
index 5030ec4..2a3f2f0 100644 (file)
@@ -168,12 +168,18 @@ void copy_port_attr_to_resp(struct ib_port_attr *attr,
 static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_PORT)(
        struct uverbs_attr_bundle *attrs)
 {
-       struct ib_device *ib_dev = attrs->ufile->device->ib_dev;
+       struct ib_device *ib_dev;
        struct ib_port_attr attr = {};
        struct ib_uverbs_query_port_resp_ex resp = {};
+       struct ib_ucontext *ucontext;
        int ret;
        u8 port_num;
 
+       ucontext = ib_uverbs_get_ucontext(attrs);
+       if (IS_ERR(ucontext))
+               return PTR_ERR(ucontext);
+       ib_dev = ucontext->device;
+
        /* FIXME: Extend the UAPI_DEF_OBJ_NEEDS_FN stuff.. */
        if (!ib_dev->ops.query_port)
                return -EOPNOTSUPP;
index 3268054..19551aa 100644 (file)
@@ -766,8 +766,8 @@ struct bnxt_qplib_rcfw_sbuf *bnxt_qplib_rcfw_alloc_sbuf(
                return NULL;
 
        sbuf->size = size;
-       sbuf->sb = dma_zalloc_coherent(&rcfw->pdev->dev, sbuf->size,
-                                      &sbuf->dma_addr, GFP_ATOMIC);
+       sbuf->sb = dma_alloc_coherent(&rcfw->pdev->dev, sbuf->size,
+                                     &sbuf->dma_addr, GFP_ATOMIC);
        if (!sbuf->sb)
                goto bail;
 
index 59eeac5..57d4951 100644 (file)
@@ -105,10 +105,10 @@ static int __alloc_pbl(struct pci_dev *pdev, struct bnxt_qplib_pbl *pbl,
 
        if (!sghead) {
                for (i = 0; i < pages; i++) {
-                       pbl->pg_arr[i] = dma_zalloc_coherent(&pdev->dev,
-                                                            pbl->pg_size,
-                                                            &pbl->pg_map_arr[i],
-                                                            GFP_KERNEL);
+                       pbl->pg_arr[i] = dma_alloc_coherent(&pdev->dev,
+                                                           pbl->pg_size,
+                                                           &pbl->pg_map_arr[i],
+                                                           GFP_KERNEL);
                        if (!pbl->pg_arr[i])
                                goto fail;
                        pbl->pg_count++;
index df4f7a3..8ac72ac 100644 (file)
@@ -291,9 +291,9 @@ int cxio_create_qp(struct cxio_rdev *rdev_p, u32 kernel_domain,
        if (!wq->sq)
                goto err3;
 
-       wq->queue = dma_zalloc_coherent(&(rdev_p->rnic_info.pdev->dev),
-                                            depth * sizeof(union t3_wr),
-                                            &(wq->dma_addr), GFP_KERNEL);
+       wq->queue = dma_alloc_coherent(&(rdev_p->rnic_info.pdev->dev),
+                                      depth * sizeof(union t3_wr),
+                                      &(wq->dma_addr), GFP_KERNEL);
        if (!wq->queue)
                goto err4;
 
index 981ff5c..504cf52 100644 (file)
@@ -2564,9 +2564,8 @@ static int alloc_srq_queue(struct c4iw_srq *srq, struct c4iw_dev_ucontext *uctx,
        wq->rqt_abs_idx = (wq->rqt_hwaddr - rdev->lldi.vr->rq.start) >>
                T4_RQT_ENTRY_SHIFT;
 
-       wq->queue = dma_zalloc_coherent(&rdev->lldi.pdev->dev,
-                                      wq->memsize, &wq->dma_addr,
-                       GFP_KERNEL);
+       wq->queue = dma_alloc_coherent(&rdev->lldi.pdev->dev, wq->memsize,
+                                      &wq->dma_addr, GFP_KERNEL);
        if (!wq->queue)
                goto err_free_rqtpool;
 
index c22ebc7..f9a7e9d 100644 (file)
@@ -488,7 +488,7 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
                vmf = 1;
                break;
        case STATUS:
-               if (flags & (unsigned long)(VM_WRITE | VM_EXEC)) {
+               if (flags & VM_WRITE) {
                        ret = -EPERM;
                        goto done;
                }
index 0904490..7835eb5 100644 (file)
@@ -899,10 +899,10 @@ int hfi1_init(struct hfi1_devdata *dd, int reinit)
                goto done;
 
        /* allocate dummy tail memory for all receive contexts */
-       dd->rcvhdrtail_dummy_kvaddr = dma_zalloc_coherent(
-               &dd->pcidev->dev, sizeof(u64),
-               &dd->rcvhdrtail_dummy_dma,
-               GFP_KERNEL);
+       dd->rcvhdrtail_dummy_kvaddr = dma_alloc_coherent(&dd->pcidev->dev,
+                                                        sizeof(u64),
+                                                        &dd->rcvhdrtail_dummy_dma,
+                                                        GFP_KERNEL);
 
        if (!dd->rcvhdrtail_dummy_kvaddr) {
                dd_dev_err(dd, "cannot allocate dummy tail memory\n");
@@ -1863,9 +1863,9 @@ int hfi1_create_rcvhdrq(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd)
                        gfp_flags = GFP_KERNEL;
                else
                        gfp_flags = GFP_USER;
-               rcd->rcvhdrq = dma_zalloc_coherent(
-                       &dd->pcidev->dev, amt, &rcd->rcvhdrq_dma,
-                       gfp_flags | __GFP_COMP);
+               rcd->rcvhdrq = dma_alloc_coherent(&dd->pcidev->dev, amt,
+                                                 &rcd->rcvhdrq_dma,
+                                                 gfp_flags | __GFP_COMP);
 
                if (!rcd->rcvhdrq) {
                        dd_dev_err(dd,
@@ -1876,9 +1876,10 @@ int hfi1_create_rcvhdrq(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd)
 
                if (HFI1_CAP_KGET_MASK(rcd->flags, DMA_RTAIL) ||
                    HFI1_CAP_UGET_MASK(rcd->flags, DMA_RTAIL)) {
-                       rcd->rcvhdrtail_kvaddr = dma_zalloc_coherent(
-                               &dd->pcidev->dev, PAGE_SIZE,
-                               &rcd->rcvhdrqtailaddr_dma, gfp_flags);
+                       rcd->rcvhdrtail_kvaddr = dma_alloc_coherent(&dd->pcidev->dev,
+                                                                   PAGE_SIZE,
+                                                                   &rcd->rcvhdrqtailaddr_dma,
+                                                                   gfp_flags);
                        if (!rcd->rcvhdrtail_kvaddr)
                                goto bail_free;
                }
@@ -1974,10 +1975,10 @@ int hfi1_setup_eagerbufs(struct hfi1_ctxtdata *rcd)
        while (alloced_bytes < rcd->egrbufs.size &&
               rcd->egrbufs.alloced < rcd->egrbufs.count) {
                rcd->egrbufs.buffers[idx].addr =
-                       dma_zalloc_coherent(&dd->pcidev->dev,
-                                           rcd->egrbufs.rcvtid_size,
-                                           &rcd->egrbufs.buffers[idx].dma,
-                                           gfp_flags);
+                       dma_alloc_coherent(&dd->pcidev->dev,
+                                          rcd->egrbufs.rcvtid_size,
+                                          &rcd->egrbufs.buffers[idx].dma,
+                                          gfp_flags);
                if (rcd->egrbufs.buffers[idx].addr) {
                        rcd->egrbufs.buffers[idx].len =
                                rcd->egrbufs.rcvtid_size;
index dd5a5c0..04126d7 100644 (file)
@@ -2098,11 +2098,10 @@ int init_credit_return(struct hfi1_devdata *dd)
                int bytes = TXE_NUM_CONTEXTS * sizeof(struct credit_return);
 
                set_dev_node(&dd->pcidev->dev, i);
-               dd->cr_base[i].va = dma_zalloc_coherent(
-                                       &dd->pcidev->dev,
-                                       bytes,
-                                       &dd->cr_base[i].dma,
-                                       GFP_KERNEL);
+               dd->cr_base[i].va = dma_alloc_coherent(&dd->pcidev->dev,
+                                                      bytes,
+                                                      &dd->cr_base[i].dma,
+                                                      GFP_KERNEL);
                if (!dd->cr_base[i].va) {
                        set_dev_node(&dd->pcidev->dev, dd->node);
                        dd_dev_err(dd,
index b84356e..96897a9 100644 (file)
@@ -1453,12 +1453,9 @@ int sdma_init(struct hfi1_devdata *dd, u8 port)
                timer_setup(&sde->err_progress_check_timer,
                            sdma_err_progress_check, 0);
 
-               sde->descq = dma_zalloc_coherent(
-                       &dd->pcidev->dev,
-                       descq_cnt * sizeof(u64[2]),
-                       &sde->descq_phys,
-                       GFP_KERNEL
-               );
+               sde->descq = dma_alloc_coherent(&dd->pcidev->dev,
+                                               descq_cnt * sizeof(u64[2]),
+                                               &sde->descq_phys, GFP_KERNEL);
                if (!sde->descq)
                        goto bail;
                sde->tx_ring =
@@ -1471,24 +1468,18 @@ int sdma_init(struct hfi1_devdata *dd, u8 port)
 
        dd->sdma_heads_size = L1_CACHE_BYTES * num_engines;
        /* Allocate memory for DMA of head registers to memory */
-       dd->sdma_heads_dma = dma_zalloc_coherent(
-               &dd->pcidev->dev,
-               dd->sdma_heads_size,
-               &dd->sdma_heads_phys,
-               GFP_KERNEL
-       );
+       dd->sdma_heads_dma = dma_alloc_coherent(&dd->pcidev->dev,
+                                               dd->sdma_heads_size,
+                                               &dd->sdma_heads_phys,
+                                               GFP_KERNEL);
        if (!dd->sdma_heads_dma) {
                dd_dev_err(dd, "failed to allocate SendDMA head memory\n");
                goto bail;
        }
 
        /* Allocate memory for pad */
-       dd->sdma_pad_dma = dma_zalloc_coherent(
-               &dd->pcidev->dev,
-               sizeof(u32),
-               &dd->sdma_pad_phys,
-               GFP_KERNEL
-       );
+       dd->sdma_pad_dma = dma_alloc_coherent(&dd->pcidev->dev, sizeof(u32),
+                                             &dd->sdma_pad_phys, GFP_KERNEL);
        if (!dd->sdma_pad_dma) {
                dd_dev_err(dd, "failed to allocate SendDMA pad memory\n");
                goto bail;
index 88242fe..bf96067 100644 (file)
@@ -987,7 +987,6 @@ void hfi1_ud_rcv(struct hfi1_packet *packet)
            opcode == IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE) {
                wc.ex.imm_data = packet->ohdr->u.ud.imm_data;
                wc.wc_flags = IB_WC_WITH_IMM;
-               tlen -= sizeof(u32);
        } else if (opcode == IB_OPCODE_UD_SEND_ONLY) {
                wc.ex.imm_data = 0;
                wc.wc_flags = 0;
index 6300033..dac058d 100644 (file)
@@ -197,8 +197,8 @@ int hns_roce_buf_alloc(struct hns_roce_dev *hr_dev, u32 size, u32 max_direct,
                buf->npages = 1 << order;
                buf->page_shift = page_shift;
                /* MTT PA must be recorded in 4k alignment, t is 4k aligned */
-               buf->direct.buf = dma_zalloc_coherent(dev,
-                                                     size, &t, GFP_KERNEL);
+               buf->direct.buf = dma_alloc_coherent(dev, size, &t,
+                                                    GFP_KERNEL);
                if (!buf->direct.buf)
                        return -ENOMEM;
 
@@ -219,9 +219,10 @@ int hns_roce_buf_alloc(struct hns_roce_dev *hr_dev, u32 size, u32 max_direct,
                        return -ENOMEM;
 
                for (i = 0; i < buf->nbufs; ++i) {
-                       buf->page_list[i].buf = dma_zalloc_coherent(dev,
-                                                                 page_size, &t,
-                                                                 GFP_KERNEL);
+                       buf->page_list[i].buf = dma_alloc_coherent(dev,
+                                                                  page_size,
+                                                                  &t,
+                                                                  GFP_KERNEL);
 
                        if (!buf->page_list[i].buf)
                                goto err_free;
index 3a66945..543fa15 100644 (file)
@@ -5091,7 +5091,7 @@ static int hns_roce_mhop_alloc_eq(struct hns_roce_dev *hr_dev,
                                eqe_alloc = i * (buf_chk_sz / eq->eqe_size);
                                size = (eq->entries - eqe_alloc) * eq->eqe_size;
                        }
-                       eq->buf[i] = dma_zalloc_coherent(dev, size,
+                       eq->buf[i] = dma_alloc_coherent(dev, size,
                                                        &(eq->buf_dma[i]),
                                                        GFP_KERNEL);
                        if (!eq->buf[i])
@@ -5126,9 +5126,9 @@ static int hns_roce_mhop_alloc_eq(struct hns_roce_dev *hr_dev,
                                        size = (eq->entries - eqe_alloc)
                                                * eq->eqe_size;
                                }
-                               eq->buf[idx] = dma_zalloc_coherent(dev, size,
-                                                           &(eq->buf_dma[idx]),
-                                                           GFP_KERNEL);
+                               eq->buf[idx] = dma_alloc_coherent(dev, size,
+                                                                 &(eq->buf_dma[idx]),
+                                                                 GFP_KERNEL);
                                if (!eq->buf[idx])
                                        goto err_dma_alloc_buf;
 
@@ -5241,7 +5241,7 @@ static int hns_roce_v2_create_eq(struct hns_roce_dev *hr_dev,
                        goto free_cmd_mbox;
                }
 
-               eq->buf_list->buf = dma_zalloc_coherent(dev, buf_chk_sz,
+               eq->buf_list->buf = dma_alloc_coherent(dev, buf_chk_sz,
                                                       &(eq->buf_list->map),
                                                       GFP_KERNEL);
                if (!eq->buf_list->buf) {
index 960b194..12deacf 100644 (file)
@@ -210,6 +210,7 @@ struct ib_srq *hns_roce_create_srq(struct ib_pd *pd,
                                   struct ib_udata *udata)
 {
        struct hns_roce_dev *hr_dev = to_hr_dev(pd->device);
+       struct hns_roce_ib_create_srq_resp resp = {};
        struct hns_roce_srq *srq;
        int srq_desc_size;
        int srq_buf_size;
@@ -378,16 +379,21 @@ struct ib_srq *hns_roce_create_srq(struct ib_pd *pd,
 
        srq->event = hns_roce_ib_srq_event;
        srq->ibsrq.ext.xrc.srq_num = srq->srqn;
+       resp.srqn = srq->srqn;
 
        if (udata) {
-               if (ib_copy_to_udata(udata, &srq->srqn, sizeof(__u32))) {
+               if (ib_copy_to_udata(udata, &resp,
+                                    min(udata->outlen, sizeof(resp)))) {
                        ret = -EFAULT;
-                       goto err_wrid;
+                       goto err_srqc_alloc;
                }
        }
 
        return &srq->ibsrq;
 
+err_srqc_alloc:
+       hns_roce_srq_free(hr_dev, srq);
+
 err_wrid:
        kvfree(srq->wrid);
 
index a9ea966..59e9781 100644 (file)
@@ -745,8 +745,8 @@ enum i40iw_status_code i40iw_allocate_dma_mem(struct i40iw_hw *hw,
        if (!mem)
                return I40IW_ERR_PARAM;
        mem->size = ALIGN(size, alignment);
-       mem->va = dma_zalloc_coherent(&pcidev->dev, mem->size,
-                                     (dma_addr_t *)&mem->pa, GFP_KERNEL);
+       mem->va = dma_alloc_coherent(&pcidev->dev, mem->size,
+                                    (dma_addr_t *)&mem->pa, GFP_KERNEL);
        if (!mem->va)
                return I40IW_ERR_NO_MEMORY;
        return 0;
index 25439da..936ee13 100644 (file)
@@ -1411,7 +1411,7 @@ int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
 
        sqp_mad = (struct mlx4_mad_snd_buf *) (sqp->tx_ring[wire_tx_ix].buf.addr);
        if (sqp->tx_ring[wire_tx_ix].ah)
-               rdma_destroy_ah(sqp->tx_ring[wire_tx_ix].ah, 0);
+               mlx4_ib_destroy_ah(sqp->tx_ring[wire_tx_ix].ah, 0);
        sqp->tx_ring[wire_tx_ix].ah = ah;
        ib_dma_sync_single_for_cpu(&dev->ib_dev,
                                   sqp->tx_ring[wire_tx_ix].buf.map,
@@ -1902,7 +1902,7 @@ static void mlx4_ib_sqp_comp_worker(struct work_struct *work)
                if (wc.status == IB_WC_SUCCESS) {
                        switch (wc.opcode) {
                        case IB_WC_SEND:
-                               rdma_destroy_ah(sqp->tx_ring[wc.wr_id &
+                               mlx4_ib_destroy_ah(sqp->tx_ring[wc.wr_id &
                                              (MLX4_NUM_TUNNEL_BUFS - 1)].ah, 0);
                                sqp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah
                                        = NULL;
@@ -1931,7 +1931,7 @@ static void mlx4_ib_sqp_comp_worker(struct work_struct *work)
                                 " status = %d, wrid = 0x%llx\n",
                                 ctx->slave, wc.status, wc.wr_id);
                        if (!MLX4_TUN_IS_RECV(wc.wr_id)) {
-                               rdma_destroy_ah(sqp->tx_ring[wc.wr_id &
+                               mlx4_ib_destroy_ah(sqp->tx_ring[wc.wr_id &
                                              (MLX4_NUM_TUNNEL_BUFS - 1)].ah, 0);
                                sqp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah
                                        = NULL;
index e8a1e44..798591a 100644 (file)
@@ -630,8 +630,7 @@ const struct uapi_definition mlx5_ib_flow_defs[] = {
                UAPI_DEF_IS_OBJ_SUPPORTED(flow_is_supported)),
        UAPI_DEF_CHAIN_OBJ_TREE(
                UVERBS_OBJECT_FLOW,
-               &mlx5_ib_fs,
-               UAPI_DEF_IS_OBJ_SUPPORTED(flow_is_supported)),
+               &mlx5_ib_fs),
        UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_FLOW_ACTION,
                                &mlx5_ib_flow_actions),
        {},
index 01e0f62..4ee3296 100644 (file)
@@ -1595,10 +1595,12 @@ static void mlx5_ib_prefetch_mr_work(struct work_struct *work)
        struct prefetch_mr_work *w =
                container_of(work, struct prefetch_mr_work, work);
 
-       if (w->dev->ib_dev.reg_state == IB_DEV_REGISTERED)
+       if (ib_device_try_get(&w->dev->ib_dev)) {
                mlx5_ib_prefetch_sg_list(w->dev, w->pf_flags, w->sg_list,
                                         w->num_sge);
-
+               ib_device_put(&w->dev->ib_dev);
+       }
+       put_device(&w->dev->ib_dev.dev);
        kfree(w);
 }
 
@@ -1617,15 +1619,13 @@ int mlx5_ib_advise_mr_prefetch(struct ib_pd *pd,
                return mlx5_ib_prefetch_sg_list(dev, pf_flags, sg_list,
                                                num_sge);
 
-       if (dev->ib_dev.reg_state != IB_DEV_REGISTERED)
-               return -ENODEV;
-
        work = kvzalloc(struct_size(work, sg_list, num_sge), GFP_KERNEL);
        if (!work)
                return -ENOMEM;
 
        memcpy(work->sg_list, sg_list, num_sge * sizeof(struct ib_sge));
 
+       get_device(&dev->ib_dev.dev);
        work->dev = dev;
        work->pf_flags = pf_flags;
        work->num_sge = num_sge;
index dd2ae64..7db778d 100644 (file)
@@ -1912,14 +1912,16 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
                }
 
                if (!check_flags_mask(ucmd.flags,
+                                     MLX5_QP_FLAG_ALLOW_SCATTER_CQE |
+                                     MLX5_QP_FLAG_BFREG_INDEX |
+                                     MLX5_QP_FLAG_PACKET_BASED_CREDIT_MODE |
+                                     MLX5_QP_FLAG_SCATTER_CQE |
                                      MLX5_QP_FLAG_SIGNATURE |
-                                             MLX5_QP_FLAG_SCATTER_CQE |
-                                             MLX5_QP_FLAG_TUNNEL_OFFLOADS |
-                                             MLX5_QP_FLAG_BFREG_INDEX |
-                                             MLX5_QP_FLAG_TYPE_DCT |
-                                             MLX5_QP_FLAG_TYPE_DCI |
-                                             MLX5_QP_FLAG_ALLOW_SCATTER_CQE |
-                                             MLX5_QP_FLAG_PACKET_BASED_CREDIT_MODE))
+                                     MLX5_QP_FLAG_TIR_ALLOW_SELF_LB_MC |
+                                     MLX5_QP_FLAG_TIR_ALLOW_SELF_LB_UC |
+                                     MLX5_QP_FLAG_TUNNEL_OFFLOADS |
+                                     MLX5_QP_FLAG_TYPE_DCI |
+                                     MLX5_QP_FLAG_TYPE_DCT))
                        return -EINVAL;
 
                err = get_qp_user_index(to_mucontext(pd->uobject->context),
index cc9c0c8..112d2f3 100644 (file)
@@ -623,8 +623,9 @@ int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type,
        page = dev->db_tab->page + end;
 
 alloc:
-       page->db_rec = dma_zalloc_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE,
-                                          &page->mapping, GFP_KERNEL);
+       page->db_rec = dma_alloc_coherent(&dev->pdev->dev,
+                                         MTHCA_ICM_PAGE_SIZE, &page->mapping,
+                                         GFP_KERNEL);
        if (!page->db_rec) {
                ret = -ENOMEM;
                goto out;
index 82cb6b7..e3e9dd5 100644 (file)
@@ -534,7 +534,7 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
        {
                struct mthca_ucontext *context;
 
-               qp = kmalloc(sizeof *qp, GFP_KERNEL);
+               qp = kzalloc(sizeof(*qp), GFP_KERNEL);
                if (!qp)
                        return ERR_PTR(-ENOMEM);
 
@@ -600,7 +600,7 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
                if (udata)
                        return ERR_PTR(-EINVAL);
 
-               qp = kmalloc(sizeof (struct mthca_sqp), GFP_KERNEL);
+               qp = kzalloc(sizeof(struct mthca_sqp), GFP_KERNEL);
                if (!qp)
                        return ERR_PTR(-ENOMEM);
 
index 241a57a..097e5ab 100644 (file)
@@ -380,8 +380,8 @@ static int ocrdma_alloc_q(struct ocrdma_dev *dev,
        q->len = len;
        q->entry_size = entry_size;
        q->size = len * entry_size;
-       q->va = dma_zalloc_coherent(&dev->nic_info.pdev->dev, q->size,
-                                   &q->dma, GFP_KERNEL);
+       q->va = dma_alloc_coherent(&dev->nic_info.pdev->dev, q->size, &q->dma,
+                                  GFP_KERNEL);
        if (!q->va)
                return -ENOMEM;
        return 0;
@@ -1819,7 +1819,7 @@ int ocrdma_mbx_create_cq(struct ocrdma_dev *dev, struct ocrdma_cq *cq,
                return -ENOMEM;
        ocrdma_init_mch(&cmd->cmd.req, OCRDMA_CMD_CREATE_CQ,
                        OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
-       cq->va = dma_zalloc_coherent(&pdev->dev, cq->len, &cq->pa, GFP_KERNEL);
+       cq->va = dma_alloc_coherent(&pdev->dev, cq->len, &cq->pa, GFP_KERNEL);
        if (!cq->va) {
                status = -ENOMEM;
                goto mem_err;
@@ -2209,7 +2209,7 @@ static int ocrdma_set_create_qp_sq_cmd(struct ocrdma_create_qp_req *cmd,
        qp->sq.max_cnt = max_wqe_allocated;
        len = (hw_pages * hw_page_size);
 
-       qp->sq.va = dma_zalloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL);
+       qp->sq.va = dma_alloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL);
        if (!qp->sq.va)
                return -EINVAL;
        qp->sq.len = len;
@@ -2259,7 +2259,7 @@ static int ocrdma_set_create_qp_rq_cmd(struct ocrdma_create_qp_req *cmd,
        qp->rq.max_cnt = max_rqe_allocated;
        len = (hw_pages * hw_page_size);
 
-       qp->rq.va = dma_zalloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL);
+       qp->rq.va = dma_alloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL);
        if (!qp->rq.va)
                return -ENOMEM;
        qp->rq.pa = pa;
@@ -2315,8 +2315,8 @@ static int ocrdma_set_create_qp_ird_cmd(struct ocrdma_create_qp_req *cmd,
        if (dev->attr.ird == 0)
                return 0;
 
-       qp->ird_q_va = dma_zalloc_coherent(&pdev->dev, ird_q_len, &pa,
-                                          GFP_KERNEL);
+       qp->ird_q_va = dma_alloc_coherent(&pdev->dev, ird_q_len, &pa,
+                                         GFP_KERNEL);
        if (!qp->ird_q_va)
                return -ENOMEM;
        ocrdma_build_q_pages(&cmd->ird_addr[0], dev->attr.num_ird_pages,
index dd15474..6be0ea1 100644 (file)
@@ -73,8 +73,8 @@ bool ocrdma_alloc_stats_resources(struct ocrdma_dev *dev)
        mem->size = max_t(u32, sizeof(struct ocrdma_rdma_stats_req),
                        sizeof(struct ocrdma_rdma_stats_resp));
 
-       mem->va = dma_zalloc_coherent(&dev->nic_info.pdev->dev, mem->size,
-                                     &mem->pa, GFP_KERNEL);
+       mem->va = dma_alloc_coherent(&dev->nic_info.pdev->dev, mem->size,
+                                    &mem->pa, GFP_KERNEL);
        if (!mem->va) {
                pr_err("%s: stats mbox allocation failed\n", __func__);
                return false;
index c46bed0..287c332 100644 (file)
@@ -504,8 +504,8 @@ struct ib_ucontext *ocrdma_alloc_ucontext(struct ib_device *ibdev,
        INIT_LIST_HEAD(&ctx->mm_head);
        mutex_init(&ctx->mm_list_lock);
 
-       ctx->ah_tbl.va = dma_zalloc_coherent(&pdev->dev, map_len,
-                                            &ctx->ah_tbl.pa, GFP_KERNEL);
+       ctx->ah_tbl.va = dma_alloc_coherent(&pdev->dev, map_len,
+                                           &ctx->ah_tbl.pa, GFP_KERNEL);
        if (!ctx->ah_tbl.va) {
                kfree(ctx);
                return ERR_PTR(-ENOMEM);
@@ -838,7 +838,7 @@ static int ocrdma_build_pbl_tbl(struct ocrdma_dev *dev, struct ocrdma_hw_mr *mr)
                return -ENOMEM;
 
        for (i = 0; i < mr->num_pbls; i++) {
-               va = dma_zalloc_coherent(&pdev->dev, dma_len, &pa, GFP_KERNEL);
+               va = dma_alloc_coherent(&pdev->dev, dma_len, &pa, GFP_KERNEL);
                if (!va) {
                        ocrdma_free_mr_pbl_tbl(dev, mr);
                        status = -ENOMEM;
index b342a70..e1ccf32 100644 (file)
@@ -556,8 +556,8 @@ static struct qedr_pbl *qedr_alloc_pbl_tbl(struct qedr_dev *dev,
                return ERR_PTR(-ENOMEM);
 
        for (i = 0; i < pbl_info->num_pbls; i++) {
-               va = dma_zalloc_coherent(&pdev->dev, pbl_info->pbl_size,
-                                        &pa, flags);
+               va = dma_alloc_coherent(&pdev->dev, pbl_info->pbl_size, &pa,
+                                       flags);
                if (!va)
                        goto err;
 
index 868da0e..445ea19 100644 (file)
@@ -512,7 +512,6 @@ void qib_ud_rcv(struct qib_ibport *ibp, struct ib_header *hdr,
            opcode == IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE) {
                wc.ex.imm_data = ohdr->u.ud.imm_data;
                wc.wc_flags = IB_WC_WITH_IMM;
-               tlen -= sizeof(u32);
        } else if (opcode == IB_OPCODE_UD_SEND_ONLY) {
                wc.ex.imm_data = 0;
                wc.wc_flags = 0;
index 42b8685..3c633ab 100644 (file)
@@ -427,7 +427,40 @@ static inline enum ib_qp_state pvrdma_qp_state_to_ib(enum pvrdma_qp_state state)
 
 static inline enum pvrdma_wr_opcode ib_wr_opcode_to_pvrdma(enum ib_wr_opcode op)
 {
-       return (enum pvrdma_wr_opcode)op;
+       switch (op) {
+       case IB_WR_RDMA_WRITE:
+               return PVRDMA_WR_RDMA_WRITE;
+       case IB_WR_RDMA_WRITE_WITH_IMM:
+               return PVRDMA_WR_RDMA_WRITE_WITH_IMM;
+       case IB_WR_SEND:
+               return PVRDMA_WR_SEND;
+       case IB_WR_SEND_WITH_IMM:
+               return PVRDMA_WR_SEND_WITH_IMM;
+       case IB_WR_RDMA_READ:
+               return PVRDMA_WR_RDMA_READ;
+       case IB_WR_ATOMIC_CMP_AND_SWP:
+               return PVRDMA_WR_ATOMIC_CMP_AND_SWP;
+       case IB_WR_ATOMIC_FETCH_AND_ADD:
+               return PVRDMA_WR_ATOMIC_FETCH_AND_ADD;
+       case IB_WR_LSO:
+               return PVRDMA_WR_LSO;
+       case IB_WR_SEND_WITH_INV:
+               return PVRDMA_WR_SEND_WITH_INV;
+       case IB_WR_RDMA_READ_WITH_INV:
+               return PVRDMA_WR_RDMA_READ_WITH_INV;
+       case IB_WR_LOCAL_INV:
+               return PVRDMA_WR_LOCAL_INV;
+       case IB_WR_REG_MR:
+               return PVRDMA_WR_FAST_REG_MR;
+       case IB_WR_MASKED_ATOMIC_CMP_AND_SWP:
+               return PVRDMA_WR_MASKED_ATOMIC_CMP_AND_SWP;
+       case IB_WR_MASKED_ATOMIC_FETCH_AND_ADD:
+               return PVRDMA_WR_MASKED_ATOMIC_FETCH_AND_ADD;
+       case IB_WR_REG_SIG_MR:
+               return PVRDMA_WR_REG_SIG_MR;
+       default:
+               return PVRDMA_WR_ERROR;
+       }
 }
 
 static inline enum ib_wc_status pvrdma_wc_status_to_ib(
index eaa109d..39c37b6 100644 (file)
@@ -890,8 +890,8 @@ static int pvrdma_pci_probe(struct pci_dev *pdev,
        dev_info(&pdev->dev, "device version %d, driver version %d\n",
                 dev->dsr_version, PVRDMA_VERSION);
 
-       dev->dsr = dma_zalloc_coherent(&pdev->dev, sizeof(*dev->dsr),
-                                      &dev->dsrbase, GFP_KERNEL);
+       dev->dsr = dma_alloc_coherent(&pdev->dev, sizeof(*dev->dsr),
+                                     &dev->dsrbase, GFP_KERNEL);
        if (!dev->dsr) {
                dev_err(&pdev->dev, "failed to allocate shared region\n");
                ret = -ENOMEM;
index 3acf74c..1ec3646 100644 (file)
@@ -721,6 +721,12 @@ int pvrdma_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
                    wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
                        wqe_hdr->ex.imm_data = wr->ex.imm_data;
 
+               if (unlikely(wqe_hdr->opcode == PVRDMA_WR_ERROR)) {
+                       *bad_wr = wr;
+                       ret = -EINVAL;
+                       goto out;
+               }
+
                switch (qp->ibqp.qp_type) {
                case IB_QPT_GSI:
                case IB_QPT_UD:
index a1bd8cf..c6cc3e4 100644 (file)
@@ -2910,6 +2910,8 @@ send:
                        goto op_err;
                if (!ret)
                        goto rnr_nak;
+               if (wqe->length > qp->r_len)
+                       goto inv_err;
                break;
 
        case IB_WR_RDMA_WRITE_WITH_IMM:
@@ -3078,7 +3080,10 @@ op_err:
        goto err;
 
 inv_err:
-       send_status = IB_WC_REM_INV_REQ_ERR;
+       send_status =
+               sqp->ibqp.qp_type == IB_QPT_RC ?
+                       IB_WC_REM_INV_REQ_ERR :
+                       IB_WC_SUCCESS;
        wc.status = IB_WC_LOC_QP_OP_ERR;
        goto err;
 
index 1da119d..73e808c 100644 (file)
@@ -248,7 +248,6 @@ struct ipoib_cm_tx {
        struct list_head     list;
        struct net_device   *dev;
        struct ipoib_neigh  *neigh;
-       struct ipoib_path   *path;
        struct ipoib_tx_buf *tx_ring;
        unsigned int         tx_head;
        unsigned int         tx_tail;
index 0428e01..aa9dcfc 100644 (file)
@@ -1312,7 +1312,6 @@ struct ipoib_cm_tx *ipoib_cm_create_tx(struct net_device *dev, struct ipoib_path
 
        neigh->cm = tx;
        tx->neigh = neigh;
-       tx->path = path;
        tx->dev = dev;
        list_add(&tx->list, &priv->cm.start_list);
        set_bit(IPOIB_FLAG_INITIALIZED, &tx->flags);
@@ -1371,7 +1370,7 @@ static void ipoib_cm_tx_start(struct work_struct *work)
                                neigh->daddr + QPN_AND_OPTIONS_OFFSET);
                        goto free_neigh;
                }
-               memcpy(&pathrec, &p->path->pathrec, sizeof(pathrec));
+               memcpy(&pathrec, &path->pathrec, sizeof(pathrec));
 
                spin_unlock_irqrestore(&priv->lock, flags);
                netif_tx_unlock_bh(dev);
index cfc8b94..aa4e431 100644 (file)
@@ -252,6 +252,8 @@ static const struct xpad_device {
        { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX },
        { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX },
        { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX },
+       { 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
+       { 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
        { 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 },
        { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 },
@@ -428,6 +430,7 @@ static const struct usb_device_id xpad_table[] = {
        XPAD_XBOXONE_VENDOR(0x0e6f),            /* 0x0e6f X-Box One controllers */
        XPAD_XBOX360_VENDOR(0x0f0d),            /* Hori Controllers */
        XPAD_XBOXONE_VENDOR(0x0f0d),            /* Hori Controllers */
+       XPAD_XBOX360_VENDOR(0x1038),            /* SteelSeries Controllers */
        XPAD_XBOX360_VENDOR(0x11c9),            /* Nacon GC100XF */
        XPAD_XBOX360_VENDOR(0x12ab),            /* X-Box 360 dance pads */
        XPAD_XBOX360_VENDOR(0x1430),            /* RedOctane X-Box 360 controllers */
index 4713957..a878351 100644 (file)
@@ -420,7 +420,7 @@ config KEYBOARD_MPR121
 
 config KEYBOARD_SNVS_PWRKEY
        tristate "IMX SNVS Power Key Driver"
-       depends on SOC_IMX6SX
+       depends on SOC_IMX6SX || SOC_IMX7D
        depends on OF
        help
          This is the snvs powerkey driver for the Freescale i.MX application
index 312916f..73686c2 100644 (file)
@@ -75,9 +75,7 @@
 struct cap11xx_led {
        struct cap11xx_priv *priv;
        struct led_classdev cdev;
-       struct work_struct work;
        u32 reg;
-       enum led_brightness new_brightness;
 };
 #endif
 
@@ -233,30 +231,21 @@ static void cap11xx_input_close(struct input_dev *idev)
 }
 
 #ifdef CONFIG_LEDS_CLASS
-static void cap11xx_led_work(struct work_struct *work)
+static int cap11xx_led_set(struct led_classdev *cdev,
+                           enum led_brightness value)
 {
-       struct cap11xx_led *led = container_of(work, struct cap11xx_led, work);
+       struct cap11xx_led *led = container_of(cdev, struct cap11xx_led, cdev);
        struct cap11xx_priv *priv = led->priv;
-       int value = led->new_brightness;
 
        /*
-        * All LEDs share the same duty cycle as this is a HW limitation.
-        * Brightness levels per LED are either 0 (OFF) and 1 (ON).
+        * All LEDs share the same duty cycle as this is a HW
+        * limitation. Brightness levels per LED are either
+        * 0 (OFF) and 1 (ON).
         */
-       regmap_update_bits(priv->regmap, CAP11XX_REG_LED_OUTPUT_CONTROL,
-                               BIT(led->reg), value ? BIT(led->reg) : 0);
-}
-
-static void cap11xx_led_set(struct led_classdev *cdev,
-                          enum led_brightness value)
-{
-       struct cap11xx_led *led = container_of(cdev, struct cap11xx_led, cdev);
-
-       if (led->new_brightness == value)
-               return;
-
-       led->new_brightness = value;
-       schedule_work(&led->work);
+       return regmap_update_bits(priv->regmap,
+                                 CAP11XX_REG_LED_OUTPUT_CONTROL,
+                                 BIT(led->reg),
+                                 value ? BIT(led->reg) : 0);
 }
 
 static int cap11xx_init_leds(struct device *dev,
@@ -299,7 +288,7 @@ static int cap11xx_init_leds(struct device *dev,
                led->cdev.default_trigger =
                        of_get_property(child, "linux,default-trigger", NULL);
                led->cdev.flags = 0;
-               led->cdev.brightness_set = cap11xx_led_set;
+               led->cdev.brightness_set_blocking = cap11xx_led_set;
                led->cdev.max_brightness = 1;
                led->cdev.brightness = LED_OFF;
 
@@ -312,8 +301,6 @@ static int cap11xx_init_leds(struct device *dev,
                led->reg = reg;
                led->priv = priv;
 
-               INIT_WORK(&led->work, cap11xx_led_work);
-
                error = devm_led_classdev_register(dev, &led->cdev);
                if (error) {
                        of_node_put(child);
index 403452e..3d1cb7b 100644 (file)
@@ -222,7 +222,7 @@ static void matrix_keypad_stop(struct input_dev *dev)
        keypad->stopped = true;
        spin_unlock_irq(&keypad->lock);
 
-       flush_work(&keypad->work.work);
+       flush_delayed_work(&keypad->work);
        /*
         * matrix_keypad_scan() will leave IRQs enabled;
         * we should disable them now.
index 43b8648..d466bc0 100644 (file)
@@ -58,10 +58,9 @@ static unsigned char qt2160_key2code[] = {
 struct qt2160_led {
        struct qt2160_data *qt2160;
        struct led_classdev cdev;
-       struct work_struct work;
        char name[32];
        int id;
-       enum led_brightness new_brightness;
+       enum led_brightness brightness;
 };
 #endif
 
@@ -74,7 +73,6 @@ struct qt2160_data {
        u16 key_matrix;
 #ifdef CONFIG_LEDS_CLASS
        struct qt2160_led leds[QT2160_NUM_LEDS_X];
-       struct mutex led_lock;
 #endif
 };
 
@@ -83,46 +81,39 @@ static int qt2160_write(struct i2c_client *client, u8 reg, u8 data);
 
 #ifdef CONFIG_LEDS_CLASS
 
-static void qt2160_led_work(struct work_struct *work)
+static int qt2160_led_set(struct led_classdev *cdev,
+                         enum led_brightness value)
 {
-       struct qt2160_led *led = container_of(work, struct qt2160_led, work);
+       struct qt2160_led *led = container_of(cdev, struct qt2160_led, cdev);
        struct qt2160_data *qt2160 = led->qt2160;
        struct i2c_client *client = qt2160->client;
-       int value = led->new_brightness;
        u32 drive, pwmen;
 
-       mutex_lock(&qt2160->led_lock);
-
-       drive = qt2160_read(client, QT2160_CMD_DRIVE_X);
-       pwmen = qt2160_read(client, QT2160_CMD_PWMEN_X);
-       if (value != LED_OFF) {
-               drive |= (1 << led->id);
-               pwmen |= (1 << led->id);
-
-       } else {
-               drive &= ~(1 << led->id);
-               pwmen &= ~(1 << led->id);
-       }
-       qt2160_write(client, QT2160_CMD_DRIVE_X, drive);
-       qt2160_write(client, QT2160_CMD_PWMEN_X, pwmen);
+       if (value != led->brightness) {
+               drive = qt2160_read(client, QT2160_CMD_DRIVE_X);
+               pwmen = qt2160_read(client, QT2160_CMD_PWMEN_X);
+               if (value != LED_OFF) {
+                       drive |= BIT(led->id);
+                       pwmen |= BIT(led->id);
 
-       /*
-        * Changing this register will change the brightness
-        * of every LED in the qt2160. It's a HW limitation.
-        */
-       if (value != LED_OFF)
-               qt2160_write(client, QT2160_CMD_PWM_DUTY, value);
+               } else {
+                       drive &= ~BIT(led->id);
+                       pwmen &= ~BIT(led->id);
+               }
+               qt2160_write(client, QT2160_CMD_DRIVE_X, drive);
+               qt2160_write(client, QT2160_CMD_PWMEN_X, pwmen);
 
-       mutex_unlock(&qt2160->led_lock);
-}
+               /*
+                * Changing this register will change the brightness
+                * of every LED in the qt2160. It's a HW limitation.
+                */
+               if (value != LED_OFF)
+                       qt2160_write(client, QT2160_CMD_PWM_DUTY, value);
 
-static void qt2160_led_set(struct led_classdev *cdev,
-                          enum led_brightness value)
-{
-       struct qt2160_led *led = container_of(cdev, struct qt2160_led, cdev);
+               led->brightness = value;
+       }
 
-       led->new_brightness = value;
-       schedule_work(&led->work);
+       return 0;
 }
 
 #endif /* CONFIG_LEDS_CLASS */
@@ -293,20 +284,16 @@ static int qt2160_register_leds(struct qt2160_data *qt2160)
        int ret;
        int i;
 
-       mutex_init(&qt2160->led_lock);
-
        for (i = 0; i < QT2160_NUM_LEDS_X; i++) {
                struct qt2160_led *led = &qt2160->leds[i];
 
                snprintf(led->name, sizeof(led->name), "qt2160:x%d", i);
                led->cdev.name = led->name;
-               led->cdev.brightness_set = qt2160_led_set;
+               led->cdev.brightness_set_blocking = qt2160_led_set;
                led->cdev.brightness = LED_OFF;
                led->id = i;
                led->qt2160 = qt2160;
 
-               INIT_WORK(&led->work, qt2160_led_work);
-
                ret = led_classdev_register(&client->dev, &led->cdev);
                if (ret < 0)
                        return ret;
@@ -324,10 +311,8 @@ static void qt2160_unregister_leds(struct qt2160_data *qt2160)
 {
        int i;
 
-       for (i = 0; i < QT2160_NUM_LEDS_X; i++) {
+       for (i = 0; i < QT2160_NUM_LEDS_X; i++)
                led_classdev_unregister(&qt2160->leds[i].cdev);
-               cancel_work_sync(&qt2160->leds[i].work);
-       }
 }
 
 #else
index babcfb1..3b85631 100644 (file)
@@ -153,6 +153,8 @@ static int keyscan_probe(struct platform_device *pdev)
 
        input_dev->id.bustype = BUS_HOST;
 
+       keypad_data->input_dev = input_dev;
+
        error = keypad_matrix_key_parse_dt(keypad_data);
        if (error)
                return error;
@@ -168,8 +170,6 @@ static int keyscan_probe(struct platform_device *pdev)
 
        input_set_drvdata(input_dev, keypad_data);
 
-       keypad_data->input_dev = input_dev;
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        keypad_data->base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(keypad_data->base))
index 094bddf..c1e66f4 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/io.h>
 #include <linux/input-polldev.h>
 #include <linux/i2c.h>
-#include <linux/workqueue.h>
 #include <linux/leds.h>
 
 #define APANEL_NAME    "Fujitsu Application Panel"
@@ -59,8 +58,6 @@ struct apanel {
        struct i2c_client *client;
        unsigned short keymap[MAX_PANEL_KEYS];
        u16    nkeys;
-       u16    led_bits;
-       struct work_struct led_work;
        struct led_classdev mail_led;
 };
 
@@ -109,25 +106,13 @@ static void apanel_poll(struct input_polled_dev *ipdev)
                        report_key(idev, ap->keymap[i]);
 }
 
-/* Track state changes of LED */
-static void led_update(struct work_struct *work)
-{
-       struct apanel *ap = container_of(work, struct apanel, led_work);
-
-       i2c_smbus_write_word_data(ap->client, 0x10, ap->led_bits);
-}
-
-static void mail_led_set(struct led_classdev *led,
+static int mail_led_set(struct led_classdev *led,
                         enum led_brightness value)
 {
        struct apanel *ap = container_of(led, struct apanel, mail_led);
+       u16 led_bits = value != LED_OFF ? 0x8000 : 0x0000;
 
-       if (value != LED_OFF)
-               ap->led_bits |= 0x8000;
-       else
-               ap->led_bits &= ~0x8000;
-
-       schedule_work(&ap->led_work);
+       return i2c_smbus_write_word_data(ap->client, 0x10, led_bits);
 }
 
 static int apanel_remove(struct i2c_client *client)
@@ -179,7 +164,7 @@ static struct apanel apanel = {
        },
        .mail_led = {
                .name = "mail:blue",
-               .brightness_set = mail_led_set,
+               .brightness_set_blocking = mail_led_set,
        },
 };
 
@@ -235,7 +220,6 @@ static int apanel_probe(struct i2c_client *client,
        if (err)
                goto out3;
 
-       INIT_WORK(&ap->led_work, led_update);
        if (device_chip[APANEL_DEV_LED] != CHIP_NONE) {
                err = led_classdev_register(&client->dev, &ap->mail_led);
                if (err)
index 1efcfdf..dd9dd4e 100644 (file)
@@ -481,13 +481,14 @@ static int bma150_register_input_device(struct bma150_data *bma150)
        idev->close = bma150_irq_close;
        input_set_drvdata(idev, bma150);
 
+       bma150->input = idev;
+
        error = input_register_device(idev);
        if (error) {
                input_free_device(idev);
                return error;
        }
 
-       bma150->input = idev;
        return 0;
 }
 
@@ -510,15 +511,15 @@ static int bma150_register_polled_device(struct bma150_data *bma150)
 
        bma150_init_input_device(bma150, ipoll_dev->input);
 
+       bma150->input_polled = ipoll_dev;
+       bma150->input = ipoll_dev->input;
+
        error = input_register_polled_device(ipoll_dev);
        if (error) {
                input_free_polled_device(ipoll_dev);
                return error;
        }
 
-       bma150->input_polled = ipoll_dev;
-       bma150->input = ipoll_dev->input;
-
        return 0;
 }
 
index 55da191..dbb6d9e 100644 (file)
@@ -34,6 +34,7 @@ struct pwm_vibrator {
        struct work_struct play_work;
        u16 level;
        u32 direction_duty_cycle;
+       bool vcc_on;
 };
 
 static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
@@ -42,10 +43,13 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
        struct pwm_state state;
        int err;
 
-       err = regulator_enable(vibrator->vcc);
-       if (err) {
-               dev_err(pdev, "failed to enable regulator: %d", err);
-               return err;
+       if (!vibrator->vcc_on) {
+               err = regulator_enable(vibrator->vcc);
+               if (err) {
+                       dev_err(pdev, "failed to enable regulator: %d", err);
+                       return err;
+               }
+               vibrator->vcc_on = true;
        }
 
        pwm_get_state(vibrator->pwm, &state);
@@ -76,11 +80,14 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
 
 static void pwm_vibrator_stop(struct pwm_vibrator *vibrator)
 {
-       regulator_disable(vibrator->vcc);
-
        if (vibrator->pwm_dir)
                pwm_disable(vibrator->pwm_dir);
        pwm_disable(vibrator->pwm);
+
+       if (vibrator->vcc_on) {
+               regulator_disable(vibrator->vcc);
+               vibrator->vcc_on = false;
+       }
 }
 
 static void pwm_vibrator_play_work(struct work_struct *work)
index 8ec483e..26ec603 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
+#include <linux/overflow.h>
 #include <linux/input/mt.h>
 #include "../input-compat.h"
 
@@ -405,7 +406,7 @@ static int uinput_open(struct inode *inode, struct file *file)
 static int uinput_validate_absinfo(struct input_dev *dev, unsigned int code,
                                   const struct input_absinfo *abs)
 {
-       int min, max;
+       int min, max, range;
 
        min = abs->minimum;
        max = abs->maximum;
@@ -417,7 +418,7 @@ static int uinput_validate_absinfo(struct input_dev *dev, unsigned int code,
                return -EINVAL;
        }
 
-       if (abs->flat > max - min) {
+       if (!check_sub_overflow(max, min, &range) && abs->flat > range) {
                printk(KERN_DEBUG
                       "%s: abs_flat #%02x out of range: %d (min:%d/max:%d)\n",
                       UINPUT_NAME, code, abs->flat, min, max);
index f322a17..225ae69 100644 (file)
@@ -1336,7 +1336,6 @@ MODULE_DEVICE_TABLE(i2c, elan_id);
 static const struct acpi_device_id elan_acpi_id[] = {
        { "ELAN0000", 0 },
        { "ELAN0100", 0 },
-       { "ELAN0501", 0 },
        { "ELAN0600", 0 },
        { "ELAN0602", 0 },
        { "ELAN0605", 0 },
@@ -1346,6 +1345,7 @@ static const struct acpi_device_id elan_acpi_id[] = {
        { "ELAN060C", 0 },
        { "ELAN0611", 0 },
        { "ELAN0612", 0 },
+       { "ELAN0617", 0 },
        { "ELAN0618", 0 },
        { "ELAN061C", 0 },
        { "ELAN061D", 0 },
index 9fe075c..a7f8b16 100644 (file)
@@ -1119,6 +1119,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
  * Asus UX31               0x361f00        20, 15, 0e      clickpad
  * Asus UX32VD             0x361f02        00, 15, 0e      clickpad
  * Avatar AVIU-145A2       0x361f00        ?               clickpad
+ * Fujitsu CELSIUS H760    0x570f02        40, 14, 0c      3 hw buttons (**)
+ * Fujitsu CELSIUS H780    0x5d0f02        41, 16, 0d      3 hw buttons (**)
  * Fujitsu LIFEBOOK E544   0x470f00        d0, 12, 09      2 hw buttons
  * Fujitsu LIFEBOOK E546   0x470f00        50, 12, 09      2 hw buttons
  * Fujitsu LIFEBOOK E547   0x470f00        50, 12, 09      2 hw buttons
@@ -1171,6 +1173,13 @@ static const struct dmi_system_id elantech_dmi_has_middle_button[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H760"),
                },
        },
+       {
+               /* Fujitsu H780 also has a middle button */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H780"),
+               },
+       },
 #endif
        { }
 };
index b360847..a7cfab3 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
-#include <linux/clk.h>
 
 /*
  * The OLPC XO-1.75 and XO-4 laptops do not have a hardware PS/2 controller.
@@ -75,7 +74,6 @@ struct olpc_apsp {
        struct serio *kbio;
        struct serio *padio;
        void __iomem *base;
-       struct clk *clk;
        int open_count;
        int irq;
 };
@@ -148,17 +146,11 @@ static int olpc_apsp_open(struct serio *port)
        struct olpc_apsp *priv = port->port_data;
        unsigned int tmp;
        unsigned long l;
-       int error;
 
        if (priv->open_count++ == 0) {
-               error = clk_prepare_enable(priv->clk);
-               if (error)
-                       return error;
-
                l = readl(priv->base + COMMAND_FIFO_STATUS);
                if (!(l & CMD_STS_MASK)) {
                        dev_err(priv->dev, "SP cannot accept commands.\n");
-                       clk_disable_unprepare(priv->clk);
                        return -EIO;
                }
 
@@ -179,8 +171,6 @@ static void olpc_apsp_close(struct serio *port)
                /* Disable interrupt 0 */
                tmp = readl(priv->base + PJ_INTERRUPT_MASK);
                writel(tmp | INT_0, priv->base + PJ_INTERRUPT_MASK);
-
-               clk_disable_unprepare(priv->clk);
        }
 }
 
@@ -195,6 +185,8 @@ static int olpc_apsp_probe(struct platform_device *pdev)
        if (!priv)
                return -ENOMEM;
 
+       priv->dev = &pdev->dev;
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        priv->base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(priv->base)) {
@@ -206,10 +198,6 @@ static int olpc_apsp_probe(struct platform_device *pdev)
        if (priv->irq < 0)
                return priv->irq;
 
-       priv->clk = devm_clk_get(&pdev->dev, "sp");
-       if (IS_ERR(priv->clk))
-               return PTR_ERR(priv->clk);
-
        /* KEYBOARD */
        kb_serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
        if (!kb_serio)
@@ -248,7 +236,6 @@ static int olpc_apsp_probe(struct platform_device *pdev)
                goto err_irq;
        }
 
-       priv->dev = &pdev->dev;
        device_init_wakeup(priv->dev, 1);
        platform_set_drvdata(pdev, priv);
 
index c62cceb..5e8d838 100644 (file)
@@ -76,6 +76,7 @@ static void ps2_gpio_close(struct serio *serio)
 {
        struct ps2_gpio_data *drvdata = serio->port_data;
 
+       flush_delayed_work(&drvdata->tx_work);
        disable_irq(drvdata->irq);
 }
 
index af6027c..068dbbc 100644 (file)
@@ -698,7 +698,7 @@ config TOUCHSCREEN_EDT_FT5X06
 
 config TOUCHSCREEN_RASPBERRYPI_FW
        tristate "Raspberry Pi's firmware base touch screen support"
-       depends on RASPBERRYPI_FIRMWARE || COMPILE_TEST
+       depends on RASPBERRYPI_FIRMWARE || (RASPBERRYPI_FIRMWARE=n && COMPILE_TEST)
        help
          Say Y here if you have the official Raspberry Pi 7 inch screen on
          your system.
index f456c11..6988126 100644 (file)
@@ -147,8 +147,8 @@ static int rpi_ts_probe(struct platform_device *pdev)
                return -ENOMEM;
        ts->pdev = pdev;
 
-       ts->fw_regs_va = dma_zalloc_coherent(dev, PAGE_SIZE, &ts->fw_regs_phys,
-                                            GFP_KERNEL);
+       ts->fw_regs_va = dma_alloc_coherent(dev, PAGE_SIZE, &ts->fw_regs_phys,
+                                           GFP_KERNEL);
        if (!ts->fw_regs_va) {
                dev_err(dev, "failed to dma_alloc_coherent\n");
                return -ENOMEM;
index 87ba23a..2a7b78b 100644 (file)
@@ -1991,16 +1991,13 @@ static void do_attach(struct iommu_dev_data *dev_data,
 
 static void do_detach(struct iommu_dev_data *dev_data)
 {
+       struct protection_domain *domain = dev_data->domain;
        struct amd_iommu *iommu;
        u16 alias;
 
        iommu = amd_iommu_rlookup_table[dev_data->devid];
        alias = dev_data->alias;
 
-       /* decrease reference counters */
-       dev_data->domain->dev_iommu[iommu->index] -= 1;
-       dev_data->domain->dev_cnt                 -= 1;
-
        /* Update data structures */
        dev_data->domain = NULL;
        list_del(&dev_data->list);
@@ -2010,6 +2007,16 @@ static void do_detach(struct iommu_dev_data *dev_data)
 
        /* Flush the DTE entry */
        device_flush_dte(dev_data);
+
+       /* Flush IOTLB */
+       domain_flush_tlb_pde(domain);
+
+       /* Wait for the flushes to finish */
+       domain_flush_complete(domain);
+
+       /* decrease reference counters - needs to happen after the flushes */
+       domain->dev_iommu[iommu->index] -= 1;
+       domain->dev_cnt                 -= 1;
 }
 
 /*
@@ -2617,13 +2624,13 @@ out_unmap:
                        bus_addr  = address + s->dma_address + (j << PAGE_SHIFT);
                        iommu_unmap_page(domain, bus_addr, PAGE_SIZE);
 
-                       if (--mapped_pages)
+                       if (--mapped_pages == 0)
                                goto out_free_iova;
                }
        }
 
 out_free_iova:
-       free_iova_fast(&dma_dom->iovad, address, npages);
+       free_iova_fast(&dma_dom->iovad, address >> PAGE_SHIFT, npages);
 
 out_err:
        return 0;
index 2bd9ac2..78188bf 100644 (file)
@@ -363,7 +363,7 @@ static int dmar_map_gfx = 1;
 static int dmar_forcedac;
 static int intel_iommu_strict;
 static int intel_iommu_superpage = 1;
-static int intel_iommu_sm = 1;
+static int intel_iommu_sm;
 static int iommu_identity_mapping;
 
 #define IDENTMAP_ALL           1
@@ -456,9 +456,9 @@ static int __init intel_iommu_setup(char *str)
                } else if (!strncmp(str, "sp_off", 6)) {
                        pr_info("Disable supported super page\n");
                        intel_iommu_superpage = 0;
-               } else if (!strncmp(str, "sm_off", 6)) {
-                       pr_info("Intel-IOMMU: disable scalable mode support\n");
-                       intel_iommu_sm = 0;
+               } else if (!strncmp(str, "sm_on", 5)) {
+                       pr_info("Intel-IOMMU: scalable mode supported\n");
+                       intel_iommu_sm = 1;
                } else if (!strncmp(str, "tboot_noforce", 13)) {
                        printk(KERN_INFO
                                "Intel-IOMMU: not forcing on after tboot. This could expose security risk for tboot\n");
@@ -5294,7 +5294,7 @@ static void intel_iommu_put_resv_regions(struct device *dev,
        struct iommu_resv_region *entry, *next;
 
        list_for_each_entry_safe(entry, next, head, list) {
-               if (entry->type == IOMMU_RESV_RESERVED)
+               if (entry->type == IOMMU_RESV_MSI)
                        kfree(entry);
        }
 }
index 6ede428..7e0df67 100644 (file)
@@ -232,9 +232,8 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_data *data)
 
        spin_lock_init(&dom->pgtlock);
 
-       dom->pgt_va = dma_zalloc_coherent(data->dev,
-                               M2701_IOMMU_PGT_SIZE,
-                               &dom->pgt_pa, GFP_KERNEL);
+       dom->pgt_va = dma_alloc_coherent(data->dev, M2701_IOMMU_PGT_SIZE,
+                                        &dom->pgt_pa, GFP_KERNEL);
        if (!dom->pgt_va)
                return -ENOMEM;
 
@@ -442,6 +441,10 @@ static int mtk_iommu_add_device(struct device *dev)
                iommu_spec.args_count = count;
 
                mtk_iommu_create_mapping(dev, &iommu_spec);
+
+               /* dev->iommu_fwspec might have changed */
+               fwspec = dev_iommu_fwspec_get(dev);
+
                of_node_put(iommu_spec.np);
        }
 
index d8947b2..f04a6df 100644 (file)
@@ -224,7 +224,7 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
         * If we have reason to believe the IOMMU driver missed the initial
         * probe for dev, replay it to get things in order.
         */
-       if (dev->bus && !device_iommu_mapped(dev))
+       if (!err && dev->bus && !device_iommu_mapped(dev))
                err = iommu_probe_device(dev);
 
        /* Ignore all other errors apart from EPROBE_DEFER */
index 2543bab..5a2ec43 100644 (file)
@@ -95,7 +95,7 @@ static inline void setup_irq_channel(u32 magic, void __iomem *reg_addr)
 
        /* Setup 64 channel slots */
        for (i = 0; i < INTC_IRQS; i += 4)
-               writel_relaxed(build_channel_val(i, magic), reg_addr + i);
+               writel(build_channel_val(i, magic), reg_addr + i);
 }
 
 static int __init
@@ -135,16 +135,10 @@ ck_intc_init_comm(struct device_node *node, struct device_node *parent)
 static inline bool handle_irq_perbit(struct pt_regs *regs, u32 hwirq,
                                     u32 irq_base)
 {
-       u32 irq;
-
        if (hwirq == 0)
                return 0;
 
-       while (hwirq) {
-               irq = __ffs(hwirq);
-               hwirq &= ~BIT(irq);
-               handle_domain_irq(root_domain, irq_base + irq, regs);
-       }
+       handle_domain_irq(root_domain, irq_base + __fls(hwirq), regs);
 
        return 1;
 }
@@ -154,12 +148,16 @@ static void gx_irq_handler(struct pt_regs *regs)
 {
        bool ret;
 
-       do {
-               ret  = handle_irq_perbit(regs,
-                               readl_relaxed(reg_base + GX_INTC_PEN31_00), 0);
-               ret |= handle_irq_perbit(regs,
-                               readl_relaxed(reg_base + GX_INTC_PEN63_32), 32);
-       } while (ret);
+retry:
+       ret = handle_irq_perbit(regs,
+                       readl(reg_base + GX_INTC_PEN63_32), 32);
+       if (ret)
+               goto retry;
+
+       ret = handle_irq_perbit(regs,
+                       readl(reg_base + GX_INTC_PEN31_00), 0);
+       if (ret)
+               goto retry;
 }
 
 static int __init
@@ -174,14 +172,14 @@ gx_intc_init(struct device_node *node, struct device_node *parent)
        /*
         * Initial enable reg to disable all interrupts
         */
-       writel_relaxed(0x0, reg_base + GX_INTC_NEN31_00);
-       writel_relaxed(0x0, reg_base + GX_INTC_NEN63_32);
+       writel(0x0, reg_base + GX_INTC_NEN31_00);
+       writel(0x0, reg_base + GX_INTC_NEN63_32);
 
        /*
         * Initial mask reg with all unmasked, because we only use enalbe reg
         */
-       writel_relaxed(0x0, reg_base + GX_INTC_NMASK31_00);
-       writel_relaxed(0x0, reg_base + GX_INTC_NMASK63_32);
+       writel(0x0, reg_base + GX_INTC_NMASK31_00);
+       writel(0x0, reg_base + GX_INTC_NMASK63_32);
 
        setup_irq_channel(0x03020100, reg_base + GX_INTC_SOURCE);
 
@@ -204,20 +202,29 @@ static void ck_irq_handler(struct pt_regs *regs)
        void __iomem *reg_pen_lo = reg_base + CK_INTC_PEN31_00;
        void __iomem *reg_pen_hi = reg_base + CK_INTC_PEN63_32;
 
-       do {
-               /* handle 0 - 31 irqs */
-               ret  = handle_irq_perbit(regs, readl_relaxed(reg_pen_lo), 0);
-               ret |= handle_irq_perbit(regs, readl_relaxed(reg_pen_hi), 32);
+retry:
+       /* handle 0 - 63 irqs */
+       ret = handle_irq_perbit(regs, readl(reg_pen_hi), 32);
+       if (ret)
+               goto retry;
 
-               if (nr_irq == INTC_IRQS)
-                       continue;
+       ret = handle_irq_perbit(regs, readl(reg_pen_lo), 0);
+       if (ret)
+               goto retry;
+
+       if (nr_irq == INTC_IRQS)
+               return;
 
-               /* handle 64 - 127 irqs */
-               ret |= handle_irq_perbit(regs,
-                       readl_relaxed(reg_pen_lo + CK_INTC_DUAL_BASE), 64);
-               ret |= handle_irq_perbit(regs,
-                       readl_relaxed(reg_pen_hi + CK_INTC_DUAL_BASE), 96);
-       } while (ret);
+       /* handle 64 - 127 irqs */
+       ret = handle_irq_perbit(regs,
+                       readl(reg_pen_hi + CK_INTC_DUAL_BASE), 96);
+       if (ret)
+               goto retry;
+
+       ret = handle_irq_perbit(regs,
+                       readl(reg_pen_lo + CK_INTC_DUAL_BASE), 64);
+       if (ret)
+               goto retry;
 }
 
 static int __init
@@ -230,11 +237,11 @@ ck_intc_init(struct device_node *node, struct device_node *parent)
                return ret;
 
        /* Initial enable reg to disable all interrupts */
-       writel_relaxed(0, reg_base + CK_INTC_NEN31_00);
-       writel_relaxed(0, reg_base + CK_INTC_NEN63_32);
+       writel(0, reg_base + CK_INTC_NEN31_00);
+       writel(0, reg_base + CK_INTC_NEN63_32);
 
        /* Enable irq intc */
-       writel_relaxed(BIT(31), reg_base + CK_INTC_ICR);
+       writel(BIT(31), reg_base + CK_INTC_ICR);
 
        ck_set_gc(node, reg_base, CK_INTC_NEN31_00, 0);
        ck_set_gc(node, reg_base, CK_INTC_NEN63_32, 32);
@@ -260,8 +267,8 @@ ck_dual_intc_init(struct device_node *node, struct device_node *parent)
                return ret;
 
        /* Initial enable reg to disable all interrupts */
-       writel_relaxed(0, reg_base + CK_INTC_NEN31_00 + CK_INTC_DUAL_BASE);
-       writel_relaxed(0, reg_base + CK_INTC_NEN63_32 + CK_INTC_DUAL_BASE);
+       writel(0, reg_base + CK_INTC_NEN31_00 + CK_INTC_DUAL_BASE);
+       writel(0, reg_base + CK_INTC_NEN63_32 + CK_INTC_DUAL_BASE);
 
        ck_set_gc(node, reg_base + CK_INTC_DUAL_BASE, CK_INTC_NEN31_00, 64);
        ck_set_gc(node, reg_base + CK_INTC_DUAL_BASE, CK_INTC_NEN63_32, 96);
index db20e99..c3aba3f 100644 (file)
@@ -97,9 +97,14 @@ struct its_device;
  * The ITS structure - contains most of the infrastructure, with the
  * top-level MSI domain, the command queue, the collections, and the
  * list of devices writing to it.
+ *
+ * dev_alloc_lock has to be taken for device allocations, while the
+ * spinlock must be taken to parse data structures such as the device
+ * list.
  */
 struct its_node {
        raw_spinlock_t          lock;
+       struct mutex            dev_alloc_lock;
        struct list_head        entry;
        void __iomem            *base;
        phys_addr_t             phys_base;
@@ -156,6 +161,7 @@ struct its_device {
        void                    *itt;
        u32                     nr_ites;
        u32                     device_id;
+       bool                    shared;
 };
 
 static struct {
@@ -1580,6 +1586,9 @@ static unsigned long *its_lpi_alloc(int nr_irqs, u32 *base, int *nr_ids)
                nr_irqs /= 2;
        } while (nr_irqs > 0);
 
+       if (!nr_irqs)
+               err = -ENOSPC;
+
        if (err)
                goto out;
 
@@ -2059,6 +2068,29 @@ static int __init allocate_lpi_tables(void)
        return 0;
 }
 
+static u64 its_clear_vpend_valid(void __iomem *vlpi_base)
+{
+       u32 count = 1000000;    /* 1s! */
+       bool clean;
+       u64 val;
+
+       val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
+       val &= ~GICR_VPENDBASER_Valid;
+       gits_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
+
+       do {
+               val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
+               clean = !(val & GICR_VPENDBASER_Dirty);
+               if (!clean) {
+                       count--;
+                       cpu_relax();
+                       udelay(1);
+               }
+       } while (!clean && count);
+
+       return val;
+}
+
 static void its_cpu_init_lpis(void)
 {
        void __iomem *rbase = gic_data_rdist_rd_base();
@@ -2144,6 +2176,30 @@ static void its_cpu_init_lpis(void)
        val |= GICR_CTLR_ENABLE_LPIS;
        writel_relaxed(val, rbase + GICR_CTLR);
 
+       if (gic_rdists->has_vlpis) {
+               void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
+
+               /*
+                * It's possible for CPU to receive VLPIs before it is
+                * sheduled as a vPE, especially for the first CPU, and the
+                * VLPI with INTID larger than 2^(IDbits+1) will be considered
+                * as out of range and dropped by GIC.
+                * So we initialize IDbits to known value to avoid VLPI drop.
+                */
+               val = (LPI_NRBITS - 1) & GICR_VPROPBASER_IDBITS_MASK;
+               pr_debug("GICv4: CPU%d: Init IDbits to 0x%llx for GICR_VPROPBASER\n",
+                       smp_processor_id(), val);
+               gits_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
+
+               /*
+                * Also clear Valid bit of GICR_VPENDBASER, in case some
+                * ancient programming gets left in and has possibility of
+                * corrupting memory.
+                */
+               val = its_clear_vpend_valid(vlpi_base);
+               WARN_ON(val & GICR_VPENDBASER_Dirty);
+       }
+
        /* Make sure the GIC has seen the above */
        dsb(sy);
 out:
@@ -2399,13 +2455,14 @@ static void its_free_device(struct its_device *its_dev)
        kfree(its_dev);
 }
 
-static int its_alloc_device_irq(struct its_device *dev, irq_hw_number_t *hwirq)
+static int its_alloc_device_irq(struct its_device *dev, int nvecs, irq_hw_number_t *hwirq)
 {
        int idx;
 
-       idx = find_first_zero_bit(dev->event_map.lpi_map,
-                                 dev->event_map.nr_lpis);
-       if (idx == dev->event_map.nr_lpis)
+       idx = bitmap_find_free_region(dev->event_map.lpi_map,
+                                     dev->event_map.nr_lpis,
+                                     get_count_order(nvecs));
+       if (idx < 0)
                return -ENOSPC;
 
        *hwirq = dev->event_map.lpi_base + idx;
@@ -2421,6 +2478,7 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
        struct its_device *its_dev;
        struct msi_domain_info *msi_info;
        u32 dev_id;
+       int err = 0;
 
        /*
         * We ignore "dev" entierely, and rely on the dev_id that has
@@ -2443,6 +2501,7 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
                return -EINVAL;
        }
 
+       mutex_lock(&its->dev_alloc_lock);
        its_dev = its_find_device(its, dev_id);
        if (its_dev) {
                /*
@@ -2450,18 +2509,22 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
                 * another alias (PCI bridge of some sort). No need to
                 * create the device.
                 */
+               its_dev->shared = true;
                pr_debug("Reusing ITT for devID %x\n", dev_id);
                goto out;
        }
 
        its_dev = its_create_device(its, dev_id, nvec, true);
-       if (!its_dev)
-               return -ENOMEM;
+       if (!its_dev) {
+               err = -ENOMEM;
+               goto out;
+       }
 
        pr_debug("ITT %d entries, %d bits\n", nvec, ilog2(nvec));
 out:
+       mutex_unlock(&its->dev_alloc_lock);
        info->scratchpad[0].ptr = its_dev;
-       return 0;
+       return err;
 }
 
 static struct msi_domain_ops its_msi_domain_ops = {
@@ -2501,21 +2564,21 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
        int err;
        int i;
 
-       for (i = 0; i < nr_irqs; i++) {
-               err = its_alloc_device_irq(its_dev, &hwirq);
-               if (err)
-                       return err;
+       err = its_alloc_device_irq(its_dev, nr_irqs, &hwirq);
+       if (err)
+               return err;
 
-               err = its_irq_gic_domain_alloc(domain, virq + i, hwirq);
+       for (i = 0; i < nr_irqs; i++) {
+               err = its_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
                if (err)
                        return err;
 
                irq_domain_set_hwirq_and_chip(domain, virq + i,
-                                             hwirq, &its_irq_chip, its_dev);
+                                             hwirq + i, &its_irq_chip, its_dev);
                irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq + i)));
                pr_debug("ID:%d pID:%d vID:%d\n",
-                        (int)(hwirq - its_dev->event_map.lpi_base),
-                        (int) hwirq, virq + i);
+                        (int)(hwirq + i - its_dev->event_map.lpi_base),
+                        (int)(hwirq + i), virq + i);
        }
 
        return 0;
@@ -2565,6 +2628,7 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
 {
        struct irq_data *d = irq_domain_get_irq_data(domain, virq);
        struct its_device *its_dev = irq_data_get_irq_chip_data(d);
+       struct its_node *its = its_dev->its;
        int i;
 
        for (i = 0; i < nr_irqs; i++) {
@@ -2579,8 +2643,14 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
                irq_domain_reset_irq_data(data);
        }
 
-       /* If all interrupts have been freed, start mopping the floor */
-       if (bitmap_empty(its_dev->event_map.lpi_map,
+       mutex_lock(&its->dev_alloc_lock);
+
+       /*
+        * If all interrupts have been freed, start mopping the
+        * floor. This is conditionned on the device not being shared.
+        */
+       if (!its_dev->shared &&
+           bitmap_empty(its_dev->event_map.lpi_map,
                         its_dev->event_map.nr_lpis)) {
                its_lpi_free(its_dev->event_map.lpi_map,
                             its_dev->event_map.lpi_base,
@@ -2592,6 +2662,8 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
                its_free_device(its_dev);
        }
 
+       mutex_unlock(&its->dev_alloc_lock);
+
        irq_domain_free_irqs_parent(domain, virq, nr_irqs);
 }
 
@@ -2754,26 +2826,11 @@ static void its_vpe_schedule(struct its_vpe *vpe)
 static void its_vpe_deschedule(struct its_vpe *vpe)
 {
        void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
-       u32 count = 1000000;    /* 1s! */
-       bool clean;
        u64 val;
 
-       /* We're being scheduled out */
-       val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
-       val &= ~GICR_VPENDBASER_Valid;
-       gits_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
-
-       do {
-               val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
-               clean = !(val & GICR_VPENDBASER_Dirty);
-               if (!clean) {
-                       count--;
-                       cpu_relax();
-                       udelay(1);
-               }
-       } while (!clean && count);
+       val = its_clear_vpend_valid(vlpi_base);
 
-       if (unlikely(!clean && !count)) {
+       if (unlikely(val & GICR_VPENDBASER_Dirty)) {
                pr_err_ratelimited("ITS virtual pending table not cleaning\n");
                vpe->idai = false;
                vpe->pending_last = true;
@@ -3516,6 +3573,7 @@ static int __init its_probe_one(struct resource *res,
        }
 
        raw_spin_lock_init(&its->lock);
+       mutex_init(&its->dev_alloc_lock);
        INIT_LIST_HEAD(&its->entry);
        INIT_LIST_HEAD(&its->its_device_list);
        typer = gic_read_typer(its_base + GITS_TYPER);
index ad70e7c..fbfa7ff 100644 (file)
@@ -24,7 +24,7 @@ struct mbi_range {
        unsigned long           *bm;
 };
 
-static struct mutex            mbi_lock;
+static DEFINE_MUTEX(mbi_lock);
 static phys_addr_t             mbi_phys_base;
 static struct mbi_range                *mbi_ranges;
 static unsigned int            mbi_range_nr;
index e9256de..8b81271 100644 (file)
@@ -7,7 +7,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
@@ -16,7 +15,6 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/of_gpio.h>
 #include <linux/of_irq.h>
 #include <linux/irqchip/irq-madera.h>
 #include <linux/mfd/madera/core.h>
index 25f32e1..3496b61 100644 (file)
@@ -34,6 +34,9 @@
 #define SEL_INT_PENDING                (1 << 6)
 #define SEL_INT_NUM_MASK       0x3f
 
+#define MMP2_ICU_INT_ROUTE_PJ4_IRQ     (1 << 5)
+#define MMP2_ICU_INT_ROUTE_PJ4_FIQ     (1 << 6)
+
 struct icu_chip_data {
        int                     nr_irqs;
        unsigned int            virq_base;
@@ -190,7 +193,8 @@ static const struct mmp_intc_conf mmp_conf = {
 static const struct mmp_intc_conf mmp2_conf = {
        .conf_enable    = 0x20,
        .conf_disable   = 0x0,
-       .conf_mask      = 0x7f,
+       .conf_mask      = MMP2_ICU_INT_ROUTE_PJ4_IRQ |
+                         MMP2_ICU_INT_ROUTE_PJ4_FIQ,
 };
 
 static void __exception_irq_entry mmp_handle_irq(struct pt_regs *regs)
index 6edfd4b..a93296b 100644 (file)
@@ -822,6 +822,7 @@ out_unmap:
 static const struct irq_domain_ops stm32_exti_h_domain_ops = {
        .alloc  = stm32_exti_h_domain_alloc,
        .free   = irq_domain_free_irqs_common,
+       .xlate = irq_domain_xlate_twocell,
 };
 
 static int
index 5385f57..2793333 100644 (file)
@@ -71,14 +71,17 @@ static void xtensa_mx_irq_mask(struct irq_data *d)
        unsigned int mask = 1u << d->hwirq;
 
        if (mask & (XCHAL_INTTYPE_MASK_EXTERN_EDGE |
-                               XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) {
-               set_er(1u << (xtensa_get_ext_irq_no(d->hwirq) -
-                                       HW_IRQ_MX_BASE), MIENG);
-       } else {
-               mask = __this_cpu_read(cached_irq_mask) & ~mask;
-               __this_cpu_write(cached_irq_mask, mask);
-               xtensa_set_sr(mask, intenable);
+                   XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) {
+               unsigned int ext_irq = xtensa_get_ext_irq_no(d->hwirq);
+
+               if (ext_irq >= HW_IRQ_MX_BASE) {
+                       set_er(1u << (ext_irq - HW_IRQ_MX_BASE), MIENG);
+                       return;
+               }
        }
+       mask = __this_cpu_read(cached_irq_mask) & ~mask;
+       __this_cpu_write(cached_irq_mask, mask);
+       xtensa_set_sr(mask, intenable);
 }
 
 static void xtensa_mx_irq_unmask(struct irq_data *d)
@@ -86,14 +89,17 @@ static void xtensa_mx_irq_unmask(struct irq_data *d)
        unsigned int mask = 1u << d->hwirq;
 
        if (mask & (XCHAL_INTTYPE_MASK_EXTERN_EDGE |
-                               XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) {
-               set_er(1u << (xtensa_get_ext_irq_no(d->hwirq) -
-                                       HW_IRQ_MX_BASE), MIENGSET);
-       } else {
-               mask |= __this_cpu_read(cached_irq_mask);
-               __this_cpu_write(cached_irq_mask, mask);
-               xtensa_set_sr(mask, intenable);
+                   XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) {
+               unsigned int ext_irq = xtensa_get_ext_irq_no(d->hwirq);
+
+               if (ext_irq >= HW_IRQ_MX_BASE) {
+                       set_er(1u << (ext_irq - HW_IRQ_MX_BASE), MIENGSET);
+                       return;
+               }
        }
+       mask |= __this_cpu_read(cached_irq_mask);
+       __this_cpu_write(cached_irq_mask, mask);
+       xtensa_set_sr(mask, intenable);
 }
 
 static void xtensa_mx_irq_enable(struct irq_data *d)
@@ -113,7 +119,11 @@ static void xtensa_mx_irq_ack(struct irq_data *d)
 
 static int xtensa_mx_irq_retrigger(struct irq_data *d)
 {
-       xtensa_set_sr(1 << d->hwirq, intset);
+       unsigned int mask = 1u << d->hwirq;
+
+       if (WARN_ON(mask & ~XCHAL_INTTYPE_MASK_SOFTWARE))
+               return 0;
+       xtensa_set_sr(mask, intset);
        return 1;
 }
 
index c200234..ab12328 100644 (file)
@@ -70,7 +70,11 @@ static void xtensa_irq_ack(struct irq_data *d)
 
 static int xtensa_irq_retrigger(struct irq_data *d)
 {
-       xtensa_set_sr(1 << d->hwirq, intset);
+       unsigned int mask = 1u << d->hwirq;
+
+       if (WARN_ON(mask & ~XCHAL_INTTYPE_MASK_SOFTWARE))
+               return 0;
+       xtensa_set_sr(mask, intset);
        return 1;
 }
 
index 4ac378e..40ca1e8 100644 (file)
@@ -423,7 +423,7 @@ void b1_parse_version(avmctrl_info *cinfo)
        int i, j;
 
        for (j = 0; j < AVM_MAXVERSION; j++)
-               cinfo->version[j] = "\0\0" + 1;
+               cinfo->version[j] = "";
        for (i = 0, j = 0;
             j < AVM_MAXVERSION && i < cinfo->versionlen;
             j++, i += cinfo->versionbuf[i] + 1)
index 6d05946..124ff53 100644 (file)
@@ -262,8 +262,7 @@ hfcsusb_ph_info(struct hfcsusb *hw)
        struct dchannel *dch = &hw->dch;
        int i;
 
-       phi = kzalloc(sizeof(struct ph_info) +
-                     dch->dev.nrbchan * sizeof(struct ph_info_ch), GFP_ATOMIC);
+       phi = kzalloc(struct_size(phi, bch, dch->dev.nrbchan), GFP_ATOMIC);
        phi->dch.ch.protocol = hw->protocol;
        phi->dch.ch.Flags = dch->Flags;
        phi->dch.state = dch->state;
index 1b2239c..dc1cded 100644 (file)
@@ -1437,15 +1437,19 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        modem_info *info = (modem_info *) tty->driver_data;
 
+       mutex_lock(&modem_info_mutex);
        if (!old_termios)
                isdn_tty_change_speed(info);
        else {
                if (tty->termios.c_cflag == old_termios->c_cflag &&
                    tty->termios.c_ispeed == old_termios->c_ispeed &&
-                   tty->termios.c_ospeed == old_termios->c_ospeed)
+                   tty->termios.c_ospeed == old_termios->c_ospeed) {
+                       mutex_unlock(&modem_info_mutex);
                        return;
+               }
                isdn_tty_change_speed(info);
        }
+       mutex_unlock(&modem_info_mutex);
 }
 
 /*
index 211ed6c..5789787 100644 (file)
@@ -170,8 +170,8 @@ dev_expire_timer(struct timer_list *t)
        spin_lock_irqsave(&timer->dev->lock, flags);
        if (timer->id >= 0)
                list_move_tail(&timer->list, &timer->dev->expired);
-       spin_unlock_irqrestore(&timer->dev->lock, flags);
        wake_up_interruptible(&timer->dev->wait);
+       spin_unlock_irqrestore(&timer->dev->lock, flags);
 }
 
 static int
index a2e74fe..fd64df5 100644 (file)
@@ -318,7 +318,9 @@ static int lp5523_init_program_engine(struct lp55xx_chip *chip)
 
        /* Let the programs run for couple of ms and check the engine status */
        usleep_range(3000, 6000);
-       lp55xx_read(chip, LP5523_REG_STATUS, &status);
+       ret = lp55xx_read(chip, LP5523_REG_STATUS, &status);
+       if (ret)
+               return ret;
        status &= LP5523_ENG_STATUS_MASK;
 
        if (status != LP5523_ENG_STATUS_MASK) {
index 0ff2215..dd538e6 100644 (file)
@@ -932,7 +932,7 @@ static int dm_crypt_integrity_io_alloc(struct dm_crypt_io *io, struct bio *bio)
        if (IS_ERR(bip))
                return PTR_ERR(bip);
 
-       tag_len = io->cc->on_disk_tag_size * bio_sectors(bio);
+       tag_len = io->cc->on_disk_tag_size * (bio_sectors(bio) >> io->cc->sector_shift);
 
        bip->bip_iter.bi_size = tag_len;
        bip->bip_iter.bi_sector = io->cc->start + io->sector;
@@ -2414,9 +2414,21 @@ static int crypt_ctr_cipher_new(struct dm_target *ti, char *cipher_in, char *key
         * capi:cipher_api_spec-iv:ivopts
         */
        tmp = &cipher_in[strlen("capi:")];
-       cipher_api = strsep(&tmp, "-");
-       *ivmode = strsep(&tmp, ":");
-       *ivopts = tmp;
+
+       /* Separate IV options if present, it can contain another '-' in hash name */
+       *ivopts = strrchr(tmp, ':');
+       if (*ivopts) {
+               **ivopts = '\0';
+               (*ivopts)++;
+       }
+       /* Parse IV mode */
+       *ivmode = strrchr(tmp, '-');
+       if (*ivmode) {
+               **ivmode = '\0';
+               (*ivmode)++;
+       }
+       /* The rest is crypto API spec */
+       cipher_api = tmp;
 
        if (*ivmode && !strcmp(*ivmode, "lmk"))
                cc->tfms_count = 64;
@@ -2486,11 +2498,8 @@ static int crypt_ctr_cipher_old(struct dm_target *ti, char *cipher_in, char *key
                goto bad_mem;
 
        chainmode = strsep(&tmp, "-");
-       *ivopts = strsep(&tmp, "-");
-       *ivmode = strsep(&*ivopts, ":");
-
-       if (tmp)
-               DMWARN("Ignoring unexpected additional cipher options");
+       *ivmode = strsep(&tmp, ":");
+       *ivopts = tmp;
 
        /*
         * For compatibility with the original dm-crypt mapping format, if
index 4eb5f8c..a20531e 100644 (file)
@@ -131,7 +131,7 @@ static void rq_end_stats(struct mapped_device *md, struct request *orig)
 static void rq_completed(struct mapped_device *md)
 {
        /* nudge anyone waiting on suspend queue */
-       if (unlikely(waitqueue_active(&md->wait)))
+       if (unlikely(wq_has_sleeper(&md->wait)))
                wake_up(&md->wait);
 
        /*
index 20b0776..ed3cace 100644 (file)
@@ -1678,7 +1678,7 @@ int dm_thin_remove_range(struct dm_thin_device *td,
        return r;
 }
 
-int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *result)
+int dm_pool_block_is_shared(struct dm_pool_metadata *pmd, dm_block_t b, bool *result)
 {
        int r;
        uint32_t ref_count;
@@ -1686,7 +1686,7 @@ int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *resu
        down_read(&pmd->root_lock);
        r = dm_sm_get_count(pmd->data_sm, b, &ref_count);
        if (!r)
-               *result = (ref_count != 0);
+               *result = (ref_count > 1);
        up_read(&pmd->root_lock);
 
        return r;
index 35e954e..f6be0d7 100644 (file)
@@ -195,7 +195,7 @@ int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd,
 
 int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result);
 
-int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *result);
+int dm_pool_block_is_shared(struct dm_pool_metadata *pmd, dm_block_t b, bool *result);
 
 int dm_pool_inc_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_t e);
 int dm_pool_dec_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_t e);
index dadd969..e83b636 100644 (file)
@@ -257,6 +257,7 @@ struct pool {
 
        spinlock_t lock;
        struct bio_list deferred_flush_bios;
+       struct bio_list deferred_flush_completions;
        struct list_head prepared_mappings;
        struct list_head prepared_discards;
        struct list_head prepared_discards_pt2;
@@ -956,6 +957,39 @@ static void process_prepared_mapping_fail(struct dm_thin_new_mapping *m)
        mempool_free(m, &m->tc->pool->mapping_pool);
 }
 
+static void complete_overwrite_bio(struct thin_c *tc, struct bio *bio)
+{
+       struct pool *pool = tc->pool;
+       unsigned long flags;
+
+       /*
+        * If the bio has the REQ_FUA flag set we must commit the metadata
+        * before signaling its completion.
+        */
+       if (!bio_triggers_commit(tc, bio)) {
+               bio_endio(bio);
+               return;
+       }
+
+       /*
+        * Complete bio with an error if earlier I/O caused changes to the
+        * metadata that can't be committed, e.g, due to I/O errors on the
+        * metadata device.
+        */
+       if (dm_thin_aborted_changes(tc->td)) {
+               bio_io_error(bio);
+               return;
+       }
+
+       /*
+        * Batch together any bios that trigger commits and then issue a
+        * single commit for them in process_deferred_bios().
+        */
+       spin_lock_irqsave(&pool->lock, flags);
+       bio_list_add(&pool->deferred_flush_completions, bio);
+       spin_unlock_irqrestore(&pool->lock, flags);
+}
+
 static void process_prepared_mapping(struct dm_thin_new_mapping *m)
 {
        struct thin_c *tc = m->tc;
@@ -988,7 +1022,7 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
         */
        if (bio) {
                inc_remap_and_issue_cell(tc, m->cell, m->data_block);
-               bio_endio(bio);
+               complete_overwrite_bio(tc, bio);
        } else {
                inc_all_io_entry(tc->pool, m->cell->holder);
                remap_and_issue(tc, m->cell->holder, m->data_block);
@@ -1048,7 +1082,7 @@ static void passdown_double_checking_shared_status(struct dm_thin_new_mapping *m
         * passdown we have to check that these blocks are now unused.
         */
        int r = 0;
-       bool used = true;
+       bool shared = true;
        struct thin_c *tc = m->tc;
        struct pool *pool = tc->pool;
        dm_block_t b = m->data_block, e, end = m->data_block + m->virt_end - m->virt_begin;
@@ -1058,11 +1092,11 @@ static void passdown_double_checking_shared_status(struct dm_thin_new_mapping *m
        while (b != end) {
                /* find start of unmapped run */
                for (; b < end; b++) {
-                       r = dm_pool_block_is_used(pool->pmd, b, &used);
+                       r = dm_pool_block_is_shared(pool->pmd, b, &shared);
                        if (r)
                                goto out;
 
-                       if (!used)
+                       if (!shared)
                                break;
                }
 
@@ -1071,11 +1105,11 @@ static void passdown_double_checking_shared_status(struct dm_thin_new_mapping *m
 
                /* find end of run */
                for (e = b + 1; e != end; e++) {
-                       r = dm_pool_block_is_used(pool->pmd, e, &used);
+                       r = dm_pool_block_is_shared(pool->pmd, e, &shared);
                        if (r)
                                goto out;
 
-                       if (used)
+                       if (shared)
                                break;
                }
 
@@ -2317,7 +2351,7 @@ static void process_deferred_bios(struct pool *pool)
 {
        unsigned long flags;
        struct bio *bio;
-       struct bio_list bios;
+       struct bio_list bios, bio_completions;
        struct thin_c *tc;
 
        tc = get_first_thin(pool);
@@ -2328,26 +2362,36 @@ static void process_deferred_bios(struct pool *pool)
        }
 
        /*
-        * If there are any deferred flush bios, we must commit
-        * the metadata before issuing them.
+        * If there are any deferred flush bios, we must commit the metadata
+        * before issuing them or signaling their completion.
         */
        bio_list_init(&bios);
+       bio_list_init(&bio_completions);
+
        spin_lock_irqsave(&pool->lock, flags);
        bio_list_merge(&bios, &pool->deferred_flush_bios);
        bio_list_init(&pool->deferred_flush_bios);
+
+       bio_list_merge(&bio_completions, &pool->deferred_flush_completions);
+       bio_list_init(&pool->deferred_flush_completions);
        spin_unlock_irqrestore(&pool->lock, flags);
 
-       if (bio_list_empty(&bios) &&
+       if (bio_list_empty(&bios) && bio_list_empty(&bio_completions) &&
            !(dm_pool_changed_this_transaction(pool->pmd) && need_commit_due_to_time(pool)))
                return;
 
        if (commit(pool)) {
+               bio_list_merge(&bios, &bio_completions);
+
                while ((bio = bio_list_pop(&bios)))
                        bio_io_error(bio);
                return;
        }
        pool->last_commit_jiffies = jiffies;
 
+       while ((bio = bio_list_pop(&bio_completions)))
+               bio_endio(bio);
+
        while ((bio = bio_list_pop(&bios)))
                generic_make_request(bio);
 }
@@ -2954,6 +2998,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
        INIT_DELAYED_WORK(&pool->no_space_timeout, do_no_space_timeout);
        spin_lock_init(&pool->lock);
        bio_list_init(&pool->deferred_flush_bios);
+       bio_list_init(&pool->deferred_flush_completions);
        INIT_LIST_HEAD(&pool->prepared_mappings);
        INIT_LIST_HEAD(&pool->prepared_discards);
        INIT_LIST_HEAD(&pool->prepared_discards_pt2);
index d67c95e..515e6af 100644 (file)
@@ -699,7 +699,7 @@ static void end_io_acct(struct dm_io *io)
                                    true, duration, &io->stats_aux);
 
        /* nudge anyone waiting on suspend queue */
-       if (unlikely(waitqueue_active(&md->wait)))
+       if (unlikely(wq_has_sleeper(&md->wait)))
                wake_up(&md->wait);
 }
 
@@ -1320,7 +1320,7 @@ static int clone_bio(struct dm_target_io *tio, struct bio *bio,
 
        __bio_clone_fast(clone, bio);
 
-       if (unlikely(bio_integrity(bio) != NULL)) {
+       if (bio_integrity(bio)) {
                int r;
 
                if (unlikely(!dm_target_has_integrity(tio->ti->type) &&
@@ -1339,7 +1339,7 @@ static int clone_bio(struct dm_target_io *tio, struct bio *bio,
        bio_advance(clone, to_bytes(sector - clone->bi_iter.bi_sector));
        clone->bi_iter.bi_size = to_bytes(len);
 
-       if (unlikely(bio_integrity(bio) != NULL))
+       if (bio_integrity(bio))
                bio_integrity_trim(clone);
 
        return 0;
@@ -1588,6 +1588,9 @@ static void init_clone_info(struct clone_info *ci, struct mapped_device *md,
        ci->sector = bio->bi_iter.bi_sector;
 }
 
+#define __dm_part_stat_sub(part, field, subnd) \
+       (part_stat_get(part, field) -= (subnd))
+
 /*
  * Entry point to split a bio into clones and submit them to the targets.
  */
@@ -1642,7 +1645,21 @@ static blk_qc_t __split_and_process_bio(struct mapped_device *md,
                                struct bio *b = bio_split(bio, bio_sectors(bio) - ci.sector_count,
                                                          GFP_NOIO, &md->queue->bio_split);
                                ci.io->orig_bio = b;
+
+                               /*
+                                * Adjust IO stats for each split, otherwise upon queue
+                                * reentry there will be redundant IO accounting.
+                                * NOTE: this is a stop-gap fix, a proper fix involves
+                                * significant refactoring of DM core's bio splitting
+                                * (by eliminating DM's splitting and just using bio_split)
+                                */
+                               part_stat_lock();
+                               __dm_part_stat_sub(&dm_disk(md)->part0,
+                                                  sectors[op_stat_group(bio_op(bio))], ci.sector_count);
+                               part_stat_unlock();
+
                                bio_chain(b, bio);
+                               trace_block_split(md->queue, b, bio->bi_iter.bi_sector);
                                ret = generic_make_request(bio);
                                break;
                        }
@@ -1713,6 +1730,15 @@ out:
        return ret;
 }
 
+static blk_qc_t dm_process_bio(struct mapped_device *md,
+                              struct dm_table *map, struct bio *bio)
+{
+       if (dm_get_md_type(md) == DM_TYPE_NVME_BIO_BASED)
+               return __process_bio(md, map, bio);
+       else
+               return __split_and_process_bio(md, map, bio);
+}
+
 static blk_qc_t dm_make_request(struct request_queue *q, struct bio *bio)
 {
        struct mapped_device *md = q->queuedata;
@@ -1733,10 +1759,7 @@ static blk_qc_t dm_make_request(struct request_queue *q, struct bio *bio)
                return ret;
        }
 
-       if (dm_get_md_type(md) == DM_TYPE_NVME_BIO_BASED)
-               ret = __process_bio(md, map, bio);
-       else
-               ret = __split_and_process_bio(md, map, bio);
+       ret = dm_process_bio(md, map, bio);
 
        dm_put_live_table(md, srcu_idx);
        return ret;
@@ -2415,9 +2438,9 @@ static void dm_wq_work(struct work_struct *work)
                        break;
 
                if (dm_request_based(md))
-                       generic_make_request(c);
+                       (void) generic_make_request(c);
                else
-                       __split_and_process_bio(md, map, c);
+                       (void) dm_process_bio(md, map, c);
        }
 
        dm_put_live_table(md, srcu_idx);
index fd4af4d..05ffffb 100644 (file)
@@ -207,15 +207,10 @@ static bool create_on_open = true;
 struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
                            struct mddev *mddev)
 {
-       struct bio *b;
-
        if (!mddev || !bioset_initialized(&mddev->bio_set))
                return bio_alloc(gfp_mask, nr_iovecs);
 
-       b = bio_alloc_bioset(gfp_mask, nr_iovecs, &mddev->bio_set);
-       if (!b)
-               return NULL;
-       return b;
+       return bio_alloc_bioset(gfp_mask, nr_iovecs, &mddev->bio_set);
 }
 EXPORT_SYMBOL_GPL(bio_alloc_mddev);
 
index 1d54109..fa47249 100644 (file)
@@ -1863,6 +1863,20 @@ static void end_sync_read(struct bio *bio)
                reschedule_retry(r1_bio);
 }
 
+static void abort_sync_write(struct mddev *mddev, struct r1bio *r1_bio)
+{
+       sector_t sync_blocks = 0;
+       sector_t s = r1_bio->sector;
+       long sectors_to_go = r1_bio->sectors;
+
+       /* make sure these bits don't get cleared. */
+       do {
+               md_bitmap_end_sync(mddev->bitmap, s, &sync_blocks, 1);
+               s += sync_blocks;
+               sectors_to_go -= sync_blocks;
+       } while (sectors_to_go > 0);
+}
+
 static void end_sync_write(struct bio *bio)
 {
        int uptodate = !bio->bi_status;
@@ -1874,15 +1888,7 @@ static void end_sync_write(struct bio *bio)
        struct md_rdev *rdev = conf->mirrors[find_bio_disk(r1_bio, bio)].rdev;
 
        if (!uptodate) {
-               sector_t sync_blocks = 0;
-               sector_t s = r1_bio->sector;
-               long sectors_to_go = r1_bio->sectors;
-               /* make sure these bits doesn't get cleared. */
-               do {
-                       md_bitmap_end_sync(mddev->bitmap, s, &sync_blocks, 1);
-                       s += sync_blocks;
-                       sectors_to_go -= sync_blocks;
-               } while (sectors_to_go > 0);
+               abort_sync_write(mddev, r1_bio);
                set_bit(WriteErrorSeen, &rdev->flags);
                if (!test_and_set_bit(WantReplacement, &rdev->flags))
                        set_bit(MD_RECOVERY_NEEDED, &
@@ -2172,8 +2178,10 @@ static void sync_request_write(struct mddev *mddev, struct r1bio *r1_bio)
                     (i == r1_bio->read_disk ||
                      !test_bit(MD_RECOVERY_SYNC, &mddev->recovery))))
                        continue;
-               if (test_bit(Faulty, &conf->mirrors[i].rdev->flags))
+               if (test_bit(Faulty, &conf->mirrors[i].rdev->flags)) {
+                       abort_sync_write(mddev, r1_bio);
                        continue;
+               }
 
                bio_set_op_attrs(wbio, REQ_OP_WRITE, 0);
                if (test_bit(FailFast, &conf->mirrors[i].rdev->flags))
index ec3a5ef..cbbe6b6 100644 (file)
@@ -1935,12 +1935,14 @@ out:
 }
 
 static struct stripe_head *
-r5c_recovery_alloc_stripe(struct r5conf *conf,
-                         sector_t stripe_sect)
+r5c_recovery_alloc_stripe(
+               struct r5conf *conf,
+               sector_t stripe_sect,
+               int noblock)
 {
        struct stripe_head *sh;
 
-       sh = raid5_get_active_stripe(conf, stripe_sect, 0, 1, 0);
+       sh = raid5_get_active_stripe(conf, stripe_sect, 0, noblock, 0);
        if (!sh)
                return NULL;  /* no more stripe available */
 
@@ -2150,7 +2152,7 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
                                                stripe_sect);
 
                if (!sh) {
-                       sh = r5c_recovery_alloc_stripe(conf, stripe_sect);
+                       sh = r5c_recovery_alloc_stripe(conf, stripe_sect, 1);
                        /*
                         * cannot get stripe from raid5_get_active_stripe
                         * try replay some stripes
@@ -2159,20 +2161,29 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
                                r5c_recovery_replay_stripes(
                                        cached_stripe_list, ctx);
                                sh = r5c_recovery_alloc_stripe(
-                                       conf, stripe_sect);
+                                       conf, stripe_sect, 1);
                        }
                        if (!sh) {
+                               int new_size = conf->min_nr_stripes * 2;
                                pr_debug("md/raid:%s: Increasing stripe cache size to %d to recovery data on journal.\n",
                                        mdname(mddev),
-                                       conf->min_nr_stripes * 2);
-                               raid5_set_cache_size(mddev,
-                                                    conf->min_nr_stripes * 2);
-                               sh = r5c_recovery_alloc_stripe(conf,
-                                                              stripe_sect);
+                                       new_size);
+                               ret = raid5_set_cache_size(mddev, new_size);
+                               if (conf->min_nr_stripes <= new_size / 2) {
+                                       pr_err("md/raid:%s: Cannot increase cache size, ret=%d, new_size=%d, min_nr_stripes=%d, max_nr_stripes=%d\n",
+                                               mdname(mddev),
+                                               ret,
+                                               new_size,
+                                               conf->min_nr_stripes,
+                                               conf->max_nr_stripes);
+                                       return -ENOMEM;
+                               }
+                               sh = r5c_recovery_alloc_stripe(
+                                       conf, stripe_sect, 0);
                        }
                        if (!sh) {
                                pr_err("md/raid:%s: Cannot get enough stripes due to memory pressure. Recovery failed.\n",
-                                      mdname(mddev));
+                                       mdname(mddev));
                                return -ENOMEM;
                        }
                        list_add_tail(&sh->lru, cached_stripe_list);
index 4990f03..cecea90 100644 (file)
@@ -6369,6 +6369,7 @@ raid5_show_stripe_cache_size(struct mddev *mddev, char *page)
 int
 raid5_set_cache_size(struct mddev *mddev, int size)
 {
+       int result = 0;
        struct r5conf *conf = mddev->private;
 
        if (size <= 16 || size > 32768)
@@ -6385,11 +6386,14 @@ raid5_set_cache_size(struct mddev *mddev, int size)
 
        mutex_lock(&conf->cache_size_mutex);
        while (size > conf->max_nr_stripes)
-               if (!grow_one_stripe(conf, GFP_KERNEL))
+               if (!grow_one_stripe(conf, GFP_KERNEL)) {
+                       conf->min_nr_stripes = conf->max_nr_stripes;
+                       result = -ENOMEM;
                        break;
+               }
        mutex_unlock(&conf->cache_size_mutex);
 
-       return 0;
+       return result;
 }
 EXPORT_SYMBOL(raid5_set_cache_size);
 
index 447baae..cdb79ae 100644 (file)
@@ -218,8 +218,8 @@ static int cio2_fbpt_init(struct cio2_device *cio2, struct cio2_queue *q)
 {
        struct device *dev = &cio2->pci_dev->dev;
 
-       q->fbpt = dma_zalloc_coherent(dev, CIO2_FBPT_SIZE, &q->fbpt_bus_addr,
-                                     GFP_KERNEL);
+       q->fbpt = dma_alloc_coherent(dev, CIO2_FBPT_SIZE, &q->fbpt_bus_addr,
+                                    GFP_KERNEL);
        if (!q->fbpt)
                return -ENOMEM;
 
index e80123c..060c0ad 100644 (file)
@@ -49,7 +49,7 @@ int mtk_vcodec_mem_alloc(struct mtk_vcodec_ctx *data,
        struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)data;
        struct device *dev = &ctx->dev->plat_dev->dev;
 
-       mem->va = dma_zalloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL);
+       mem->va = dma_alloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL);
        if (!mem->va) {
                mtk_v4l2_err("%s dma_alloc size=%ld failed!", dev_name(dev),
                             size);
index d01821a..89d9c4c 100644 (file)
@@ -807,7 +807,9 @@ static void vim2m_stop_streaming(struct vb2_queue *q)
        struct vb2_v4l2_buffer *vbuf;
        unsigned long flags;
 
-       cancel_delayed_work_sync(&dev->work_run);
+       if (v4l2_m2m_get_curr_priv(dev->m2m_dev) == ctx)
+               cancel_delayed_work_sync(&dev->work_run);
+
        for (;;) {
                if (V4L2_TYPE_IS_OUTPUT(q->type))
                        vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
index 1441a73..90aad46 100644 (file)
@@ -287,6 +287,7 @@ static void v4l_print_format(const void *arg, bool write_only)
        const struct v4l2_window *win;
        const struct v4l2_sdr_format *sdr;
        const struct v4l2_meta_format *meta;
+       u32 planes;
        unsigned i;
 
        pr_cont("type=%s", prt_names(p->type, v4l2_type_names));
@@ -317,7 +318,8 @@ static void v4l_print_format(const void *arg, bool write_only)
                        prt_names(mp->field, v4l2_field_names),
                        mp->colorspace, mp->num_planes, mp->flags,
                        mp->ycbcr_enc, mp->quantization, mp->xfer_func);
-               for (i = 0; i < mp->num_planes; i++)
+               planes = min_t(u32, mp->num_planes, VIDEO_MAX_PLANES);
+               for (i = 0; i < planes; i++)
                        printk(KERN_DEBUG "plane %u: bytesperline=%u sizeimage=%u\n", i,
                                        mp->plane_fmt[i].bytesperline,
                                        mp->plane_fmt[i].sizeimage);
@@ -1551,8 +1553,11 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
                if (unlikely(!ops->vidioc_s_fmt_vid_cap_mplane))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
+               if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES)
+                       break;
                for (i = 0; i < p->fmt.pix_mp.num_planes; i++)
-                       CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline);
+                       CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i],
+                                         bytesperline);
                return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
                if (unlikely(!ops->vidioc_s_fmt_vid_overlay))
@@ -1581,8 +1586,11 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
                if (unlikely(!ops->vidioc_s_fmt_vid_out_mplane))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
+               if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES)
+                       break;
                for (i = 0; i < p->fmt.pix_mp.num_planes; i++)
-                       CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline);
+                       CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i],
+                                         bytesperline);
                return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
                if (unlikely(!ops->vidioc_s_fmt_vid_out_overlay))
@@ -1648,8 +1656,11 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
                if (unlikely(!ops->vidioc_try_fmt_vid_cap_mplane))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
+               if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES)
+                       break;
                for (i = 0; i < p->fmt.pix_mp.num_planes; i++)
-                       CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline);
+                       CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i],
+                                         bytesperline);
                return ops->vidioc_try_fmt_vid_cap_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
                if (unlikely(!ops->vidioc_try_fmt_vid_overlay))
@@ -1678,8 +1689,11 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
                if (unlikely(!ops->vidioc_try_fmt_vid_out_mplane))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
+               if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES)
+                       break;
                for (i = 0; i < p->fmt.pix_mp.num_planes; i++)
-                       CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline);
+                       CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i],
+                                         bytesperline);
                return ops->vidioc_try_fmt_vid_out_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
                if (unlikely(!ops->vidioc_try_fmt_vid_out_overlay))
index 8c5dfdc..76f9909 100644 (file)
@@ -102,6 +102,7 @@ config MFD_AAT2870_CORE
 config MFD_AT91_USART
        tristate "AT91 USART Driver"
        select MFD_CORE
+       depends on ARCH_AT91 || COMPILE_TEST
        help
          Select this to get support for AT91 USART IP. This is a wrapper
          over at91-usart-serial driver and usart-spi-driver. Only one function
@@ -1418,7 +1419,7 @@ config MFD_TPS65217
 
 config MFD_TPS68470
        bool "TI TPS68470 Power Management / LED chips"
-       depends on ACPI && I2C=y
+       depends on ACPI && PCI && I2C=y
        select MFD_CORE
        select REGMAP_I2C
        select I2C_DESIGNWARE_PLATFORM
index 30d09d1..11ab17f 100644 (file)
@@ -261,7 +261,7 @@ static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
        mutex_unlock(&ab8500->lock);
        dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
 
-       return ret;
+       return (ret < 0) ? ret : 0;
 }
 
 static int ab8500_get_register(struct device *dev, u8 bank,
index e1450a5..3c97f2c 100644 (file)
@@ -641,9 +641,9 @@ static const struct mfd_cell axp221_cells[] = {
 
 static const struct mfd_cell axp223_cells[] = {
        {
-               .name                   = "axp221-pek",
-               .num_resources          = ARRAY_SIZE(axp22x_pek_resources),
-               .resources              = axp22x_pek_resources,
+               .name           = "axp221-pek",
+               .num_resources  = ARRAY_SIZE(axp22x_pek_resources),
+               .resources      = axp22x_pek_resources,
        }, {
                .name           = "axp22x-adc",
                .of_compatible  = "x-powers,axp221-adc",
@@ -651,7 +651,7 @@ static const struct mfd_cell axp223_cells[] = {
                .name           = "axp20x-battery-power-supply",
                .of_compatible  = "x-powers,axp221-battery-power-supply",
        }, {
-               .name                   = "axp20x-regulator",
+               .name           = "axp20x-regulator",
        }, {
                .name           = "axp20x-ac-power-supply",
                .of_compatible  = "x-powers,axp221-ac-power-supply",
@@ -667,9 +667,9 @@ static const struct mfd_cell axp223_cells[] = {
 
 static const struct mfd_cell axp152_cells[] = {
        {
-               .name                   = "axp20x-pek",
-               .num_resources          = ARRAY_SIZE(axp152_pek_resources),
-               .resources              = axp152_pek_resources,
+               .name           = "axp20x-pek",
+               .num_resources  = ARRAY_SIZE(axp152_pek_resources),
+               .resources      = axp152_pek_resources,
        },
 };
 
@@ -698,87 +698,101 @@ static const struct resource axp288_charger_resources[] = {
 
 static const struct mfd_cell axp288_cells[] = {
        {
-               .name = "axp288_adc",
-               .num_resources = ARRAY_SIZE(axp288_adc_resources),
-               .resources = axp288_adc_resources,
-       },
-       {
-               .name = "axp288_extcon",
-               .num_resources = ARRAY_SIZE(axp288_extcon_resources),
-               .resources = axp288_extcon_resources,
-       },
-       {
-               .name = "axp288_charger",
-               .num_resources = ARRAY_SIZE(axp288_charger_resources),
-               .resources = axp288_charger_resources,
-       },
-       {
-               .name = "axp288_fuel_gauge",
-               .num_resources = ARRAY_SIZE(axp288_fuel_gauge_resources),
-               .resources = axp288_fuel_gauge_resources,
-       },
-       {
-               .name = "axp221-pek",
-               .num_resources = ARRAY_SIZE(axp288_power_button_resources),
-               .resources = axp288_power_button_resources,
-       },
-       {
-               .name = "axp288_pmic_acpi",
+               .name           = "axp288_adc",
+               .num_resources  = ARRAY_SIZE(axp288_adc_resources),
+               .resources      = axp288_adc_resources,
+       }, {
+               .name           = "axp288_extcon",
+               .num_resources  = ARRAY_SIZE(axp288_extcon_resources),
+               .resources      = axp288_extcon_resources,
+       }, {
+               .name           = "axp288_charger",
+               .num_resources  = ARRAY_SIZE(axp288_charger_resources),
+               .resources      = axp288_charger_resources,
+       }, {
+               .name           = "axp288_fuel_gauge",
+               .num_resources  = ARRAY_SIZE(axp288_fuel_gauge_resources),
+               .resources      = axp288_fuel_gauge_resources,
+       }, {
+               .name           = "axp221-pek",
+               .num_resources  = ARRAY_SIZE(axp288_power_button_resources),
+               .resources      = axp288_power_button_resources,
+       }, {
+               .name           = "axp288_pmic_acpi",
        },
 };
 
 static const struct mfd_cell axp803_cells[] = {
        {
-               .name                   = "axp221-pek",
-               .num_resources          = ARRAY_SIZE(axp803_pek_resources),
-               .resources              = axp803_pek_resources,
+               .name           = "axp221-pek",
+               .num_resources  = ARRAY_SIZE(axp803_pek_resources),
+               .resources      = axp803_pek_resources,
+       }, {
+               .name           = "axp20x-gpio",
+               .of_compatible  = "x-powers,axp813-gpio",
+       }, {
+               .name           = "axp813-adc",
+               .of_compatible  = "x-powers,axp813-adc",
+       }, {
+               .name           = "axp20x-battery-power-supply",
+               .of_compatible  = "x-powers,axp813-battery-power-supply",
+       }, {
+               .name           = "axp20x-ac-power-supply",
+               .of_compatible  = "x-powers,axp813-ac-power-supply",
+               .num_resources  = ARRAY_SIZE(axp20x_ac_power_supply_resources),
+               .resources      = axp20x_ac_power_supply_resources,
        },
-       {       .name                   = "axp20x-regulator" },
+       {       .name           = "axp20x-regulator" },
 };
 
 static const struct mfd_cell axp806_self_working_cells[] = {
        {
-               .name                   = "axp221-pek",
-               .num_resources          = ARRAY_SIZE(axp806_pek_resources),
-               .resources              = axp806_pek_resources,
+               .name           = "axp221-pek",
+               .num_resources  = ARRAY_SIZE(axp806_pek_resources),
+               .resources      = axp806_pek_resources,
        },
-       {       .name                   = "axp20x-regulator" },
+       {       .name           = "axp20x-regulator" },
 };
 
 static const struct mfd_cell axp806_cells[] = {
        {
-               .id                     = 2,
-               .name                   = "axp20x-regulator",
+               .id             = 2,
+               .name           = "axp20x-regulator",
        },
 };
 
 static const struct mfd_cell axp809_cells[] = {
        {
-               .name                   = "axp221-pek",
-               .num_resources          = ARRAY_SIZE(axp809_pek_resources),
-               .resources              = axp809_pek_resources,
+               .name           = "axp221-pek",
+               .num_resources  = ARRAY_SIZE(axp809_pek_resources),
+               .resources      = axp809_pek_resources,
        }, {
-               .id                     = 1,
-               .name                   = "axp20x-regulator",
+               .id             = 1,
+               .name           = "axp20x-regulator",
        },
 };
 
 static const struct mfd_cell axp813_cells[] = {
        {
-               .name                   = "axp221-pek",
-               .num_resources          = ARRAY_SIZE(axp803_pek_resources),
-               .resources              = axp803_pek_resources,
+               .name           = "axp221-pek",
+               .num_resources  = ARRAY_SIZE(axp803_pek_resources),
+               .resources      = axp803_pek_resources,
        }, {
-               .name                   = "axp20x-regulator",
+               .name           = "axp20x-regulator",
        }, {
-               .name                   = "axp20x-gpio",
-               .of_compatible          = "x-powers,axp813-gpio",
+               .name           = "axp20x-gpio",
+               .of_compatible  = "x-powers,axp813-gpio",
        }, {
-               .name                   = "axp813-adc",
-               .of_compatible          = "x-powers,axp813-adc",
+               .name           = "axp813-adc",
+               .of_compatible  = "x-powers,axp813-adc",
        }, {
                .name           = "axp20x-battery-power-supply",
                .of_compatible  = "x-powers,axp813-battery-power-supply",
+       }, {
+               .name           = "axp20x-ac-power-supply",
+               .of_compatible  = "x-powers,axp813-ac-power-supply",
+               .num_resources  = ARRAY_SIZE(axp20x_ac_power_supply_resources),
+               .resources      = axp20x_ac_power_supply_resources,
        },
 };
 
index 503979c..fab3cdc 100644 (file)
@@ -59,6 +59,7 @@ static const struct regmap_access_table bd9571mwv_writable_table = {
 };
 
 static const struct regmap_range bd9571mwv_volatile_yes_ranges[] = {
+       regmap_reg_range(BD9571MWV_DVFS_MONIVDAC, BD9571MWV_DVFS_MONIVDAC),
        regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN),
        regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INT),
        regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTREQ),
index b99a194..2d0fee4 100644 (file)
@@ -499,6 +499,7 @@ static int ec_device_remove(struct platform_device *pdev)
 
        cros_ec_debugfs_remove(ec);
 
+       mfd_remove_devices(ec->dev);
        cdev_del(&ec->cdev);
        device_unregister(&ec->class_dev);
        return 0;
index 5970b8d..aec20e1 100644 (file)
@@ -2584,7 +2584,7 @@ static struct irq_chip prcmu_irq_chip = {
        .irq_unmask     = prcmu_irq_unmask,
 };
 
-static __init char *fw_project_name(u32 project)
+static char *fw_project_name(u32 project)
 {
        switch (project) {
        case PRCMU_FW_PROJECT_U8500:
@@ -2732,7 +2732,7 @@ void __init db8500_prcmu_early_init(u32 phy_base, u32 size)
        INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work);
 }
 
-static void __init init_prcm_registers(void)
+static void init_prcm_registers(void)
 {
        u32 val;
 
index ca829f8..2713de9 100644 (file)
@@ -82,11 +82,13 @@ static void exynos_lpass_enable(struct exynos_lpass *lpass)
                     LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S);
 
        regmap_write(lpass->top, SFR_LPASS_INTR_CPU_MASK,
-                    LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S);
+                    LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S |
+                    LPASS_INTR_UART);
 
        exynos_lpass_core_sw_reset(lpass, LPASS_I2S_SW_RESET);
        exynos_lpass_core_sw_reset(lpass, LPASS_DMA_SW_RESET);
        exynos_lpass_core_sw_reset(lpass, LPASS_MEM_SW_RESET);
+       exynos_lpass_core_sw_reset(lpass, LPASS_UART_SW_RESET);
 }
 
 static void exynos_lpass_disable(struct exynos_lpass *lpass)
index 440030c..2a77988 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/gpio.h>
 #include <linux/mfd/core.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/notifier.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
@@ -155,7 +156,7 @@ static int madera_wait_for_boot(struct madera *madera)
                usleep_range(MADERA_BOOT_POLL_INTERVAL_USEC / 2,
                             MADERA_BOOT_POLL_INTERVAL_USEC);
                regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_1, &val);
-       };
+       }
 
        if (!(val & MADERA_BOOT_DONE_STS1)) {
                dev_err(madera->dev, "Polling BOOT_DONE_STS timed out\n");
@@ -357,6 +358,8 @@ int madera_dev_init(struct madera *madera)
 
        dev_set_drvdata(madera->dev, madera);
        BLOCKING_INIT_NOTIFIER_HEAD(&madera->notifier);
+       mutex_init(&madera->dapm_ptr_lock);
+
        madera_set_micbias_info(madera);
 
        /*
index d821736..d8ddd1a 100644 (file)
@@ -280,7 +280,7 @@ static int max77620_config_fps(struct max77620_chip *chip,
 
        for (fps_id = 0; fps_id < MAX77620_FPS_COUNT; fps_id++) {
                sprintf(fps_name, "fps%d", fps_id);
-               if (!strcmp(fps_np->name, fps_name))
+               if (of_node_name_eq(fps_np, fps_name))
                        break;
        }
 
index f475e84..d0bf50e 100644 (file)
@@ -274,7 +274,9 @@ int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode,
 
        mc13xxx->adcflags |= MC13XXX_ADC_WORKING;
 
-       mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0);
+       ret = mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0);
+       if (ret)
+               goto out;
 
        adc0 = MC13XXX_ADC0_ADINC1 | MC13XXX_ADC0_ADINC2 |
               MC13XXX_ADC0_CHRGRAWDIV;
index 77b64bd..ab24e17 100644 (file)
@@ -329,8 +329,7 @@ static int mt6397_probe(struct platform_device *pdev)
 
        default:
                dev_err(&pdev->dev, "unsupported chip: %d\n", id);
-               ret = -ENODEV;
-               break;
+               return -ENODEV;
        }
 
        if (ret) {
index 52fafea..8d420c3 100644 (file)
@@ -638,6 +638,10 @@ static int qcom_rpm_probe(struct platform_device *pdev)
                return -EFAULT;
        }
 
+       writel(fw_version[0], RPM_CTRL_REG(rpm, 0));
+       writel(fw_version[1], RPM_CTRL_REG(rpm, 1));
+       writel(fw_version[2], RPM_CTRL_REG(rpm, 2));
+
        dev_info(&pdev->dev, "RPM firmware %u.%u.%u\n", fw_version[0],
                                                        fw_version[1],
                                                        fw_version[2]);
index 2a83696..26c7b63 100644 (file)
@@ -109,7 +109,7 @@ struct rave_sp_reply {
 /**
  * struct rave_sp_checksum - Variant specific checksum implementation details
  *
- * @length:    Caculated checksum length
+ * @length:    Calculated checksum length
  * @subroutine:        Utilized checksum algorithm implementation
  */
 struct rave_sp_checksum {
index 566caca..7569a4b 100644 (file)
@@ -1302,17 +1302,17 @@ static void stmpe_of_probe(struct stmpe_platform_data *pdata,
        pdata->autosleep = (pdata->autosleep_timeout) ? true : false;
 
        for_each_child_of_node(np, child) {
-               if (!strcmp(child->name, "stmpe_gpio")) {
+               if (of_node_name_eq(child, "stmpe_gpio")) {
                        pdata->blocks |= STMPE_BLOCK_GPIO;
-               } else if (!strcmp(child->name, "stmpe_keypad")) {
+               } else if (of_node_name_eq(child, "stmpe_keypad")) {
                        pdata->blocks |= STMPE_BLOCK_KEYPAD;
-               } else if (!strcmp(child->name, "stmpe_touchscreen")) {
+               } else if (of_node_name_eq(child, "stmpe_touchscreen")) {
                        pdata->blocks |= STMPE_BLOCK_TOUCHSCREEN;
-               } else if (!strcmp(child->name, "stmpe_adc")) {
+               } else if (of_node_name_eq(child, "stmpe_adc")) {
                        pdata->blocks |= STMPE_BLOCK_ADC;
-               } else if (!strcmp(child->name, "stmpe_pwm")) {
+               } else if (of_node_name_eq(child, "stmpe_pwm")) {
                        pdata->blocks |= STMPE_BLOCK_PWM;
-               } else if (!strcmp(child->name, "stmpe_rotator")) {
+               } else if (of_node_name_eq(child, "stmpe_rotator")) {
                        pdata->blocks |= STMPE_BLOCK_ROTATOR;
                }
        }
index c2d47d7..fd11129 100644 (file)
@@ -264,8 +264,9 @@ static      int ti_tscadc_probe(struct platform_device *pdev)
                cell->pdata_size = sizeof(tscadc);
        }
 
-       err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
-                       tscadc->used_cells, NULL, 0, NULL);
+       err = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
+                             tscadc->cells, tscadc->used_cells, NULL,
+                             0, NULL);
        if (err < 0)
                goto err_disable_clk;
 
index 910f569..8bcdecf 100644 (file)
@@ -235,9 +235,9 @@ static int tps65218_probe(struct i2c_client *client,
 
        mutex_init(&tps->tps_lock);
 
-       ret = regmap_add_irq_chip(tps->regmap, tps->irq,
-                       IRQF_ONESHOT, 0, &tps65218_irq_chip,
-                       &tps->irq_data);
+       ret = devm_regmap_add_irq_chip(&client->dev, tps->regmap, tps->irq,
+                                      IRQF_ONESHOT, 0, &tps65218_irq_chip,
+                                      &tps->irq_data);
        if (ret < 0)
                return ret;
 
@@ -253,26 +253,9 @@ static int tps65218_probe(struct i2c_client *client,
                              ARRAY_SIZE(tps65218_cells), NULL, 0,
                              regmap_irq_get_domain(tps->irq_data));
 
-       if (ret < 0)
-               goto err_irq;
-
-       return 0;
-
-err_irq:
-       regmap_del_irq_chip(tps->irq, tps->irq_data);
-
        return ret;
 }
 
-static int tps65218_remove(struct i2c_client *client)
-{
-       struct tps65218 *tps = i2c_get_clientdata(client);
-
-       regmap_del_irq_chip(tps->irq, tps->irq_data);
-
-       return 0;
-}
-
 static const struct i2c_device_id tps65218_id_table[] = {
        { "tps65218", TPS65218 },
        { },
@@ -285,7 +268,6 @@ static struct i2c_driver tps65218_driver = {
                .of_match_table = of_tps65218_match_table,
        },
        .probe          = tps65218_probe,
-       .remove         = tps65218_remove,
        .id_table       = tps65218_id_table,
 };
 
index b893797..9c7925c 100644 (file)
@@ -592,6 +592,29 @@ static int tps6586x_i2c_remove(struct i2c_client *client)
        return 0;
 }
 
+static int __maybe_unused tps6586x_i2c_suspend(struct device *dev)
+{
+       struct tps6586x *tps6586x = dev_get_drvdata(dev);
+
+       if (tps6586x->client->irq)
+               disable_irq(tps6586x->client->irq);
+
+       return 0;
+}
+
+static int __maybe_unused tps6586x_i2c_resume(struct device *dev)
+{
+       struct tps6586x *tps6586x = dev_get_drvdata(dev);
+
+       if (tps6586x->client->irq)
+               enable_irq(tps6586x->client->irq);
+
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(tps6586x_pm_ops, tps6586x_i2c_suspend,
+                        tps6586x_i2c_resume);
+
 static const struct i2c_device_id tps6586x_id_table[] = {
        { "tps6586x", 0 },
        { },
@@ -602,6 +625,7 @@ static struct i2c_driver tps6586x_driver = {
        .driver = {
                .name   = "tps6586x",
                .of_match_table = of_match_ptr(tps6586x_of_match),
+               .pm     = &tps6586x_pm_ops,
        },
        .probe          = tps6586x_i2c_probe,
        .remove         = tps6586x_i2c_remove,
index 4be3d23..299016b 100644 (file)
@@ -979,7 +979,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
  * letting it generate the right frequencies for USB, MADC, and
  * other purposes.
  */
-static inline int __init protect_pm_master(void)
+static inline int protect_pm_master(void)
 {
        int e = 0;
 
@@ -988,7 +988,7 @@ static inline int __init protect_pm_master(void)
        return e;
 }
 
-static inline int __init unprotect_pm_master(void)
+static inline int unprotect_pm_master(void)
 {
        int e = 0;
 
index 1ee68bd..16c6e2a 100644 (file)
@@ -1618,6 +1618,7 @@ static const struct reg_default wm5110_reg_default[] = {
        { 0x00000ECD, 0x0000 },    /* R3789  - HPLPF4_2 */
        { 0x00000EE0, 0x0000 },    /* R3808  - ASRC_ENABLE */
        { 0x00000EE2, 0x0000 },    /* R3810  - ASRC_RATE1 */
+       { 0x00000EE3, 0x4000 },    /* R3811  - ASRC_RATE2 */
        { 0x00000EF0, 0x0000 },    /* R3824  - ISRC 1 CTRL 1 */
        { 0x00000EF1, 0x0000 },    /* R3825  - ISRC 1 CTRL 2 */
        { 0x00000EF2, 0x0000 },    /* R3826  - ISRC 1 CTRL 3 */
@@ -2869,6 +2870,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_ASRC_ENABLE:
        case ARIZONA_ASRC_STATUS:
        case ARIZONA_ASRC_RATE1:
+       case ARIZONA_ASRC_RATE2:
        case ARIZONA_ISRC_1_CTRL_1:
        case ARIZONA_ISRC_1_CTRL_2:
        case ARIZONA_ISRC_1_CTRL_3:
index efe2fb7..25265fd 100644 (file)
@@ -218,8 +218,8 @@ void *__genwqe_alloc_consistent(struct genwqe_dev *cd, size_t size,
        if (get_order(size) >= MAX_ORDER)
                return NULL;
 
-       return dma_zalloc_coherent(&cd->pci_dev->dev, size, dma_handle,
-                                  GFP_KERNEL);
+       return dma_alloc_coherent(&cd->pci_dev->dev, size, dma_handle,
+                                 GFP_KERNEL);
 }
 
 void __genwqe_free_consistent(struct genwqe_dev *cd, size_t size,
index b8aaa68..2ed23c9 100644 (file)
@@ -820,21 +820,24 @@ static int ibmvmc_send_msg(struct crq_server_adapter *adapter,
  *
  * Return:
  *     0 - Success
+ *     Non-zero - Failure
  */
 static int ibmvmc_open(struct inode *inode, struct file *file)
 {
        struct ibmvmc_file_session *session;
-       int rc = 0;
 
        pr_debug("%s: inode = 0x%lx, file = 0x%lx, state = 0x%x\n", __func__,
                 (unsigned long)inode, (unsigned long)file,
                 ibmvmc.state);
 
        session = kzalloc(sizeof(*session), GFP_KERNEL);
+       if (!session)
+               return -ENOMEM;
+
        session->file = file;
        file->private_data = session;
 
-       return rc;
+       return 0;
 }
 
 /**
index 1fc8ea0..ca4c9cc 100644 (file)
@@ -401,8 +401,11 @@ static void mei_io_list_flush_cl(struct list_head *head,
        struct mei_cl_cb *cb, *next;
 
        list_for_each_entry_safe(cb, next, head, list) {
-               if (cl == cb->cl)
+               if (cl == cb->cl) {
                        list_del_init(&cb->list);
+                       if (cb->fop_type == MEI_FOP_READ)
+                               mei_io_cb_free(cb);
+               }
        }
 }
 
index 78c26ce..8f76165 100644 (file)
@@ -1187,9 +1187,15 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
                dma_setup_res = (struct hbm_dma_setup_response *)mei_msg;
 
                if (dma_setup_res->status) {
-                       dev_info(dev->dev, "hbm: dma setup response: failure = %d %s\n",
-                                dma_setup_res->status,
-                                mei_hbm_status_str(dma_setup_res->status));
+                       u8 status = dma_setup_res->status;
+
+                       if (status == MEI_HBMS_NOT_ALLOWED) {
+                               dev_dbg(dev->dev, "hbm: dma setup not allowed\n");
+                       } else {
+                               dev_info(dev->dev, "hbm: dma setup response: failure = %d %s\n",
+                                        status,
+                                        mei_hbm_status_str(status));
+                       }
                        dev->hbm_f_dr_supported = 0;
                        mei_dmam_ring_free(dev);
                }
index e4b10b2..bb1ee98 100644 (file)
 #define MEI_DEV_ID_BXT_M      0x1A9A  /* Broxton M */
 #define MEI_DEV_ID_APL_I      0x5A9A  /* Apollo Lake I */
 
+#define MEI_DEV_ID_DNV_IE     0x19E5  /* Denverton IE */
+
 #define MEI_DEV_ID_GLK        0x319A  /* Gemini Lake */
 
 #define MEI_DEV_ID_KBP        0xA2BA  /* Kaby Point */
 #define MEI_DEV_ID_CNP_H      0xA360  /* Cannon Point H */
 #define MEI_DEV_ID_CNP_H_4    0xA364  /* Cannon Point H 4 (iTouch) */
 
+#define MEI_DEV_ID_ICP_LP     0x34E0  /* Ice Lake Point LP */
+
 /*
  * MEI HW Section
  */
index 73ace2d..3ab946a 100644 (file)
@@ -88,11 +88,13 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
        {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, MEI_ME_PCH8_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, MEI_ME_PCH8_SPS_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, MEI_ME_PCH8_SPS_CFG)},
-       {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH8_CFG)},
+       {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH12_CFG)},
 
        {MEI_PCI_DEVICE(MEI_DEV_ID_BXT_M, MEI_ME_PCH8_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, MEI_ME_PCH8_CFG)},
 
+       {MEI_PCI_DEVICE(MEI_DEV_ID_DNV_IE, MEI_ME_PCH8_CFG)},
+
        {MEI_PCI_DEVICE(MEI_DEV_ID_GLK, MEI_ME_PCH8_CFG)},
 
        {MEI_PCI_DEVICE(MEI_DEV_ID_KBP, MEI_ME_PCH8_CFG)},
@@ -103,6 +105,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
        {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H, MEI_ME_PCH12_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H_4, MEI_ME_PCH8_CFG)},
 
+       {MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP, MEI_ME_PCH12_CFG)},
+
        /* required last entry */
        {0, }
 };
index 6b212c8..744757f 100644 (file)
@@ -47,7 +47,8 @@
  * @dc: Virtio device control
  * @vpdev: VOP device which is the parent for this virtio device
  * @vr: Buffer for accessing the VRING
- * @used: Buffer for used
+ * @used_virt: Virtual address of used ring
+ * @used: DMA address of used ring
  * @used_size: Size of the used buffer
  * @reset_done: Track whether VOP reset is complete
  * @virtio_cookie: Cookie returned upon requesting a interrupt
@@ -61,6 +62,7 @@ struct _vop_vdev {
        struct mic_device_ctrl __iomem *dc;
        struct vop_device *vpdev;
        void __iomem *vr[VOP_MAX_VRINGS];
+       void *used_virt[VOP_MAX_VRINGS];
        dma_addr_t used[VOP_MAX_VRINGS];
        int used_size[VOP_MAX_VRINGS];
        struct completion reset_done;
@@ -260,12 +262,12 @@ static bool vop_notify(struct virtqueue *vq)
 static void vop_del_vq(struct virtqueue *vq, int n)
 {
        struct _vop_vdev *vdev = to_vopvdev(vq->vdev);
-       struct vring *vr = (struct vring *)(vq + 1);
        struct vop_device *vpdev = vdev->vpdev;
 
        dma_unmap_single(&vpdev->dev, vdev->used[n],
                         vdev->used_size[n], DMA_BIDIRECTIONAL);
-       free_pages((unsigned long)vr->used, get_order(vdev->used_size[n]));
+       free_pages((unsigned long)vdev->used_virt[n],
+                  get_order(vdev->used_size[n]));
        vring_del_virtqueue(vq);
        vpdev->hw_ops->iounmap(vpdev, vdev->vr[n]);
        vdev->vr[n] = NULL;
@@ -283,6 +285,26 @@ static void vop_del_vqs(struct virtio_device *dev)
                vop_del_vq(vq, idx++);
 }
 
+static struct virtqueue *vop_new_virtqueue(unsigned int index,
+                                     unsigned int num,
+                                     struct virtio_device *vdev,
+                                     bool context,
+                                     void *pages,
+                                     bool (*notify)(struct virtqueue *vq),
+                                     void (*callback)(struct virtqueue *vq),
+                                     const char *name,
+                                     void *used)
+{
+       bool weak_barriers = false;
+       struct vring vring;
+
+       vring_init(&vring, num, pages, MIC_VIRTIO_RING_ALIGN);
+       vring.used = used;
+
+       return __vring_new_virtqueue(index, vring, vdev, weak_barriers, context,
+                                    notify, callback, name);
+}
+
 /*
  * This routine will assign vring's allocated in host/io memory. Code in
  * virtio_ring.c however continues to access this io memory as if it were local
@@ -302,7 +324,6 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev,
        struct _mic_vring_info __iomem *info;
        void *used;
        int vr_size, _vr_size, err, magic;
-       struct vring *vr;
        u8 type = ioread8(&vdev->desc->type);
 
        if (index >= ioread8(&vdev->desc->num_vq))
@@ -322,17 +343,7 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev,
                return ERR_PTR(-ENOMEM);
        vdev->vr[index] = va;
        memset_io(va, 0x0, _vr_size);
-       vq = vring_new_virtqueue(
-                               index,
-                               le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN,
-                               dev,
-                               false,
-                               ctx,
-                               (void __force *)va, vop_notify, callback, name);
-       if (!vq) {
-               err = -ENOMEM;
-               goto unmap;
-       }
+
        info = va + _vr_size;
        magic = ioread32(&info->magic);
 
@@ -341,18 +352,27 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev,
                goto unmap;
        }
 
-       /* Allocate and reassign used ring now */
        vdev->used_size[index] = PAGE_ALIGN(sizeof(__u16) * 3 +
                                             sizeof(struct vring_used_elem) *
                                             le16_to_cpu(config.num));
        used = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
                                        get_order(vdev->used_size[index]));
+       vdev->used_virt[index] = used;
        if (!used) {
                err = -ENOMEM;
                dev_err(_vop_dev(vdev), "%s %d err %d\n",
                        __func__, __LINE__, err);
-               goto del_vq;
+               goto unmap;
        }
+
+       vq = vop_new_virtqueue(index, le16_to_cpu(config.num), dev, ctx,
+                              (void __force *)va, vop_notify, callback,
+                              name, used);
+       if (!vq) {
+               err = -ENOMEM;
+               goto free_used;
+       }
+
        vdev->used[index] = dma_map_single(&vpdev->dev, used,
                                            vdev->used_size[index],
                                            DMA_BIDIRECTIONAL);
@@ -360,26 +380,17 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev,
                err = -ENOMEM;
                dev_err(_vop_dev(vdev), "%s %d err %d\n",
                        __func__, __LINE__, err);
-               goto free_used;
+               goto del_vq;
        }
        writeq(vdev->used[index], &vqconfig->used_address);
-       /*
-        * To reassign the used ring here we are directly accessing
-        * struct vring_virtqueue which is a private data structure
-        * in virtio_ring.c. At the minimum, a BUILD_BUG_ON() in
-        * vring_new_virtqueue() would ensure that
-        *  (&vq->vring == (struct vring *) (&vq->vq + 1));
-        */
-       vr = (struct vring *)(vq + 1);
-       vr->used = used;
 
        vq->priv = vdev;
        return vq;
+del_vq:
+       vring_del_virtqueue(vq);
 free_used:
        free_pages((unsigned long)used,
                   get_order(vdev->used_size[index]));
-del_vq:
-       vring_del_virtqueue(vq);
 unmap:
        vpdev->hw_ops->iounmap(vpdev, vdev->vr[index]);
        return ERR_PTR(err);
@@ -394,16 +405,21 @@ static int vop_find_vqs(struct virtio_device *dev, unsigned nvqs,
        struct _vop_vdev *vdev = to_vopvdev(dev);
        struct vop_device *vpdev = vdev->vpdev;
        struct mic_device_ctrl __iomem *dc = vdev->dc;
-       int i, err, retry;
+       int i, err, retry, queue_idx = 0;
 
        /* We must have this many virtqueues. */
        if (nvqs > ioread8(&vdev->desc->num_vq))
                return -ENOENT;
 
        for (i = 0; i < nvqs; ++i) {
+               if (!names[i]) {
+                       vqs[i] = NULL;
+                       continue;
+               }
+
                dev_dbg(_vop_dev(vdev), "%s: %d: %s\n",
                        __func__, i, names[i]);
-               vqs[i] = vop_find_vq(dev, i, callbacks[i], names[i],
+               vqs[i] = vop_find_vq(dev, queue_idx++, callbacks[i], names[i],
                                     ctx ? ctx[i] : false);
                if (IS_ERR(vqs[i])) {
                        err = PTR_ERR(vqs[i]);
@@ -576,6 +592,8 @@ static int _vop_remove_device(struct mic_device_desc __iomem *d,
        int ret = -1;
 
        if (ioread8(&dc->config_change) == MIC_VIRTIO_PARAM_DEV_REMOVE) {
+               struct device *dev = get_device(&vdev->vdev.dev);
+
                dev_dbg(&vpdev->dev,
                        "%s %d config_change %d type %d vdev %p\n",
                        __func__, __LINE__,
@@ -587,7 +605,7 @@ static int _vop_remove_device(struct mic_device_desc __iomem *d,
                iowrite8(-1, &dc->h2c_vdev_db);
                if (status & VIRTIO_CONFIG_S_DRIVER_OK)
                        wait_for_completion(&vdev->reset_done);
-               put_device(&vdev->vdev.dev);
+               put_device(dev);
                iowrite8(1, &dc->guest_ack);
                dev_dbg(&vpdev->dev, "%s %d guest_ack %d\n",
                        __func__, __LINE__, ioread8(&dc->guest_ack));
index 595ac06..95ff7c5 100644 (file)
@@ -70,8 +70,12 @@ pvpanic_walk_resources(struct acpi_resource *res, void *context)
        struct resource r;
 
        if (acpi_dev_resource_io(res, &r)) {
+#ifdef CONFIG_HAS_IOPORT_MAP
                base = ioport_map(r.start, resource_size(&r));
                return AE_OK;
+#else
+               return AE_ERROR;
+#endif
        } else if (acpi_dev_resource_memory(res, &r)) {
                base = ioremap(r.start, resource_size(&r));
                return AE_OK;
index aef1185..14f3fdb 100644 (file)
@@ -2112,7 +2112,7 @@ static void mmc_blk_mq_req_done(struct mmc_request *mrq)
                if (waiting)
                        wake_up(&mq->wait);
                else
-                       kblockd_schedule_work(&mq->complete_work);
+                       queue_work(mq->card->complete_wq, &mq->complete_work);
 
                return;
        }
@@ -2924,6 +2924,13 @@ static int mmc_blk_probe(struct mmc_card *card)
 
        mmc_fixup_device(card, mmc_blk_fixups);
 
+       card->complete_wq = alloc_workqueue("mmc_complete",
+                                       WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
+       if (unlikely(!card->complete_wq)) {
+               pr_err("Failed to create mmc completion workqueue");
+               return -ENOMEM;
+       }
+
        md = mmc_blk_alloc(card);
        if (IS_ERR(md))
                return PTR_ERR(md);
@@ -2987,6 +2994,7 @@ static void mmc_blk_remove(struct mmc_card *card)
        pm_runtime_put_noidle(&card->dev);
        mmc_blk_remove_req(md);
        dev_set_drvdata(&card->dev, NULL);
+       destroy_workqueue(card->complete_wq);
 }
 
 static int _mmc_blk_suspend(struct mmc_card *card)
index f57f5de..cf58cca 100644 (file)
@@ -234,7 +234,7 @@ int mmc_of_parse(struct mmc_host *host)
                if (device_property_read_bool(dev, "broken-cd"))
                        host->caps |= MMC_CAP_NEEDS_POLL;
 
-               ret = mmc_gpiod_request_cd(host, "cd", 0, true,
+               ret = mmc_gpiod_request_cd(host, "cd", 0, false,
                                           cd_debounce_delay_ms * 1000,
                                           &cd_gpio_invert);
                if (!ret)
index e26b814..a44ec8b 100644 (file)
@@ -116,7 +116,7 @@ config MMC_RICOH_MMC
 
 config MMC_SDHCI_ACPI
        tristate "SDHCI support for ACPI enumerated SDHCI controllers"
-       depends on MMC_SDHCI && ACPI
+       depends on MMC_SDHCI && ACPI && PCI
        select IOSF_MBI if X86
        help
          This selects support for ACPI enumerated SDHCI controllers,
@@ -978,7 +978,7 @@ config MMC_SDHCI_OMAP
        tristate "TI SDHCI Controller Support"
        depends on MMC_SDHCI_PLTFM && OF
        select THERMAL
-       select TI_SOC_THERMAL
+       imply TI_SOC_THERMAL
        help
          This selects the Secure Digital Host Controller Interface (SDHCI)
          support present in TI's DRA7 SOCs. The controller supports
index 5029352..c9e7aa5 100644 (file)
@@ -1431,6 +1431,8 @@ static int bcm2835_probe(struct platform_device *pdev)
 
 err:
        dev_dbg(dev, "%s -> err %d\n", __func__, ret);
+       if (host->dma_chan_rxtx)
+               dma_release_channel(host->dma_chan_rxtx);
        mmc_free_host(mmc);
 
        return ret;
index ed8f225..aa38b1a 100644 (file)
@@ -1,11 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2018 Mellanox Technologies.
- *
- * 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.
  */
 
 #include <linux/bitfield.h>
index c2690c1..2eba507 100644 (file)
@@ -179,6 +179,8 @@ struct meson_host {
        struct sd_emmc_desc *descs;
        dma_addr_t descs_dma_addr;
 
+       int irq;
+
        bool vqmmc_enabled;
 };
 
@@ -738,6 +740,11 @@ static int meson_mmc_clk_phase_tuning(struct mmc_host *mmc, u32 opcode,
 static int meson_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
 {
        struct meson_host *host = mmc_priv(mmc);
+       int adj = 0;
+
+       /* enable signal resampling w/o delay */
+       adj = ADJUST_ADJ_EN;
+       writel(adj, host->regs + host->data->adjust);
 
        return meson_mmc_clk_phase_tuning(mmc, opcode, host->rx_clk);
 }
@@ -768,6 +775,9 @@ static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                if (!IS_ERR(mmc->supply.vmmc))
                        mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
 
+               /* disable signal resampling */
+               writel(0, host->regs + host->data->adjust);
+
                /* Reset rx phase */
                clk_set_phase(host->rx_clk, 0);
 
@@ -1166,7 +1176,7 @@ static int meson_mmc_get_cd(struct mmc_host *mmc)
 
 static void meson_mmc_cfg_init(struct meson_host *host)
 {
-       u32 cfg = 0, adj = 0;
+       u32 cfg = 0;
 
        cfg |= FIELD_PREP(CFG_RESP_TIMEOUT_MASK,
                          ilog2(SD_EMMC_CFG_RESP_TIMEOUT));
@@ -1177,10 +1187,6 @@ static void meson_mmc_cfg_init(struct meson_host *host)
        cfg |= CFG_ERR_ABORT;
 
        writel(cfg, host->regs + SD_EMMC_CFG);
-
-       /* enable signal resampling w/o delay */
-       adj = ADJUST_ADJ_EN;
-       writel(adj, host->regs + host->data->adjust);
 }
 
 static int meson_mmc_card_busy(struct mmc_host *mmc)
@@ -1231,7 +1237,7 @@ static int meson_mmc_probe(struct platform_device *pdev)
        struct resource *res;
        struct meson_host *host;
        struct mmc_host *mmc;
-       int ret, irq;
+       int ret;
 
        mmc = mmc_alloc_host(sizeof(struct meson_host), &pdev->dev);
        if (!mmc)
@@ -1276,8 +1282,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
                goto free_host;
        }
 
-       irq = platform_get_irq(pdev, 0);
-       if (irq <= 0) {
+       host->irq = platform_get_irq(pdev, 0);
+       if (host->irq <= 0) {
                dev_err(&pdev->dev, "failed to get interrupt resource.\n");
                ret = -EINVAL;
                goto free_host;
@@ -1331,9 +1337,9 @@ static int meson_mmc_probe(struct platform_device *pdev)
        writel(IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN,
               host->regs + SD_EMMC_IRQ_EN);
 
-       ret = devm_request_threaded_irq(&pdev->dev, irq, meson_mmc_irq,
-                                       meson_mmc_irq_thread, IRQF_SHARED,
-                                       NULL, host);
+       ret = request_threaded_irq(host->irq, meson_mmc_irq,
+                                  meson_mmc_irq_thread, IRQF_SHARED,
+                                  dev_name(&pdev->dev), host);
        if (ret)
                goto err_init_clk;
 
@@ -1351,7 +1357,7 @@ static int meson_mmc_probe(struct platform_device *pdev)
        if (host->bounce_buf == NULL) {
                dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n");
                ret = -ENOMEM;
-               goto err_init_clk;
+               goto err_free_irq;
        }
 
        host->descs = dma_alloc_coherent(host->dev, SD_EMMC_DESC_BUF_LEN,
@@ -1370,6 +1376,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
 err_bounce_buf:
        dma_free_coherent(host->dev, host->bounce_buf_size,
                          host->bounce_buf, host->bounce_dma_addr);
+err_free_irq:
+       free_irq(host->irq, host);
 err_init_clk:
        clk_disable_unprepare(host->mmc_clk);
 err_core_clk:
@@ -1387,6 +1395,7 @@ static int meson_mmc_remove(struct platform_device *pdev)
 
        /* disable interrupts */
        writel(0, host->regs + SD_EMMC_IRQ_EN);
+       free_irq(host->irq, host);
 
        dma_free_coherent(host->dev, SD_EMMC_DESC_BUF_LEN,
                          host->descs, host->descs_dma_addr);
index 8afeaf8..833ef05 100644 (file)
@@ -846,7 +846,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
 
        if (timing == MMC_TIMING_MMC_HS400 &&
            host->dev_comp->hs400_tune)
-               sdr_set_field(host->base + PAD_CMD_TUNE,
+               sdr_set_field(host->base + tune_reg,
                              MSDC_PAD_TUNE_CMDRRDLY,
                              host->hs400_cmd_int_delay);
        dev_dbg(host->dev, "sclk: %d, timing: %d\n", host->mmc->actual_clock,
index 0db9905..9d12c06 100644 (file)
@@ -296,7 +296,10 @@ static int sdhci_iproc_probe(struct platform_device *pdev)
 
        iproc_host->data = iproc_data;
 
-       mmc_of_parse(host->mmc);
+       ret = mmc_of_parse(host->mmc);
+       if (ret)
+               goto err;
+
        sdhci_get_property(pdev);
 
        host->mmc->caps |= iproc_host->data->mmc_caps;
index a22e11a..eba9bcc 100644 (file)
@@ -3763,8 +3763,9 @@ int sdhci_setup_host(struct sdhci_host *host)
                 * Use zalloc to zero the reserved high 32-bits of 128-bit
                 * descriptors so that they never need to be written.
                 */
-               buf = dma_zalloc_coherent(mmc_dev(mmc), host->align_buffer_sz +
-                                        host->adma_table_sz, &dma, GFP_KERNEL);
+               buf = dma_alloc_coherent(mmc_dev(mmc),
+                                        host->align_buffer_sz + host->adma_table_sz,
+                                        &dma, GFP_KERNEL);
                if (!buf) {
                        pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n",
                                mmc_hostname(mmc));
index 279e326..70fadc9 100644 (file)
@@ -1399,13 +1399,37 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
        mmc->caps              |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
                                  MMC_CAP_ERASE | MMC_CAP_SDIO_IRQ;
 
-       if (host->cfg->clk_delays || host->use_new_timings)
+       /*
+        * Some H5 devices do not have signal traces precise enough to
+        * use HS DDR mode for their eMMC chips.
+        *
+        * We still enable HS DDR modes for all the other controller
+        * variants that support them.
+        */
+       if ((host->cfg->clk_delays || host->use_new_timings) &&
+           !of_device_is_compatible(pdev->dev.of_node,
+                                    "allwinner,sun50i-h5-emmc"))
                mmc->caps      |= MMC_CAP_1_8V_DDR | MMC_CAP_3_3V_DDR;
 
        ret = mmc_of_parse(mmc);
        if (ret)
                goto error_free_dma;
 
+       /*
+        * If we don't support delay chains in the SoC, we can't use any
+        * of the higher speed modes. Mask them out in case the device
+        * tree specifies the properties for them, which gets added to
+        * the caps by mmc_of_parse() above.
+        */
+       if (!(host->cfg->clk_delays || host->use_new_timings)) {
+               mmc->caps &= ~(MMC_CAP_3_3V_DDR | MMC_CAP_1_8V_DDR |
+                              MMC_CAP_1_2V_DDR | MMC_CAP_UHS);
+               mmc->caps2 &= ~MMC_CAP2_HS200;
+       }
+
+       /* TODO: This driver doesn't support HS400 mode yet */
+       mmc->caps2 &= ~MMC_CAP2_HS400;
+
        ret = sunxi_mmc_init_host(host);
        if (ret)
                goto error_free_dma;
index 21e3cdc..999b705 100644 (file)
@@ -522,7 +522,7 @@ static int mtd_nvmem_add(struct mtd_info *mtd)
        mtd->nvmem = nvmem_register(&config);
        if (IS_ERR(mtd->nvmem)) {
                /* Just ignore if there is no NVMEM support in the kernel */
-               if (PTR_ERR(mtd->nvmem) == -ENOSYS) {
+               if (PTR_ERR(mtd->nvmem) == -EOPNOTSUPP) {
                        mtd->nvmem = NULL;
                } else {
                        dev_err(&mtd->dev, "Failed to register NVMEM device\n");
index 9887bda..b31c868 100644 (file)
@@ -7,7 +7,7 @@
 extern struct mutex mtd_table_mutex;
 
 struct mtd_info *__mtd_next_device(int i);
-int add_mtd_device(struct mtd_info *mtd);
+int __must_check add_mtd_device(struct mtd_info *mtd);
 int del_mtd_device(struct mtd_info *mtd);
 int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
 int del_mtd_partitions(struct mtd_info *);
index b6af41b..37f174c 100644 (file)
@@ -480,6 +480,10 @@ static struct mtd_part *allocate_partition(struct mtd_info *parent,
                /* let's register it anyway to preserve ordering */
                slave->offset = 0;
                slave->mtd.size = 0;
+
+               /* Initialize ->erasesize to make add_mtd_device() happy. */
+               slave->mtd.erasesize = parent->erasesize;
+
                printk(KERN_ERR"mtd: partition \"%s\" is out of reach -- disabled\n",
                        part->name);
                goto out_register;
@@ -618,10 +622,21 @@ int mtd_add_partition(struct mtd_info *parent, const char *name,
        list_add(&new->list, &mtd_partitions);
        mutex_unlock(&mtd_partitions_mutex);
 
-       add_mtd_device(&new->mtd);
+       ret = add_mtd_device(&new->mtd);
+       if (ret)
+               goto err_remove_part;
 
        mtd_add_partition_attrs(new);
 
+       return 0;
+
+err_remove_part:
+       mutex_lock(&mtd_partitions_mutex);
+       list_del(&new->list);
+       mutex_unlock(&mtd_partitions_mutex);
+
+       free_partition(new);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_add_partition);
@@ -712,22 +727,31 @@ int add_mtd_partitions(struct mtd_info *master,
 {
        struct mtd_part *slave;
        uint64_t cur_offset = 0;
-       int i;
+       int i, ret;
 
        printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
 
        for (i = 0; i < nbparts; i++) {
                slave = allocate_partition(master, parts + i, i, cur_offset);
                if (IS_ERR(slave)) {
-                       del_mtd_partitions(master);
-                       return PTR_ERR(slave);
+                       ret = PTR_ERR(slave);
+                       goto err_del_partitions;
                }
 
                mutex_lock(&mtd_partitions_mutex);
                list_add(&slave->list, &mtd_partitions);
                mutex_unlock(&mtd_partitions_mutex);
 
-               add_mtd_device(&slave->mtd);
+               ret = add_mtd_device(&slave->mtd);
+               if (ret) {
+                       mutex_lock(&mtd_partitions_mutex);
+                       list_del(&slave->list);
+                       mutex_unlock(&mtd_partitions_mutex);
+
+                       free_partition(slave);
+                       goto err_del_partitions;
+               }
+
                mtd_add_partition_attrs(slave);
                /* Look for subpartitions */
                parse_mtd_partitions(&slave->mtd, parts[i].types, NULL);
@@ -736,6 +760,11 @@ int add_mtd_partitions(struct mtd_info *master,
        }
 
        return 0;
+
+err_del_partitions:
+       del_mtd_partitions(master);
+
+       return ret;
 }
 
 static DEFINE_SPINLOCK(part_parser_lock);
index eebac35..6e8edc9 100644 (file)
@@ -1322,7 +1322,7 @@ int denali_init(struct denali_nand_info *denali)
        }
 
        /* clk rate info is needed for setup_data_interface */
-       if (denali->clk_rate && denali->clk_x_rate)
+       if (!denali->clk_rate || !denali->clk_x_rate)
                chip->options |= NAND_KEEP_TIMINGS;
 
        chip->legacy.dummy_controller.ops = &denali_controller_ops;
index 325b441..c9149a3 100644 (file)
@@ -593,23 +593,6 @@ static void fsmc_write_buf_dma(struct fsmc_nand_data *host, const u8 *buf,
        dma_xfer(host, (void *)buf, len, DMA_TO_DEVICE);
 }
 
-/* fsmc_select_chip - assert or deassert nCE */
-static void fsmc_ce_ctrl(struct fsmc_nand_data *host, bool assert)
-{
-       u32 pc = readl(host->regs_va + FSMC_PC);
-
-       if (!assert)
-               writel_relaxed(pc & ~FSMC_ENABLE, host->regs_va + FSMC_PC);
-       else
-               writel_relaxed(pc | FSMC_ENABLE, host->regs_va + FSMC_PC);
-
-       /*
-        * nCE line changes must be applied before returning from this
-        * function.
-        */
-       mb();
-}
-
 /*
  * fsmc_exec_op - hook called by the core to execute NAND operations
  *
@@ -627,8 +610,6 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
 
        pr_debug("Executing operation [%d instructions]:\n", op->ninstrs);
 
-       fsmc_ce_ctrl(host, true);
-
        for (op_id = 0; op_id < op->ninstrs; op_id++) {
                instr = &op->instrs[op_id];
 
@@ -686,8 +667,6 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
                }
        }
 
-       fsmc_ce_ctrl(host, false);
-
        return ret;
 }
 
index bd4cfac..a4768df 100644 (file)
@@ -155,9 +155,10 @@ int gpmi_init(struct gpmi_nand_data *this)
 
        /*
         * Reset BCH here, too. We got failures otherwise :(
-        * See later BCH reset for explanation of MX23 handling
+        * See later BCH reset for explanation of MX23 and MX28 handling
         */
-       ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
+       ret = gpmi_reset_block(r->bch_regs,
+                              GPMI_IS_MX23(this) || GPMI_IS_MX28(this));
        if (ret)
                goto err_out;
 
@@ -263,12 +264,10 @@ int bch_set_geometry(struct gpmi_nand_data *this)
        /*
        * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this
        * chip, otherwise it will lock up. So we skip resetting BCH on the MX23.
-       * On the other hand, the MX28 needs the reset, because one case has been
-       * seen where the BCH produced ECC errors constantly after 10000
-       * consecutive reboots. The latter case has not been seen on the MX23
-       * yet, still we don't know if it could happen there as well.
+       * and MX28.
        */
-       ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
+       ret = gpmi_reset_block(r->bch_regs,
+                              GPMI_IS_MX23(this) || GPMI_IS_MX28(this));
        if (ret)
                goto err_out;
 
index f92ae5a..9526d5b 100644 (file)
@@ -260,7 +260,7 @@ static int jz_nand_correct_ecc_rs(struct nand_chip *chip, uint8_t *dat,
 }
 
 static int jz_nand_ioremap_resource(struct platform_device *pdev,
-       const char *name, struct resource **res, void *__iomem *base)
+       const char *name, struct resource **res, void __iomem **base)
 {
        int ret;
 
index cca4b24..839494a 100644 (file)
@@ -410,6 +410,7 @@ static int nand_check_wp(struct nand_chip *chip)
 
 /**
  * nand_fill_oob - [INTERN] Transfer client buffer to oob
+ * @chip: NAND chip object
  * @oob: oob data buffer
  * @len: oob data write length
  * @ops: oob ops structure
index 1b722fe..19a2b56 100644 (file)
@@ -158,7 +158,7 @@ static u32 add_marker_len(struct nand_bbt_descr *td)
 
 /**
  * read_bbt - [GENERIC] Read the bad block table starting from page
- * @chip: NAND chip object
+ * @this: NAND chip object
  * @buf: temporary buffer
  * @page: the starting page
  * @num: the number of bbt descriptors to read
index 46c62a3..920e737 100644 (file)
@@ -2833,6 +2833,16 @@ static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc,
        if (ret)
                return ret;
 
+       if (nandc->props->is_bam) {
+               free_bam_transaction(nandc);
+               nandc->bam_txn = alloc_bam_transaction(nandc);
+               if (!nandc->bam_txn) {
+                       dev_err(nandc->dev,
+                               "failed to allocate bam transaction\n");
+                       return -ENOMEM;
+               }
+       }
+
        ret = mtd_device_register(mtd, NULL, 0);
        if (ret)
                nand_cleanup(chip);
@@ -2847,16 +2857,6 @@ static int qcom_probe_nand_devices(struct qcom_nand_controller *nandc)
        struct qcom_nand_host *host;
        int ret;
 
-       if (nandc->props->is_bam) {
-               free_bam_transaction(nandc);
-               nandc->bam_txn = alloc_bam_transaction(nandc);
-               if (!nandc->bam_txn) {
-                       dev_err(nandc->dev,
-                               "failed to allocate bam transaction\n");
-                       return -ENOMEM;
-               }
-       }
-
        for_each_available_child_of_node(dn, child) {
                host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
                if (!host) {
index 479c2f2..fa87ae2 100644 (file)
@@ -304,24 +304,30 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand,
        struct nand_device *nand = spinand_to_nand(spinand);
        struct mtd_info *mtd = nanddev_to_mtd(nand);
        struct nand_page_io_req adjreq = *req;
-       unsigned int nbytes = 0;
-       void *buf = NULL;
+       void *buf = spinand->databuf;
+       unsigned int nbytes;
        u16 column = 0;
        int ret;
 
-       memset(spinand->databuf, 0xff,
-              nanddev_page_size(nand) +
-              nanddev_per_page_oobsize(nand));
+       /*
+        * Looks like PROGRAM LOAD (AKA write cache) does not necessarily reset
+        * the cache content to 0xFF (depends on vendor implementation), so we
+        * must fill the page cache entirely even if we only want to program
+        * the data portion of the page, otherwise we might corrupt the BBM or
+        * user data previously programmed in OOB area.
+        */
+       nbytes = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand);
+       memset(spinand->databuf, 0xff, nbytes);
+       adjreq.dataoffs = 0;
+       adjreq.datalen = nanddev_page_size(nand);
+       adjreq.databuf.out = spinand->databuf;
+       adjreq.ooblen = nanddev_per_page_oobsize(nand);
+       adjreq.ooboffs = 0;
+       adjreq.oobbuf.out = spinand->oobbuf;
 
-       if (req->datalen) {
+       if (req->datalen)
                memcpy(spinand->databuf + req->dataoffs, req->databuf.out,
                       req->datalen);
-               adjreq.dataoffs = 0;
-               adjreq.datalen = nanddev_page_size(nand);
-               adjreq.databuf.out = spinand->databuf;
-               nbytes = adjreq.datalen;
-               buf = spinand->databuf;
-       }
 
        if (req->ooblen) {
                if (req->mode == MTD_OPS_AUTO_OOB)
@@ -332,14 +338,6 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand,
                else
                        memcpy(spinand->oobbuf + req->ooboffs, req->oobbuf.out,
                               req->ooblen);
-
-               adjreq.ooblen = nanddev_per_page_oobsize(nand);
-               adjreq.ooboffs = 0;
-               nbytes += nanddev_per_page_oobsize(nand);
-               if (!buf) {
-                       buf = spinand->oobbuf;
-                       column = nanddev_page_size(nand);
-               }
        }
 
        spinand_cache_op_adjust_colum(spinand, &adjreq, &column);
@@ -370,8 +368,8 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand,
 
                /*
                 * We need to use the RANDOM LOAD CACHE operation if there's
-                * more than one iteration, because the LOAD operation resets
-                * the cache to 0xff.
+                * more than one iteration, because the LOAD operation might
+                * reset the cache to 0xff.
                 */
                if (nbytes) {
                        column = op.addr.val;
@@ -1018,11 +1016,11 @@ static int spinand_init(struct spinand_device *spinand)
        for (i = 0; i < nand->memorg.ntargets; i++) {
                ret = spinand_select_target(spinand, i);
                if (ret)
-                       goto err_free_bufs;
+                       goto err_manuf_cleanup;
 
                ret = spinand_lock_block(spinand, BL_ALL_UNLOCKED);
                if (ret)
-                       goto err_free_bufs;
+                       goto err_manuf_cleanup;
        }
 
        ret = nanddev_init(nand, &spinand_ops, THIS_MODULE);
index 6371958..21bf8ac 100644 (file)
@@ -197,9 +197,9 @@ config VXLAN
 
 config GENEVE
        tristate "Generic Network Virtualization Encapsulation"
-       depends on INET && NET_UDP_TUNNEL
+       depends on INET
        depends on IPV6 || !IPV6
-       select NET_IP_TUNNEL
+       select NET_UDP_TUNNEL
        select GRO_CELLS
        ---help---
          This allows one to create geneve virtual interfaces that provide
@@ -519,7 +519,7 @@ config NET_FAILOVER
          and destroy a failover master netdev and manages a primary and
          standby slave netdevs that get registered via the generic failover
          infrastructure. This can be used by paravirtual drivers to enable
-         an alternate low latency datapath. It alsoenables live migration of
+         an alternate low latency datapath. It also enables live migration of
          a VM with direct attached VF by failing over to the paravirtual
          datapath when the VF is unplugged.
 
index a9d597f..485462d 100644 (file)
@@ -1963,6 +1963,9 @@ static int __bond_release_one(struct net_device *bond_dev,
        if (!bond_has_slaves(bond)) {
                bond_set_carrier(bond);
                eth_hw_addr_random(bond_dev);
+               bond->nest_level = SINGLE_DEPTH_NESTING;
+       } else {
+               bond->nest_level = dev_get_nest_level(bond_dev) + 1;
        }
 
        unblock_netpoll_tx();
index a0f954f..44e6c7b 100644 (file)
@@ -257,10 +257,7 @@ static int handle_tx(struct ser_device *ser)
                if (skb->len == 0) {
                        struct sk_buff *tmp = skb_dequeue(&ser->head);
                        WARN_ON(tmp != skb);
-                       if (in_interrupt())
-                               dev_kfree_skb_irq(skb);
-                       else
-                               kfree_skb(skb);
+                       dev_consume_skb_any(skb);
                }
        }
        /* Send flow off if queue is empty */
index 3b3f88f..c05e4d5 100644 (file)
@@ -480,8 +480,6 @@ EXPORT_SYMBOL_GPL(can_put_echo_skb);
 struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
 {
        struct can_priv *priv = netdev_priv(dev);
-       struct sk_buff *skb = priv->echo_skb[idx];
-       struct canfd_frame *cf;
 
        if (idx >= priv->echo_skb_max) {
                netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
@@ -489,20 +487,21 @@ struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8
                return NULL;
        }
 
-       if (!skb) {
-               netdev_err(dev, "%s: BUG! Trying to echo non existing skb: can_priv::echo_skb[%u]\n",
-                          __func__, idx);
-               return NULL;
-       }
+       if (priv->echo_skb[idx]) {
+               /* Using "struct canfd_frame::len" for the frame
+                * length is supported on both CAN and CANFD frames.
+                */
+               struct sk_buff *skb = priv->echo_skb[idx];
+               struct canfd_frame *cf = (struct canfd_frame *)skb->data;
+               u8 len = cf->len;
 
-       /* Using "struct canfd_frame::len" for the frame
-        * length is supported on both CAN and CANFD frames.
-        */
-       cf = (struct canfd_frame *)skb->data;
-       *len_ptr = cf->len;
-       priv->echo_skb[idx] = NULL;
+               *len_ptr = len;
+               priv->echo_skb[idx] = NULL;
 
-       return skb;
+               return skb;
+       }
+
+       return NULL;
 }
 
 /*
index 0f36eaf..1c66fb2 100644 (file)
@@ -1106,7 +1106,7 @@ static int flexcan_chip_start(struct net_device *dev)
                }
        } else {
                /* clear and invalidate unused mailboxes first */
-               for (i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO; i <= priv->mb_count; i++) {
+               for (i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO; i < priv->mb_count; i++) {
                        mb = flexcan_get_mb(priv, i);
                        priv->write(FLEXCAN_MB_CODE_RX_INACTIVE,
                                    &mb->can_ctrl);
@@ -1432,7 +1432,7 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev)
        gpr_np = of_find_node_by_phandle(phandle);
        if (!gpr_np) {
                dev_dbg(&pdev->dev, "could not find gpr node by phandle\n");
-               return PTR_ERR(gpr_np);
+               return -ENODEV;
        }
 
        priv = netdev_priv(dev);
index 90f5142..d9c56a7 100644 (file)
@@ -511,9 +511,6 @@ static void b53_srab_prepare_irq(struct platform_device *pdev)
        /* Clear all pending interrupts */
        writel(0xffffffff, priv->regs + B53_SRAB_INTR);
 
-       if (dev->pdata && dev->pdata->chip_id != BCM58XX_DEVICE_ID)
-               return;
-
        for (i = 0; i < B53_N_PORTS; i++) {
                port = &priv->port_intrs[i];
 
index 361fbde..17ec32b 100644 (file)
@@ -690,7 +690,7 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds)
         * port, the other ones have already been disabled during
         * bcm_sf2_sw_setup
         */
-       for (port = 0; port < DSA_MAX_PORTS; port++) {
+       for (port = 0; port < ds->num_ports; port++) {
                if (dsa_is_user_port(ds, port) || dsa_is_cpu_port(ds, port))
                        bcm_sf2_port_disable(ds, port, NULL);
        }
index 3b12e2d..8a5111f 100644 (file)
@@ -7,7 +7,6 @@
 
 #include <linux/delay.h>
 #include <linux/export.h>
-#include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -15,7 +14,6 @@
 #include <linux/phy.h>
 #include <linux/etherdevice.h>
 #include <linux/if_bridge.h>
-#include <linux/of_gpio.h>
 #include <linux/of_net.h>
 #include <net/dsa.h>
 #include <net/switchdev.h>
index 74547f4..a8a2c72 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
-#include <linux/of_gpio.h>
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
 #include <linux/of_platform.h>
index 8a517d8..12fd7ce 100644 (file)
@@ -261,6 +261,7 @@ static irqreturn_t mv88e6xxx_g1_irq_thread_work(struct mv88e6xxx_chip *chip)
        unsigned int sub_irq;
        unsigned int n;
        u16 reg;
+       u16 ctl1;
        int err;
 
        mutex_lock(&chip->reg_lock);
@@ -270,13 +271,28 @@ static irqreturn_t mv88e6xxx_g1_irq_thread_work(struct mv88e6xxx_chip *chip)
        if (err)
                goto out;
 
-       for (n = 0; n < chip->g1_irq.nirqs; ++n) {
-               if (reg & (1 << n)) {
-                       sub_irq = irq_find_mapping(chip->g1_irq.domain, n);
-                       handle_nested_irq(sub_irq);
-                       ++nhandled;
+       do {
+               for (n = 0; n < chip->g1_irq.nirqs; ++n) {
+                       if (reg & (1 << n)) {
+                               sub_irq = irq_find_mapping(chip->g1_irq.domain,
+                                                          n);
+                               handle_nested_irq(sub_irq);
+                               ++nhandled;
+                       }
                }
-       }
+
+               mutex_lock(&chip->reg_lock);
+               err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &ctl1);
+               if (err)
+                       goto unlock;
+               err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &reg);
+unlock:
+               mutex_unlock(&chip->reg_lock);
+               if (err)
+                       goto out;
+               ctl1 &= GENMASK(chip->g1_irq.nirqs, 0);
+       } while (reg & ctl1);
+
 out:
        return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
 }
@@ -2403,6 +2419,107 @@ static int mv88e6xxx_stats_setup(struct mv88e6xxx_chip *chip)
        return mv88e6xxx_g1_stats_clear(chip);
 }
 
+/* The mv88e6390 has some hidden registers used for debug and
+ * development. The errata also makes use of them.
+ */
+static int mv88e6390_hidden_write(struct mv88e6xxx_chip *chip, int port,
+                                 int reg, u16 val)
+{
+       u16 ctrl;
+       int err;
+
+       err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_DATA_PORT,
+                                  PORT_RESERVED_1A, val);
+       if (err)
+               return err;
+
+       ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_WRITE |
+              PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
+              reg;
+
+       return mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
+                                   PORT_RESERVED_1A, ctrl);
+}
+
+static int mv88e6390_hidden_wait(struct mv88e6xxx_chip *chip)
+{
+       return mv88e6xxx_wait(chip, PORT_RESERVED_1A_CTRL_PORT,
+                             PORT_RESERVED_1A, PORT_RESERVED_1A_BUSY);
+}
+
+
+static int mv88e6390_hidden_read(struct mv88e6xxx_chip *chip, int port,
+                                 int reg, u16 *val)
+{
+       u16 ctrl;
+       int err;
+
+       ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_READ |
+              PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
+              reg;
+
+       err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
+                                  PORT_RESERVED_1A, ctrl);
+       if (err)
+               return err;
+
+       err = mv88e6390_hidden_wait(chip);
+       if (err)
+               return err;
+
+       return  mv88e6xxx_port_read(chip, PORT_RESERVED_1A_DATA_PORT,
+                                   PORT_RESERVED_1A, val);
+}
+
+/* Check if the errata has already been applied. */
+static bool mv88e6390_setup_errata_applied(struct mv88e6xxx_chip *chip)
+{
+       int port;
+       int err;
+       u16 val;
+
+       for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+               err = mv88e6390_hidden_read(chip, port, 0, &val);
+               if (err) {
+                       dev_err(chip->dev,
+                               "Error reading hidden register: %d\n", err);
+                       return false;
+               }
+               if (val != 0x01c0)
+                       return false;
+       }
+
+       return true;
+}
+
+/* The 6390 copper ports have an errata which require poking magic
+ * values into undocumented hidden registers and then performing a
+ * software reset.
+ */
+static int mv88e6390_setup_errata(struct mv88e6xxx_chip *chip)
+{
+       int port;
+       int err;
+
+       if (mv88e6390_setup_errata_applied(chip))
+               return 0;
+
+       /* Set the ports into blocking mode */
+       for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+               err = mv88e6xxx_port_set_state(chip, port, BR_STATE_DISABLED);
+               if (err)
+                       return err;
+       }
+
+       for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+               err = mv88e6390_hidden_write(chip, port, 0, 0x01c0);
+               if (err)
+                       return err;
+       }
+
+       return mv88e6xxx_software_reset(chip);
+}
+
 static int mv88e6xxx_setup(struct dsa_switch *ds)
 {
        struct mv88e6xxx_chip *chip = ds->priv;
@@ -2415,6 +2532,12 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
 
        mutex_lock(&chip->reg_lock);
 
+       if (chip->info->ops->setup_errata) {
+               err = chip->info->ops->setup_errata(chip);
+               if (err)
+                       goto unlock;
+       }
+
        /* Cache the cmode of each port. */
        for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
                if (chip->info->ops->port_get_cmode) {
@@ -3226,6 +3349,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
 
 static const struct mv88e6xxx_ops mv88e6190_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .setup_errata = mv88e6390_setup_errata,
        .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3269,6 +3393,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
 
 static const struct mv88e6xxx_ops mv88e6190x_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .setup_errata = mv88e6390_setup_errata,
        .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3312,6 +3437,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
 
 static const struct mv88e6xxx_ops mv88e6191_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .setup_errata = mv88e6390_setup_errata,
        .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3404,6 +3530,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
 
 static const struct mv88e6xxx_ops mv88e6290_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .setup_errata = mv88e6390_setup_errata,
        .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3709,6 +3836,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
 
 static const struct mv88e6xxx_ops mv88e6390_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .setup_errata = mv88e6390_setup_errata,
        .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3756,6 +3884,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
 
 static const struct mv88e6xxx_ops mv88e6390x_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .setup_errata = mv88e6390_setup_errata,
        .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
index f9ecb78..546651d 100644 (file)
@@ -300,6 +300,11 @@ struct mv88e6xxx_mdio_bus {
 };
 
 struct mv88e6xxx_ops {
+       /* Switch Setup Errata, called early in the switch setup to
+        * allow any errata actions to be performed
+        */
+       int (*setup_errata)(struct mv88e6xxx_chip *chip);
+
        int (*ieee_pri_map)(struct mv88e6xxx_chip *chip);
        int (*ip_pri_map)(struct mv88e6xxx_chip *chip);
 
index 5200e4b..ea24384 100644 (file)
@@ -314,6 +314,7 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
 {
        struct mv88e6xxx_chip *chip = dev_id;
        struct mv88e6xxx_atu_entry entry;
+       int spid;
        int err;
        u16 val;
 
@@ -336,6 +337,8 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
        if (err)
                goto out;
 
+       spid = entry.state;
+
        if (val & MV88E6XXX_G1_ATU_OP_AGE_OUT_VIOLATION) {
                dev_err_ratelimited(chip->dev,
                                    "ATU age out violation for %pM\n",
@@ -344,23 +347,23 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
 
        if (val & MV88E6XXX_G1_ATU_OP_MEMBER_VIOLATION) {
                dev_err_ratelimited(chip->dev,
-                                   "ATU member violation for %pM portvec %x\n",
-                                   entry.mac, entry.portvec);
-               chip->ports[entry.portvec].atu_member_violation++;
+                                   "ATU member violation for %pM portvec %x spid %d\n",
+                                   entry.mac, entry.portvec, spid);
+               chip->ports[spid].atu_member_violation++;
        }
 
        if (val & MV88E6XXX_G1_ATU_OP_MISS_VIOLATION) {
                dev_err_ratelimited(chip->dev,
-                                   "ATU miss violation for %pM portvec %x\n",
-                                   entry.mac, entry.portvec);
-               chip->ports[entry.portvec].atu_miss_violation++;
+                                   "ATU miss violation for %pM portvec %x spid %d\n",
+                                   entry.mac, entry.portvec, spid);
+               chip->ports[spid].atu_miss_violation++;
        }
 
        if (val & MV88E6XXX_G1_ATU_OP_FULL_VIOLATION) {
                dev_err_ratelimited(chip->dev,
-                                   "ATU full violation for %pM portvec %x\n",
-                                   entry.mac, entry.portvec);
-               chip->ports[entry.portvec].atu_full_violation++;
+                                   "ATU full violation for %pM portvec %x spid %d\n",
+                                   entry.mac, entry.portvec, spid);
+               chip->ports[spid].atu_full_violation++;
        }
        mutex_unlock(&chip->reg_lock);
 
index 0d81866..e583641 100644 (file)
 /* Offset 0x19: Port IEEE Priority Remapping Registers (4-7) */
 #define MV88E6095_PORT_IEEE_PRIO_REMAP_4567    0x19
 
+/* Offset 0x1a: Magic undocumented errata register */
+#define PORT_RESERVED_1A                       0x1a
+#define PORT_RESERVED_1A_BUSY                  BIT(15)
+#define PORT_RESERVED_1A_WRITE                 BIT(14)
+#define PORT_RESERVED_1A_READ                  0
+#define PORT_RESERVED_1A_PORT_SHIFT            5
+#define PORT_RESERVED_1A_BLOCK                 (0xf << 10)
+#define PORT_RESERVED_1A_CTRL_PORT             4
+#define PORT_RESERVED_1A_DATA_PORT             5
+
 int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
                        u16 *val);
 int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
index 2caa8c8..1bfc5ff 100644 (file)
@@ -664,7 +664,7 @@ int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
        if (port < 9)
                return 0;
 
-       return mv88e6390_serdes_irq_setup(chip, port);
+       return mv88e6390x_serdes_irq_setup(chip, port);
 }
 
 void mv88e6390x_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
index b4b839a..ad41ec6 100644 (file)
@@ -347,16 +347,17 @@ int realtek_smi_setup_mdio(struct realtek_smi *smi)
        struct device_node *mdio_np;
        int ret;
 
-       mdio_np = of_find_compatible_node(smi->dev->of_node, NULL,
-                                         "realtek,smi-mdio");
+       mdio_np = of_get_compatible_child(smi->dev->of_node, "realtek,smi-mdio");
        if (!mdio_np) {
                dev_err(smi->dev, "no MDIO bus node\n");
                return -ENODEV;
        }
 
        smi->slave_mii_bus = devm_mdiobus_alloc(smi->dev);
-       if (!smi->slave_mii_bus)
-               return -ENOMEM;
+       if (!smi->slave_mii_bus) {
+               ret = -ENOMEM;
+               goto err_put_node;
+       }
        smi->slave_mii_bus->priv = smi;
        smi->slave_mii_bus->name = "SMI slave MII";
        smi->slave_mii_bus->read = realtek_smi_mdio_read;
@@ -371,10 +372,15 @@ int realtek_smi_setup_mdio(struct realtek_smi *smi)
        if (ret) {
                dev_err(smi->dev, "unable to register MDIO bus %s\n",
                        smi->slave_mii_bus->id);
-               of_node_put(mdio_np);
+               goto err_put_node;
        }
 
        return 0;
+
+err_put_node:
+       of_node_put(mdio_np);
+
+       return ret;
 }
 
 static int realtek_smi_probe(struct platform_device *pdev)
@@ -457,6 +463,8 @@ static int realtek_smi_remove(struct platform_device *pdev)
        struct realtek_smi *smi = dev_get_drvdata(&pdev->dev);
 
        dsa_unregister_switch(smi->ds);
+       if (smi->slave_mii_bus)
+               of_node_put(smi->slave_mii_bus->dev.of_node);
        gpiod_set_value(smi->reset, 1);
 
        return 0;
index 91fc64c..47e5984 100644 (file)
@@ -1433,18 +1433,18 @@ static int greth_of_probe(struct platform_device *ofdev)
        }
 
        /* Allocate TX descriptor ring in coherent memory */
-       greth->tx_bd_base = dma_zalloc_coherent(greth->dev, 1024,
-                                               &greth->tx_bd_base_phys,
-                                               GFP_KERNEL);
+       greth->tx_bd_base = dma_alloc_coherent(greth->dev, 1024,
+                                              &greth->tx_bd_base_phys,
+                                              GFP_KERNEL);
        if (!greth->tx_bd_base) {
                err = -ENOMEM;
                goto error3;
        }
 
        /* Allocate RX descriptor ring in coherent memory */
-       greth->rx_bd_base = dma_zalloc_coherent(greth->dev, 1024,
-                                               &greth->rx_bd_base_phys,
-                                               GFP_KERNEL);
+       greth->rx_bd_base = dma_alloc_coherent(greth->dev, 1024,
+                                              &greth->rx_bd_base_phys,
+                                              GFP_KERNEL);
        if (!greth->rx_bd_base) {
                err = -ENOMEM;
                goto error4;
index 0b60921..16477aa 100644 (file)
@@ -795,8 +795,8 @@ static int slic_init_stat_queue(struct slic_device *sdev)
        size = stq->len * sizeof(*descs) + DESC_ALIGN_MASK;
 
        for (i = 0; i < SLIC_NUM_STAT_DESC_ARRAYS; i++) {
-               descs = dma_zalloc_coherent(&sdev->pdev->dev, size, &paddr,
-                                           GFP_KERNEL);
+               descs = dma_alloc_coherent(&sdev->pdev->dev, size, &paddr,
+                                          GFP_KERNEL);
                if (!descs) {
                        netdev_err(sdev->netdev,
                                   "failed to allocate status descriptors\n");
@@ -1240,8 +1240,8 @@ static int slic_init_shmem(struct slic_device *sdev)
        struct slic_shmem_data *sm_data;
        dma_addr_t paddr;
 
-       sm_data = dma_zalloc_coherent(&sdev->pdev->dev, sizeof(*sm_data),
-                                     &paddr, GFP_KERNEL);
+       sm_data = dma_alloc_coherent(&sdev->pdev->dev, sizeof(*sm_data),
+                                    &paddr, GFP_KERNEL);
        if (!sm_data) {
                dev_err(&sdev->pdev->dev, "failed to allocate shared memory\n");
                return -ENOMEM;
@@ -1621,8 +1621,8 @@ static int slic_read_eeprom(struct slic_device *sdev)
        int err = 0;
        u8 *mac[2];
 
-       eeprom = dma_zalloc_coherent(&sdev->pdev->dev, SLIC_EEPROM_SIZE,
-                                    &paddr, GFP_KERNEL);
+       eeprom = dma_alloc_coherent(&sdev->pdev->dev, SLIC_EEPROM_SIZE,
+                                   &paddr, GFP_KERNEL);
        if (!eeprom)
                return -ENOMEM;
 
index 4f11f98..1827ef1 100644 (file)
@@ -2059,7 +2059,7 @@ static inline void ace_tx_int(struct net_device *dev,
                if (skb) {
                        dev->stats.tx_packets++;
                        dev->stats.tx_bytes += skb->len;
-                       dev_kfree_skb_irq(skb);
+                       dev_consume_skb_irq(skb);
                        info->skb = NULL;
                }
 
index 0fb986b..0ae723f 100644 (file)
@@ -145,7 +145,8 @@ u32 msgdma_tx_completions(struct altera_tse_private *priv)
                        & 0xffff;
 
        if (inuse) { /* Tx FIFO is not empty */
-               ready = priv->tx_prod - priv->tx_cons - inuse - 1;
+               ready = max_t(int,
+                             priv->tx_prod - priv->tx_cons - inuse - 1, 0);
        } else {
                /* Check for buffered last packet */
                status = csrrd32(priv->tx_dma_csr, msgdma_csroffs(status));
index 02921d8..aa1d1f5 100644 (file)
@@ -714,8 +714,10 @@ static struct phy_device *connect_local_phy(struct net_device *dev)
 
                phydev = phy_connect(dev, phy_id_fmt, &altera_tse_adjust_link,
                                     priv->phy_iface);
-               if (IS_ERR(phydev))
+               if (IS_ERR(phydev)) {
                        netdev_err(dev, "Could not attach to PHY\n");
+                       phydev = NULL;
+               }
 
        } else {
                int ret;
index 420cede..b17d435 100644 (file)
@@ -111,8 +111,8 @@ static int ena_com_admin_init_sq(struct ena_com_admin_queue *queue)
        struct ena_com_admin_sq *sq = &queue->sq;
        u16 size = ADMIN_SQ_SIZE(queue->q_depth);
 
-       sq->entries = dma_zalloc_coherent(queue->q_dmadev, size, &sq->dma_addr,
-                                         GFP_KERNEL);
+       sq->entries = dma_alloc_coherent(queue->q_dmadev, size, &sq->dma_addr,
+                                        GFP_KERNEL);
 
        if (!sq->entries) {
                pr_err("memory allocation failed");
@@ -133,8 +133,8 @@ static int ena_com_admin_init_cq(struct ena_com_admin_queue *queue)
        struct ena_com_admin_cq *cq = &queue->cq;
        u16 size = ADMIN_CQ_SIZE(queue->q_depth);
 
-       cq->entries = dma_zalloc_coherent(queue->q_dmadev, size, &cq->dma_addr,
-                                         GFP_KERNEL);
+       cq->entries = dma_alloc_coherent(queue->q_dmadev, size, &cq->dma_addr,
+                                        GFP_KERNEL);
 
        if (!cq->entries) {
                pr_err("memory allocation failed");
@@ -156,8 +156,8 @@ static int ena_com_admin_init_aenq(struct ena_com_dev *dev,
 
        dev->aenq.q_depth = ENA_ASYNC_QUEUE_DEPTH;
        size = ADMIN_AENQ_SIZE(ENA_ASYNC_QUEUE_DEPTH);
-       aenq->entries = dma_zalloc_coherent(dev->dmadev, size, &aenq->dma_addr,
-                                           GFP_KERNEL);
+       aenq->entries = dma_alloc_coherent(dev->dmadev, size, &aenq->dma_addr,
+                                          GFP_KERNEL);
 
        if (!aenq->entries) {
                pr_err("memory allocation failed");
@@ -344,15 +344,15 @@ static int ena_com_init_io_sq(struct ena_com_dev *ena_dev,
                dev_node = dev_to_node(ena_dev->dmadev);
                set_dev_node(ena_dev->dmadev, ctx->numa_node);
                io_sq->desc_addr.virt_addr =
-                       dma_zalloc_coherent(ena_dev->dmadev, size,
-                                           &io_sq->desc_addr.phys_addr,
-                                           GFP_KERNEL);
+                       dma_alloc_coherent(ena_dev->dmadev, size,
+                                          &io_sq->desc_addr.phys_addr,
+                                          GFP_KERNEL);
                set_dev_node(ena_dev->dmadev, dev_node);
                if (!io_sq->desc_addr.virt_addr) {
                        io_sq->desc_addr.virt_addr =
-                               dma_zalloc_coherent(ena_dev->dmadev, size,
-                                                   &io_sq->desc_addr.phys_addr,
-                                                   GFP_KERNEL);
+                               dma_alloc_coherent(ena_dev->dmadev, size,
+                                                  &io_sq->desc_addr.phys_addr,
+                                                  GFP_KERNEL);
                }
 
                if (!io_sq->desc_addr.virt_addr) {
@@ -425,14 +425,14 @@ static int ena_com_init_io_cq(struct ena_com_dev *ena_dev,
        prev_node = dev_to_node(ena_dev->dmadev);
        set_dev_node(ena_dev->dmadev, ctx->numa_node);
        io_cq->cdesc_addr.virt_addr =
-               dma_zalloc_coherent(ena_dev->dmadev, size,
-                                   &io_cq->cdesc_addr.phys_addr, GFP_KERNEL);
+               dma_alloc_coherent(ena_dev->dmadev, size,
+                                  &io_cq->cdesc_addr.phys_addr, GFP_KERNEL);
        set_dev_node(ena_dev->dmadev, prev_node);
        if (!io_cq->cdesc_addr.virt_addr) {
                io_cq->cdesc_addr.virt_addr =
-                       dma_zalloc_coherent(ena_dev->dmadev, size,
-                                           &io_cq->cdesc_addr.phys_addr,
-                                           GFP_KERNEL);
+                       dma_alloc_coherent(ena_dev->dmadev, size,
+                                          &io_cq->cdesc_addr.phys_addr,
+                                          GFP_KERNEL);
        }
 
        if (!io_cq->cdesc_addr.virt_addr) {
@@ -1026,8 +1026,8 @@ static int ena_com_hash_key_allocate(struct ena_com_dev *ena_dev)
        struct ena_rss *rss = &ena_dev->rss;
 
        rss->hash_key =
-               dma_zalloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_key),
-                                   &rss->hash_key_dma_addr, GFP_KERNEL);
+               dma_alloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_key),
+                                  &rss->hash_key_dma_addr, GFP_KERNEL);
 
        if (unlikely(!rss->hash_key))
                return -ENOMEM;
@@ -1050,8 +1050,8 @@ static int ena_com_hash_ctrl_init(struct ena_com_dev *ena_dev)
        struct ena_rss *rss = &ena_dev->rss;
 
        rss->hash_ctrl =
-               dma_zalloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_ctrl),
-                                   &rss->hash_ctrl_dma_addr, GFP_KERNEL);
+               dma_alloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_ctrl),
+                                  &rss->hash_ctrl_dma_addr, GFP_KERNEL);
 
        if (unlikely(!rss->hash_ctrl))
                return -ENOMEM;
@@ -1094,8 +1094,8 @@ static int ena_com_indirect_table_allocate(struct ena_com_dev *ena_dev,
                sizeof(struct ena_admin_rss_ind_table_entry);
 
        rss->rss_ind_tbl =
-               dma_zalloc_coherent(ena_dev->dmadev, tbl_size,
-                                   &rss->rss_ind_tbl_dma_addr, GFP_KERNEL);
+               dma_alloc_coherent(ena_dev->dmadev, tbl_size,
+                                  &rss->rss_ind_tbl_dma_addr, GFP_KERNEL);
        if (unlikely(!rss->rss_ind_tbl))
                goto mem_err1;
 
@@ -1649,9 +1649,9 @@ int ena_com_mmio_reg_read_request_init(struct ena_com_dev *ena_dev)
 
        spin_lock_init(&mmio_read->lock);
        mmio_read->read_resp =
-               dma_zalloc_coherent(ena_dev->dmadev,
-                                   sizeof(*mmio_read->read_resp),
-                                   &mmio_read->read_resp_dma_addr, GFP_KERNEL);
+               dma_alloc_coherent(ena_dev->dmadev,
+                                  sizeof(*mmio_read->read_resp),
+                                  &mmio_read->read_resp_dma_addr, GFP_KERNEL);
        if (unlikely(!mmio_read->read_resp))
                goto err;
 
@@ -2623,8 +2623,8 @@ int ena_com_allocate_host_info(struct ena_com_dev *ena_dev)
        struct ena_host_attribute *host_attr = &ena_dev->host_attr;
 
        host_attr->host_info =
-               dma_zalloc_coherent(ena_dev->dmadev, SZ_4K,
-                                   &host_attr->host_info_dma_addr, GFP_KERNEL);
+               dma_alloc_coherent(ena_dev->dmadev, SZ_4K,
+                                  &host_attr->host_info_dma_addr, GFP_KERNEL);
        if (unlikely(!host_attr->host_info))
                return -ENOMEM;
 
@@ -2641,8 +2641,9 @@ int ena_com_allocate_debug_area(struct ena_com_dev *ena_dev,
        struct ena_host_attribute *host_attr = &ena_dev->host_attr;
 
        host_attr->debug_area_virt_addr =
-               dma_zalloc_coherent(ena_dev->dmadev, debug_area_size,
-                                   &host_attr->debug_area_dma_addr, GFP_KERNEL);
+               dma_alloc_coherent(ena_dev->dmadev, debug_area_size,
+                                  &host_attr->debug_area_dma_addr,
+                                  GFP_KERNEL);
        if (unlikely(!host_attr->debug_area_virt_addr)) {
                host_attr->debug_area_size = 0;
                return -ENOMEM;
index a70bb1b..a6eacf2 100644 (file)
@@ -2663,11 +2663,6 @@ static int ena_restore_device(struct ena_adapter *adapter)
                goto err_device_destroy;
        }
 
-       clear_bit(ENA_FLAG_ONGOING_RESET, &adapter->flags);
-       /* Make sure we don't have a race with AENQ Links state handler */
-       if (test_bit(ENA_FLAG_LINK_UP, &adapter->flags))
-               netif_carrier_on(adapter->netdev);
-
        rc = ena_enable_msix_and_set_admin_interrupts(adapter,
                                                      adapter->num_queues);
        if (rc) {
@@ -2684,6 +2679,11 @@ static int ena_restore_device(struct ena_adapter *adapter)
        }
 
        set_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags);
+
+       clear_bit(ENA_FLAG_ONGOING_RESET, &adapter->flags);
+       if (test_bit(ENA_FLAG_LINK_UP, &adapter->flags))
+               netif_carrier_on(adapter->netdev);
+
        mod_timer(&adapter->timer_service, round_jiffies(jiffies + HZ));
        dev_err(&pdev->dev,
                "Device reset completed successfully, Driver info: %s\n",
index dc8b617..6387007 100644 (file)
@@ -45,7 +45,7 @@
 
 #define DRV_MODULE_VER_MAJOR   2
 #define DRV_MODULE_VER_MINOR   0
-#define DRV_MODULE_VER_SUBMINOR 2
+#define DRV_MODULE_VER_SUBMINOR 3
 
 #define DRV_MODULE_NAME                "ena"
 #ifndef DRV_MODULE_VERSION
index a90080f..e548c0a 100644 (file)
@@ -666,7 +666,7 @@ static int amd8111e_tx(struct net_device *dev)
                        pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[tx_index],
                                        lp->tx_skbuff[tx_index]->len,
                                        PCI_DMA_TODEVICE);
-                       dev_kfree_skb_irq (lp->tx_skbuff[tx_index]);
+                       dev_consume_skb_irq(lp->tx_skbuff[tx_index]);
                        lp->tx_skbuff[tx_index] = NULL;
                        lp->tx_dma_addr[tx_index] = 0;
                }
index d272dc6..b40d437 100644 (file)
 #define MAC_MDIOSCAR_PA_WIDTH          5
 #define MAC_MDIOSCAR_RA_INDEX          0
 #define MAC_MDIOSCAR_RA_WIDTH          16
-#define MAC_MDIOSCAR_REG_INDEX         0
-#define MAC_MDIOSCAR_REG_WIDTH         21
 #define MAC_MDIOSCCDR_BUSY_INDEX       22
 #define MAC_MDIOSCCDR_BUSY_WIDTH       1
 #define MAC_MDIOSCCDR_CMD_INDEX                16
index 1e929a1..4666084 100644 (file)
@@ -1284,6 +1284,20 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
        }
 }
 
+static unsigned int xgbe_create_mdio_sca(int port, int reg)
+{
+       unsigned int mdio_sca, da;
+
+       da = (reg & MII_ADDR_C45) ? reg >> 16 : 0;
+
+       mdio_sca = 0;
+       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, RA, reg);
+       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, PA, port);
+       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, da);
+
+       return mdio_sca;
+}
+
 static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
                                   int reg, u16 val)
 {
@@ -1291,9 +1305,7 @@ static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
 
        reinit_completion(&pdata->mdio_complete);
 
-       mdio_sca = 0;
-       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
-       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
+       mdio_sca = xgbe_create_mdio_sca(addr, reg);
        XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
 
        mdio_sccd = 0;
@@ -1317,9 +1329,7 @@ static int xgbe_read_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
 
        reinit_completion(&pdata->mdio_complete);
 
-       mdio_sca = 0;
-       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
-       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
+       mdio_sca = xgbe_create_mdio_sca(addr, reg);
        XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
 
        mdio_sccd = 0;
index 0f2ad50..87b142a 100644 (file)
@@ -206,8 +206,8 @@ static netdev_tx_t xge_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        }
 
        /* Packet buffers should be 64B aligned */
-       pkt_buf = dma_zalloc_coherent(dev, XGENE_ENET_STD_MTU, &dma_addr,
-                                     GFP_ATOMIC);
+       pkt_buf = dma_alloc_coherent(dev, XGENE_ENET_STD_MTU, &dma_addr,
+                                    GFP_ATOMIC);
        if (unlikely(!pkt_buf)) {
                dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
@@ -428,8 +428,8 @@ static struct xge_desc_ring *xge_create_desc_ring(struct net_device *ndev)
        ring->ndev = ndev;
 
        size = XGENE_ENET_DESC_SIZE * XGENE_ENET_NUM_DESC;
-       ring->desc_addr = dma_zalloc_coherent(dev, size, &ring->dma_addr,
-                                             GFP_KERNEL);
+       ring->desc_addr = dma_alloc_coherent(dev, size, &ring->dma_addr,
+                                            GFP_KERNEL);
        if (!ring->desc_addr)
                goto err;
 
index 6a8e256..4d3855c 100644 (file)
@@ -777,7 +777,7 @@ static irqreturn_t bmac_txdma_intr(int irq, void *dev_id)
 
                if (bp->tx_bufs[bp->tx_empty]) {
                        ++dev->stats.tx_packets;
-                       dev_kfree_skb_irq(bp->tx_bufs[bp->tx_empty]);
+                       dev_consume_skb_irq(bp->tx_bufs[bp->tx_empty]);
                }
                bp->tx_bufs[bp->tx_empty] = NULL;
                bp->tx_fullup = 0;
index c131cfc..e3538ba 100644 (file)
@@ -660,10 +660,9 @@ static int alx_alloc_rings(struct alx_priv *alx)
                            alx->num_txq +
                            sizeof(struct alx_rrd) * alx->rx_ringsz +
                            sizeof(struct alx_rfd) * alx->rx_ringsz;
-       alx->descmem.virt = dma_zalloc_coherent(&alx->hw.pdev->dev,
-                                               alx->descmem.size,
-                                               &alx->descmem.dma,
-                                               GFP_KERNEL);
+       alx->descmem.virt = dma_alloc_coherent(&alx->hw.pdev->dev,
+                                              alx->descmem.size,
+                                              &alx->descmem.dma, GFP_KERNEL);
        if (!alx->descmem.virt)
                return -ENOMEM;
 
index 7087b88..3a3b35b 100644 (file)
@@ -1019,8 +1019,8 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter)
                sizeof(struct atl1c_recv_ret_status) * rx_desc_count +
                8 * 4;
 
-       ring_header->desc = dma_zalloc_coherent(&pdev->dev, ring_header->size,
-                                               &ring_header->dma, GFP_KERNEL);
+       ring_header->desc = dma_alloc_coherent(&pdev->dev, ring_header->size,
+                                              &ring_header->dma, GFP_KERNEL);
        if (unlikely(!ring_header->desc)) {
                dev_err(&pdev->dev, "could not get memory for DMA buffer\n");
                goto err_nomem;
index f448089..97ab0dd 100644 (file)
@@ -638,7 +638,7 @@ static void b44_tx(struct b44 *bp)
                bytes_compl += skb->len;
                pkts_compl++;
 
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
        }
 
        netdev_completed_queue(bp->dev, pkts_compl, bytes_compl);
@@ -1012,7 +1012,7 @@ static netdev_tx_t b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
                }
 
                skb_copy_from_linear_data(skb, skb_put(bounce_skb, len), len);
-               dev_kfree_skb_any(skb);
+               dev_consume_skb_any(skb);
                skb = bounce_skb;
        }
 
index 6bae973..09cd188 100644 (file)
@@ -936,7 +936,7 @@ static int bcm_enet_open(struct net_device *dev)
 
        /* allocate rx dma ring */
        size = priv->rx_ring_size * sizeof(struct bcm_enet_desc);
-       p = dma_zalloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL);
+       p = dma_alloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL);
        if (!p) {
                ret = -ENOMEM;
                goto out_freeirq_tx;
@@ -947,7 +947,7 @@ static int bcm_enet_open(struct net_device *dev)
 
        /* allocate tx dma ring */
        size = priv->tx_ring_size * sizeof(struct bcm_enet_desc);
-       p = dma_zalloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL);
+       p = dma_alloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL);
        if (!p) {
                ret = -ENOMEM;
                goto out_free_rx_ring;
@@ -2120,7 +2120,7 @@ static int bcm_enetsw_open(struct net_device *dev)
 
        /* allocate rx dma ring */
        size = priv->rx_ring_size * sizeof(struct bcm_enet_desc);
-       p = dma_zalloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL);
+       p = dma_alloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL);
        if (!p) {
                dev_err(kdev, "cannot allocate rx ring %u\n", size);
                ret = -ENOMEM;
@@ -2132,7 +2132,7 @@ static int bcm_enetsw_open(struct net_device *dev)
 
        /* allocate tx dma ring */
        size = priv->tx_ring_size * sizeof(struct bcm_enet_desc);
-       p = dma_zalloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL);
+       p = dma_alloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL);
        if (!p) {
                dev_err(kdev, "cannot allocate tx ring\n");
                ret = -ENOMEM;
index 4574275..28c9b0b 100644 (file)
@@ -520,7 +520,6 @@ static void bcm_sysport_get_wol(struct net_device *dev,
                                struct ethtool_wolinfo *wol)
 {
        struct bcm_sysport_priv *priv = netdev_priv(dev);
-       u32 reg;
 
        wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER;
        wol->wolopts = priv->wolopts;
@@ -528,11 +527,7 @@ static void bcm_sysport_get_wol(struct net_device *dev,
        if (!(priv->wolopts & WAKE_MAGICSECURE))
                return;
 
-       /* Return the programmed SecureOn password */
-       reg = umac_readl(priv, UMAC_PSW_MS);
-       put_unaligned_be16(reg, &wol->sopass[0]);
-       reg = umac_readl(priv, UMAC_PSW_LS);
-       put_unaligned_be32(reg, &wol->sopass[2]);
+       memcpy(wol->sopass, priv->sopass, sizeof(priv->sopass));
 }
 
 static int bcm_sysport_set_wol(struct net_device *dev,
@@ -548,13 +543,8 @@ static int bcm_sysport_set_wol(struct net_device *dev,
        if (wol->wolopts & ~supported)
                return -EINVAL;
 
-       /* Program the SecureOn password */
-       if (wol->wolopts & WAKE_MAGICSECURE) {
-               umac_writel(priv, get_unaligned_be16(&wol->sopass[0]),
-                           UMAC_PSW_MS);
-               umac_writel(priv, get_unaligned_be32(&wol->sopass[2]),
-                           UMAC_PSW_LS);
-       }
+       if (wol->wolopts & WAKE_MAGICSECURE)
+               memcpy(priv->sopass, wol->sopass, sizeof(priv->sopass));
 
        /* Flag the device and relevant IRQ as wakeup capable */
        if (wol->wolopts) {
@@ -1506,8 +1496,8 @@ static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv,
        /* We just need one DMA descriptor which is DMA-able, since writing to
         * the port will allocate a new descriptor in its internal linked-list
         */
-       p = dma_zalloc_coherent(kdev, sizeof(struct dma_desc), &ring->desc_dma,
-                               GFP_KERNEL);
+       p = dma_alloc_coherent(kdev, sizeof(struct dma_desc), &ring->desc_dma,
+                              GFP_KERNEL);
        if (!p) {
                netif_err(priv, hw, priv->netdev, "DMA alloc failed\n");
                return -ENOMEM;
@@ -2649,13 +2639,18 @@ static int bcm_sysport_suspend_to_wol(struct bcm_sysport_priv *priv)
        unsigned int index, i = 0;
        u32 reg;
 
-       /* Password has already been programmed */
        reg = umac_readl(priv, UMAC_MPD_CTRL);
        if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE))
                reg |= MPD_EN;
        reg &= ~PSW_EN;
-       if (priv->wolopts & WAKE_MAGICSECURE)
+       if (priv->wolopts & WAKE_MAGICSECURE) {
+               /* Program the SecureOn password */
+               umac_writel(priv, get_unaligned_be16(&priv->sopass[0]),
+                           UMAC_PSW_MS);
+               umac_writel(priv, get_unaligned_be32(&priv->sopass[2]),
+                           UMAC_PSW_LS);
                reg |= PSW_EN;
+       }
        umac_writel(priv, reg, UMAC_MPD_CTRL);
 
        if (priv->wolopts & WAKE_FILTER) {
index 0887e63..0b192fe 100644 (file)
@@ -12,6 +12,7 @@
 #define __BCM_SYSPORT_H
 
 #include <linux/bitmap.h>
+#include <linux/ethtool.h>
 #include <linux/if_vlan.h>
 #include <linux/net_dim.h>
 
@@ -778,6 +779,7 @@ struct bcm_sysport_priv {
        unsigned int            crc_fwd:1;
        u16                     rev;
        u32                     wolopts;
+       u8                      sopass[SOPASS_MAX];
        unsigned int            wol_irq_disabled:1;
 
        /* MIB related fields */
index cabc8e4..2d3a44c 100644 (file)
@@ -634,9 +634,9 @@ static int bgmac_dma_alloc(struct bgmac *bgmac)
 
                /* Alloc ring of descriptors */
                size = BGMAC_TX_RING_SLOTS * sizeof(struct bgmac_dma_desc);
-               ring->cpu_base = dma_zalloc_coherent(dma_dev, size,
-                                                    &ring->dma_base,
-                                                    GFP_KERNEL);
+               ring->cpu_base = dma_alloc_coherent(dma_dev, size,
+                                                   &ring->dma_base,
+                                                   GFP_KERNEL);
                if (!ring->cpu_base) {
                        dev_err(bgmac->dev, "Allocation of TX ring 0x%X failed\n",
                                ring->mmio_base);
@@ -659,9 +659,9 @@ static int bgmac_dma_alloc(struct bgmac *bgmac)
 
                /* Alloc ring of descriptors */
                size = BGMAC_RX_RING_SLOTS * sizeof(struct bgmac_dma_desc);
-               ring->cpu_base = dma_zalloc_coherent(dma_dev, size,
-                                                    &ring->dma_base,
-                                                    GFP_KERNEL);
+               ring->cpu_base = dma_alloc_coherent(dma_dev, size,
+                                                   &ring->dma_base,
+                                                   GFP_KERNEL);
                if (!ring->cpu_base) {
                        dev_err(bgmac->dev, "Allocation of RX ring 0x%X failed\n",
                                ring->mmio_base);
index bbb2471..d63371d 100644 (file)
@@ -844,8 +844,8 @@ bnx2_alloc_stats_blk(struct net_device *dev)
                                                 BNX2_SBLK_MSIX_ALIGN_SIZE);
        bp->status_stats_size = status_blk_size +
                                sizeof(struct statistics_block);
-       status_blk = dma_zalloc_coherent(&bp->pdev->dev, bp->status_stats_size,
-                                        &bp->status_blk_mapping, GFP_KERNEL);
+       status_blk = dma_alloc_coherent(&bp->pdev->dev, bp->status_stats_size,
+                                       &bp->status_blk_mapping, GFP_KERNEL);
        if (!status_blk)
                return -ENOMEM;
 
index 5cd3135..03d131f 100644 (file)
@@ -2081,7 +2081,7 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id,
                            bool is_pf);
 
 #define BNX2X_ILT_ZALLOC(x, y, size)                                   \
-       x = dma_zalloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL)
+       x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL)
 
 #define BNX2X_ILT_FREE(x, y, size) \
        do { \
index 142bc11..2462e7a 100644 (file)
@@ -52,7 +52,7 @@ extern int bnx2x_num_queues;
 
 #define BNX2X_PCI_ALLOC(y, size)                                       \
 ({                                                                     \
-       void *x = dma_zalloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
+       void *x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
        if (x)                                                          \
                DP(NETIF_MSG_HW,                                        \
                   "BNX2X_PCI_ALLOC: Physical %Lx Virtual %p\n",        \
index 3aa80da..8bc7e49 100644 (file)
@@ -3449,10 +3449,10 @@ alloc_ext_stats:
                        goto alloc_tx_ext_stats;
 
                bp->hw_rx_port_stats_ext =
-                       dma_zalloc_coherent(&pdev->dev,
-                                           sizeof(struct rx_port_stats_ext),
-                                           &bp->hw_rx_port_stats_ext_map,
-                                           GFP_KERNEL);
+                       dma_alloc_coherent(&pdev->dev,
+                                          sizeof(struct rx_port_stats_ext),
+                                          &bp->hw_rx_port_stats_ext_map,
+                                          GFP_KERNEL);
                if (!bp->hw_rx_port_stats_ext)
                        return 0;
 
@@ -3462,10 +3462,10 @@ alloc_tx_ext_stats:
 
                if (bp->hwrm_spec_code >= 0x10902) {
                        bp->hw_tx_port_stats_ext =
-                               dma_zalloc_coherent(&pdev->dev,
-                                           sizeof(struct tx_port_stats_ext),
-                                           &bp->hw_tx_port_stats_ext_map,
-                                           GFP_KERNEL);
+                               dma_alloc_coherent(&pdev->dev,
+                                                  sizeof(struct tx_port_stats_ext),
+                                                  &bp->hw_tx_port_stats_ext_map,
+                                                  GFP_KERNEL);
                }
                bp->flags |= BNXT_FLAG_PORT_STATS_EXT;
        }
@@ -4973,12 +4973,18 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
                struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
                struct bnxt_ring_struct *ring = &cpr->cp_ring_struct;
                u32 map_idx = ring->map_idx;
+               unsigned int vector;
 
+               vector = bp->irq_tbl[map_idx].vector;
+               disable_irq_nosync(vector);
                rc = hwrm_ring_alloc_send_msg(bp, ring, type, map_idx);
-               if (rc)
+               if (rc) {
+                       enable_irq(vector);
                        goto err_out;
+               }
                bnxt_set_db(bp, &cpr->cp_db, type, map_idx, ring->fw_ring_id);
                bnxt_db_nq(bp, &cpr->cp_db, cpr->cp_raw_cons);
+               enable_irq(vector);
                bp->grp_info[i].cp_fw_ring_id = ring->fw_ring_id;
 
                if (!i) {
@@ -5601,7 +5607,8 @@ static int bnxt_hwrm_check_pf_rings(struct bnxt *bp, int tx_rings, int rx_rings,
                         FUNC_CFG_REQ_FLAGS_STAT_CTX_ASSETS_TEST |
                         FUNC_CFG_REQ_FLAGS_VNIC_ASSETS_TEST;
                if (bp->flags & BNXT_FLAG_CHIP_P5)
-                       flags |= FUNC_CFG_REQ_FLAGS_RSSCOS_CTX_ASSETS_TEST;
+                       flags |= FUNC_CFG_REQ_FLAGS_RSSCOS_CTX_ASSETS_TEST |
+                                FUNC_CFG_REQ_FLAGS_NQ_ASSETS_TEST;
                else
                        flags |= FUNC_CFG_REQ_FLAGS_RING_GRP_ASSETS_TEST;
        }
@@ -6221,9 +6228,12 @@ static int bnxt_alloc_ctx_pg_tbls(struct bnxt *bp,
                        rmem->pg_tbl_map = ctx_pg->ctx_dma_arr[i];
                        rmem->depth = 1;
                        rmem->nr_pages = MAX_CTX_PAGES;
-                       if (i == (nr_tbls - 1))
-                               rmem->nr_pages = ctx_pg->nr_pages %
-                                                MAX_CTX_PAGES;
+                       if (i == (nr_tbls - 1)) {
+                               int rem = ctx_pg->nr_pages % MAX_CTX_PAGES;
+
+                               if (rem)
+                                       rmem->nr_pages = rem;
+                       }
                        rc = bnxt_alloc_ctx_mem_blk(bp, pg_tbl);
                        if (rc)
                                break;
index 15c7041..7077515 100644 (file)
@@ -316,8 +316,8 @@ static int bnxt_hwrm_set_dcbx_app(struct bnxt *bp, struct dcb_app *app,
 
        n = IEEE_8021QAZ_MAX_TCS;
        data_len = sizeof(*data) + sizeof(*fw_app) * n;
-       data = dma_zalloc_coherent(&bp->pdev->dev, data_len, &mapping,
-                                  GFP_KERNEL);
+       data = dma_alloc_coherent(&bp->pdev->dev, data_len, &mapping,
+                                 GFP_KERNEL);
        if (!data)
                return -ENOMEM;
 
index 140dbd6..7f56032 100644 (file)
@@ -85,8 +85,8 @@ static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
                return -EFAULT;
        }
 
-       data_addr = dma_zalloc_coherent(&bp->pdev->dev, bytesize,
-                                       &data_dma_addr, GFP_KERNEL);
+       data_addr = dma_alloc_coherent(&bp->pdev->dev, bytesize,
+                                      &data_dma_addr, GFP_KERNEL);
        if (!data_addr)
                return -ENOMEM;
 
index f1aaac8..0a09958 100644 (file)
@@ -386,8 +386,8 @@ struct hwrm_err_output {
 #define HWRM_VERSION_MAJOR 1
 #define HWRM_VERSION_MINOR 10
 #define HWRM_VERSION_UPDATE 0
-#define HWRM_VERSION_RSVD 33
-#define HWRM_VERSION_STR "1.10.0.33"
+#define HWRM_VERSION_RSVD 35
+#define HWRM_VERSION_STR "1.10.0.35"
 
 /* hwrm_ver_get_input (size:192b/24B) */
 struct hwrm_ver_get_input {
@@ -1184,6 +1184,7 @@ struct hwrm_func_cfg_input {
        #define FUNC_CFG_REQ_FLAGS_L2_CTX_ASSETS_TEST             0x100000UL
        #define FUNC_CFG_REQ_FLAGS_TRUSTED_VF_ENABLE              0x200000UL
        #define FUNC_CFG_REQ_FLAGS_DYNAMIC_TX_RING_ALLOC          0x400000UL
+       #define FUNC_CFG_REQ_FLAGS_NQ_ASSETS_TEST                 0x800000UL
        __le32  enables;
        #define FUNC_CFG_REQ_ENABLES_MTU                     0x1UL
        #define FUNC_CFG_REQ_ENABLES_MRU                     0x2UL
index 5db9f41..134ae28 100644 (file)
@@ -1288,7 +1288,7 @@ static void sbdma_tx_process(struct sbmac_softc *sc, struct sbmacdma *d,
                 * for transmits, we just free buffers.
                 */
 
-               dev_kfree_skb_irq(sb);
+               dev_consume_skb_irq(sb);
 
                /*
                 * .. and advance to the next buffer.
index 3b1397a..b1627dd 100644 (file)
@@ -8712,10 +8712,10 @@ static int tg3_mem_rx_acquire(struct tg3 *tp)
                if (!i && tg3_flag(tp, ENABLE_RSS))
                        continue;
 
-               tnapi->rx_rcb = dma_zalloc_coherent(&tp->pdev->dev,
-                                                   TG3_RX_RCB_RING_BYTES(tp),
-                                                   &tnapi->rx_rcb_mapping,
-                                                   GFP_KERNEL);
+               tnapi->rx_rcb = dma_alloc_coherent(&tp->pdev->dev,
+                                                  TG3_RX_RCB_RING_BYTES(tp),
+                                                  &tnapi->rx_rcb_mapping,
+                                                  GFP_KERNEL);
                if (!tnapi->rx_rcb)
                        goto err_out;
        }
@@ -8768,9 +8768,9 @@ static int tg3_alloc_consistent(struct tg3 *tp)
 {
        int i;
 
-       tp->hw_stats = dma_zalloc_coherent(&tp->pdev->dev,
-                                          sizeof(struct tg3_hw_stats),
-                                          &tp->stats_mapping, GFP_KERNEL);
+       tp->hw_stats = dma_alloc_coherent(&tp->pdev->dev,
+                                         sizeof(struct tg3_hw_stats),
+                                         &tp->stats_mapping, GFP_KERNEL);
        if (!tp->hw_stats)
                goto err_out;
 
@@ -8778,10 +8778,10 @@ static int tg3_alloc_consistent(struct tg3 *tp)
                struct tg3_napi *tnapi = &tp->napi[i];
                struct tg3_hw_status *sblk;
 
-               tnapi->hw_status = dma_zalloc_coherent(&tp->pdev->dev,
-                                                      TG3_HW_STATUS_SIZE,
-                                                      &tnapi->status_mapping,
-                                                      GFP_KERNEL);
+               tnapi->hw_status = dma_alloc_coherent(&tp->pdev->dev,
+                                                     TG3_HW_STATUS_SIZE,
+                                                     &tnapi->status_mapping,
+                                                     GFP_KERNEL);
                if (!tnapi->hw_status)
                        goto err_out;
 
index 3d45f4c..9bbaad9 100644 (file)
 #define MACB_CAPS_JUMBO                                0x00000020
 #define MACB_CAPS_GEM_HAS_PTP                  0x00000040
 #define MACB_CAPS_BD_RD_PREFETCH               0x00000080
+#define MACB_CAPS_NEEDS_RSTONUBR               0x00000100
 #define MACB_CAPS_FIFO_MODE                    0x10000000
 #define MACB_CAPS_GIGABIT_MODE_AVAILABLE       0x20000000
 #define MACB_CAPS_SG_DISABLED                  0x40000000
@@ -1214,6 +1215,8 @@ struct macb {
 
        int     rx_bd_rd_prefetch;
        int     tx_bd_rd_prefetch;
+
+       u32     rx_intr_mask;
 };
 
 #ifdef CONFIG_MACB_USE_HWSTAMP
index b126926..2b28826 100644 (file)
@@ -56,8 +56,7 @@
 /* level of occupied TX descriptors under which we wake up TX process */
 #define MACB_TX_WAKEUP_THRESH(bp)      (3 * (bp)->tx_ring_size / 4)
 
-#define MACB_RX_INT_FLAGS      (MACB_BIT(RCOMP) | MACB_BIT(RXUBR)      \
-                                | MACB_BIT(ISR_ROVR))
+#define MACB_RX_INT_FLAGS      (MACB_BIT(RCOMP) | MACB_BIT(ISR_ROVR))
 #define MACB_TX_ERR_FLAGS      (MACB_BIT(ISR_TUND)                     \
                                        | MACB_BIT(ISR_RLE)             \
                                        | MACB_BIT(TXERR))
@@ -1270,7 +1269,7 @@ static int macb_poll(struct napi_struct *napi, int budget)
                                queue_writel(queue, ISR, MACB_BIT(RCOMP));
                        napi_reschedule(napi);
                } else {
-                       queue_writel(queue, IER, MACB_RX_INT_FLAGS);
+                       queue_writel(queue, IER, bp->rx_intr_mask);
                }
        }
 
@@ -1288,7 +1287,7 @@ static void macb_hresp_error_task(unsigned long data)
        u32 ctrl;
 
        for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
-               queue_writel(queue, IDR, MACB_RX_INT_FLAGS |
+               queue_writel(queue, IDR, bp->rx_intr_mask |
                                         MACB_TX_INT_FLAGS |
                                         MACB_BIT(HRESP));
        }
@@ -1318,7 +1317,7 @@ static void macb_hresp_error_task(unsigned long data)
 
                /* Enable interrupts */
                queue_writel(queue, IER,
-                            MACB_RX_INT_FLAGS |
+                            bp->rx_intr_mask |
                             MACB_TX_INT_FLAGS |
                             MACB_BIT(HRESP));
        }
@@ -1372,14 +1371,14 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
                            (unsigned int)(queue - bp->queues),
                            (unsigned long)status);
 
-               if (status & MACB_RX_INT_FLAGS) {
+               if (status & bp->rx_intr_mask) {
                        /* There's no point taking any more interrupts
                         * until we have processed the buffers. The
                         * scheduling call may fail if the poll routine
                         * is already scheduled, so disable interrupts
                         * now.
                         */
-                       queue_writel(queue, IDR, MACB_RX_INT_FLAGS);
+                       queue_writel(queue, IDR, bp->rx_intr_mask);
                        if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
                                queue_writel(queue, ISR, MACB_BIT(RCOMP));
 
@@ -1412,8 +1411,9 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
                /* There is a hardware issue under heavy load where DMA can
                 * stop, this causes endless "used buffer descriptor read"
                 * interrupts but it can be cleared by re-enabling RX. See
-                * the at91 manual, section 41.3.1 or the Zynq manual
-                * section 16.7.4 for details.
+                * the at91rm9200 manual, section 41.3.1 or the Zynq manual
+                * section 16.7.4 for details. RXUBR is only enabled for
+                * these two versions.
                 */
                if (status & MACB_BIT(RXUBR)) {
                        ctrl = macb_readl(bp, NCR);
@@ -1738,12 +1738,8 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
                *skb = nskb;
        }
 
-       if (padlen) {
-               if (padlen >= ETH_FCS_LEN)
-                       skb_put_zero(*skb, padlen - ETH_FCS_LEN);
-               else
-                       skb_trim(*skb, ETH_FCS_LEN - padlen);
-       }
+       if (padlen > ETH_FCS_LEN)
+               skb_put_zero(*skb, padlen - ETH_FCS_LEN);
 
 add_fcs:
        /* set FCS to packet */
@@ -2263,7 +2259,7 @@ static void macb_init_hw(struct macb *bp)
 
                /* Enable interrupts */
                queue_writel(queue, IER,
-                            MACB_RX_INT_FLAGS |
+                            bp->rx_intr_mask |
                             MACB_TX_INT_FLAGS |
                             MACB_BIT(HRESP));
        }
@@ -3911,6 +3907,7 @@ static const struct macb_config sama5d4_config = {
 };
 
 static const struct macb_config emac_config = {
+       .caps = MACB_CAPS_NEEDS_RSTONUBR,
        .clk_init = at91ether_clk_init,
        .init = at91ether_init,
 };
@@ -3932,7 +3929,8 @@ static const struct macb_config zynqmp_config = {
 };
 
 static const struct macb_config zynq_config = {
-       .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_NO_GIGABIT_HALF,
+       .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_NO_GIGABIT_HALF |
+               MACB_CAPS_NEEDS_RSTONUBR,
        .dma_burst_length = 16,
        .clk_init = macb_clk_init,
        .init = macb_init,
@@ -4087,6 +4085,10 @@ static int macb_probe(struct platform_device *pdev)
                                                macb_dma_desc_get_size(bp);
        }
 
+       bp->rx_intr_mask = MACB_RX_INT_FLAGS;
+       if (bp->caps & MACB_CAPS_NEEDS_RSTONUBR)
+               bp->rx_intr_mask |= MACB_BIT(RXUBR);
+
        mac = of_get_mac_address(np);
        if (mac) {
                ether_addr_copy(bp->dev->dev_addr, mac);
index 5f03199..05f4a3b 100644 (file)
@@ -54,7 +54,6 @@ config CAVIUM_PTP
        tristate "Cavium PTP coprocessor as PTP clock"
        depends on 64BIT && PCI
        imply PTP_1588_CLOCK
-       default y
        ---help---
          This driver adds support for the Precision Time Protocol Clocks and
          Timestamping coprocessor (PTP) found on Cavium processors.
index fcaf18f..5b4d3ba 100644 (file)
@@ -59,7 +59,7 @@ static int nicvf_alloc_q_desc_mem(struct nicvf *nic, struct q_desc_mem *dmem,
        dmem->q_len = q_len;
        dmem->size = (desc_size * q_len) + align_bytes;
        /* Save address, need it while freeing */
-       dmem->unalign_base = dma_zalloc_coherent(&nic->pdev->dev, dmem->size,
+       dmem->unalign_base = dma_alloc_coherent(&nic->pdev->dev, dmem->size,
                                                &dmem->dma, GFP_KERNEL);
        if (!dmem->unalign_base)
                return -ENOMEM;
index 20b6e1b..89db739 100644 (file)
@@ -620,7 +620,7 @@ static void *alloc_ring(struct pci_dev *pdev, size_t nelem, size_t elem_size,
 {
        size_t len = nelem * elem_size;
        void *s = NULL;
-       void *p = dma_zalloc_coherent(&pdev->dev, len, phys, GFP_KERNEL);
+       void *p = dma_alloc_coherent(&pdev->dev, len, phys, GFP_KERNEL);
 
        if (!p)
                return NULL;
@@ -2381,7 +2381,7 @@ no_mem:
                                        lro_add_page(adap, qs, fl,
                                                     G_RSPD_LEN(len),
                                                     flags & F_RSPD_EOP);
-                                        goto next_fl;
+                                       goto next_fl;
                                }
 
                                skb = get_packet_pg(adap, fl, q,
@@ -3214,11 +3214,13 @@ void t3_start_sge_timers(struct adapter *adap)
        for (i = 0; i < SGE_QSETS; ++i) {
                struct sge_qset *q = &adap->sge.qs[i];
 
-       if (q->tx_reclaim_timer.function)
-               mod_timer(&q->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD);
+               if (q->tx_reclaim_timer.function)
+                       mod_timer(&q->tx_reclaim_timer,
+                                 jiffies + TX_RECLAIM_PERIOD);
 
-       if (q->rx_reclaim_timer.function)
-               mod_timer(&q->rx_reclaim_timer, jiffies + RX_RECLAIM_PERIOD);
+               if (q->rx_reclaim_timer.function)
+                       mod_timer(&q->rx_reclaim_timer,
+                                 jiffies + RX_RECLAIM_PERIOD);
        }
 }
 
index 080918a..0a9f2c5 100644 (file)
@@ -1082,7 +1082,7 @@ int t3_check_fw_version(struct adapter *adapter)
                CH_WARN(adapter, "found newer FW version(%u.%u), "
                        "driver compiled for version %u.%u\n", major, minor,
                        FW_VERSION_MAJOR, FW_VERSION_MINOR);
-                       return 0;
+               return 0;
        }
        return -EINVAL;
 }
@@ -3619,7 +3619,7 @@ int t3_reset_adapter(struct adapter *adapter)
 
 static int init_parity(struct adapter *adap)
 {
-               int i, err, addr;
+       int i, err, addr;
 
        if (t3_read_reg(adap, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
                return -EBUSY;
@@ -3806,6 +3806,6 @@ int t3_replay_prep_adapter(struct adapter *adapter)
                p->phy.ops->power_down(&p->phy, 1);
        }
 
-return 0;
+       return 0;
 }
 
index 9f9d6ca..58a039c 100644 (file)
@@ -378,10 +378,10 @@ static void cxgb4_init_ptp_timer(struct adapter *adapter)
        int err;
 
        memset(&c, 0, sizeof(c));
-               c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PTP_CMD) |
-                                            FW_CMD_REQUEST_F |
-                                            FW_CMD_WRITE_F |
-                                            FW_PTP_CMD_PORTID_V(0));
+       c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PTP_CMD) |
+                                    FW_CMD_REQUEST_F |
+                                    FW_CMD_WRITE_F |
+                                    FW_PTP_CMD_PORTID_V(0));
        c.retval_len16 = cpu_to_be32(FW_CMD_LEN16_V(sizeof(c) / 16));
        c.u.scmd.sc = FW_PTP_SC_INIT_TIMER;
 
index 9a6065a..c041f44 100644 (file)
@@ -78,7 +78,7 @@ static void free_msix_idx_in_bmap(struct adapter *adap, unsigned int msix_idx)
        unsigned long flags;
 
        spin_lock_irqsave(&bmap->lock, flags);
-        __clear_bit(msix_idx, bmap->msix_bmap);
+       __clear_bit(msix_idx, bmap->msix_bmap);
        spin_unlock_irqrestore(&bmap->lock, flags);
 }
 
index b901884..fc0bc64 100644 (file)
@@ -694,7 +694,7 @@ static void *alloc_ring(struct device *dev, size_t nelem, size_t elem_size,
 {
        size_t len = nelem * elem_size + stat_size;
        void *s = NULL;
-       void *p = dma_zalloc_coherent(dev, len, phys, GFP_KERNEL);
+       void *p = dma_alloc_coherent(dev, len, phys, GFP_KERNEL);
 
        if (!p)
                return NULL;
index e8c3429..2b03f61 100644 (file)
@@ -3794,7 +3794,7 @@ int t4_load_phy_fw(struct adapter *adap,
        /* If we have version number support, then check to see if the adapter
         * already has up-to-date PHY firmware loaded.
         */
-        if (phy_fw_version) {
+       if (phy_fw_version) {
                new_phy_fw_vers = phy_fw_version(phy_fw_data, phy_fw_size);
                ret = t4_phy_fw_ver(adap, &cur_phy_fw_ver);
                if (ret < 0)
index 3007e1a..1d534f0 100644 (file)
@@ -756,7 +756,7 @@ static void *alloc_ring(struct device *dev, size_t nelem, size_t hwsize,
         * Allocate the hardware ring and PCI DMA bus address space for said.
         */
        size_t hwlen = nelem * hwsize + stat_size;
-       void *hwring = dma_zalloc_coherent(dev, hwlen, busaddrp, GFP_KERNEL);
+       void *hwring = dma_alloc_coherent(dev, hwlen, busaddrp, GFP_KERNEL);
 
        if (!hwring)
                return NULL;
index 60641e2..9a7f70d 100644 (file)
@@ -1434,7 +1434,8 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
                 * csum is correct or is zero.
                 */
                if ((netdev->features & NETIF_F_RXCSUM) && !csum_not_calc &&
-                   tcp_udp_csum_ok && ipv4_csum_ok && outer_csum_ok) {
+                   tcp_udp_csum_ok && outer_csum_ok &&
+                   (ipv4_csum_ok || ipv6)) {
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        skb->csum_level = encap;
                }
index 13430f7..f1a2da1 100644 (file)
@@ -585,7 +585,7 @@ static void de_tx (struct de_private *de)
                                netif_dbg(de, tx_done, de->dev,
                                          "tx done, slot %d\n", tx_tail);
                        }
-                       dev_kfree_skb_irq(skb);
+                       dev_consume_skb_irq(skb);
                }
 
 next:
index 1e9d882..59a7f0b 100644 (file)
@@ -1808,9 +1808,9 @@ int be_cmd_get_fat_dump(struct be_adapter *adapter, u32 buf_len, void *buf)
        total_size = buf_len;
 
        get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + 60*1024;
-       get_fat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
-                                            get_fat_cmd.size,
-                                            &get_fat_cmd.dma, GFP_ATOMIC);
+       get_fat_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+                                           get_fat_cmd.size,
+                                           &get_fat_cmd.dma, GFP_ATOMIC);
        if (!get_fat_cmd.va)
                return -ENOMEM;
 
@@ -2302,8 +2302,8 @@ int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
                return -EINVAL;
 
        cmd.size = sizeof(struct be_cmd_resp_port_type);
-       cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
-                                    GFP_ATOMIC);
+       cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+                                   GFP_ATOMIC);
        if (!cmd.va) {
                dev_err(&adapter->pdev->dev, "Memory allocation failed\n");
                return -ENOMEM;
@@ -3066,8 +3066,8 @@ int lancer_fw_download(struct be_adapter *adapter,
 
        flash_cmd.size = sizeof(struct lancer_cmd_req_write_object)
                                + LANCER_FW_DOWNLOAD_CHUNK;
-       flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size,
-                                          &flash_cmd.dma, GFP_KERNEL);
+       flash_cmd.va = dma_alloc_coherent(dev, flash_cmd.size, &flash_cmd.dma,
+                                         GFP_KERNEL);
        if (!flash_cmd.va)
                return -ENOMEM;
 
@@ -3184,8 +3184,8 @@ int be_fw_download(struct be_adapter *adapter, const struct firmware *fw)
        }
 
        flash_cmd.size = sizeof(struct be_cmd_write_flashrom);
-       flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size, &flash_cmd.dma,
-                                          GFP_KERNEL);
+       flash_cmd.va = dma_alloc_coherent(dev, flash_cmd.size, &flash_cmd.dma,
+                                         GFP_KERNEL);
        if (!flash_cmd.va)
                return -ENOMEM;
 
@@ -3435,8 +3435,8 @@ int be_cmd_get_phy_info(struct be_adapter *adapter)
                goto err;
        }
        cmd.size = sizeof(struct be_cmd_req_get_phy_info);
-       cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
-                                    GFP_ATOMIC);
+       cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+                                   GFP_ATOMIC);
        if (!cmd.va) {
                dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
                status = -ENOMEM;
@@ -3522,9 +3522,9 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter)
 
        memset(&attribs_cmd, 0, sizeof(struct be_dma_mem));
        attribs_cmd.size = sizeof(struct be_cmd_resp_cntl_attribs);
-       attribs_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
-                                            attribs_cmd.size,
-                                            &attribs_cmd.dma, GFP_ATOMIC);
+       attribs_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+                                           attribs_cmd.size,
+                                           &attribs_cmd.dma, GFP_ATOMIC);
        if (!attribs_cmd.va) {
                dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
                status = -ENOMEM;
@@ -3699,10 +3699,10 @@ int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
 
        memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem));
        get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list);
-       get_mac_list_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
-                                                 get_mac_list_cmd.size,
-                                                 &get_mac_list_cmd.dma,
-                                                 GFP_ATOMIC);
+       get_mac_list_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+                                                get_mac_list_cmd.size,
+                                                &get_mac_list_cmd.dma,
+                                                GFP_ATOMIC);
 
        if (!get_mac_list_cmd.va) {
                dev_err(&adapter->pdev->dev,
@@ -3829,8 +3829,8 @@ int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
 
        memset(&cmd, 0, sizeof(struct be_dma_mem));
        cmd.size = sizeof(struct be_cmd_req_set_mac_list);
-       cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
-                                    GFP_KERNEL);
+       cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+                                   GFP_KERNEL);
        if (!cmd.va)
                return -ENOMEM;
 
@@ -4035,8 +4035,8 @@ int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
 
        memset(&cmd, 0, sizeof(struct be_dma_mem));
        cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1);
-       cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
-                                    GFP_ATOMIC);
+       cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+                                   GFP_ATOMIC);
        if (!cmd.va) {
                dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
                status = -ENOMEM;
@@ -4089,9 +4089,9 @@ int be_cmd_set_fw_log_level(struct be_adapter *adapter, u32 level)
 
        memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
        extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
-       extfat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
-                                           extfat_cmd.size, &extfat_cmd.dma,
-                                           GFP_ATOMIC);
+       extfat_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+                                          extfat_cmd.size, &extfat_cmd.dma,
+                                          GFP_ATOMIC);
        if (!extfat_cmd.va)
                return -ENOMEM;
 
@@ -4127,9 +4127,9 @@ int be_cmd_get_fw_log_level(struct be_adapter *adapter)
 
        memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
        extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
-       extfat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
-                                           extfat_cmd.size, &extfat_cmd.dma,
-                                           GFP_ATOMIC);
+       extfat_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+                                          extfat_cmd.size, &extfat_cmd.dma,
+                                          GFP_ATOMIC);
 
        if (!extfat_cmd.va) {
                dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n",
@@ -4354,8 +4354,8 @@ int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res)
 
        memset(&cmd, 0, sizeof(struct be_dma_mem));
        cmd.size = sizeof(struct be_cmd_resp_get_func_config);
-       cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
-                                    GFP_ATOMIC);
+       cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+                                   GFP_ATOMIC);
        if (!cmd.va) {
                dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
                status = -ENOMEM;
@@ -4452,8 +4452,8 @@ int be_cmd_get_profile_config(struct be_adapter *adapter,
 
        memset(&cmd, 0, sizeof(struct be_dma_mem));
        cmd.size = sizeof(struct be_cmd_resp_get_profile_config);
-       cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
-                                    GFP_ATOMIC);
+       cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+                                   GFP_ATOMIC);
        if (!cmd.va)
                return -ENOMEM;
 
@@ -4539,8 +4539,8 @@ static int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc,
 
        memset(&cmd, 0, sizeof(struct be_dma_mem));
        cmd.size = sizeof(struct be_cmd_req_set_profile_config);
-       cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
-                                    GFP_ATOMIC);
+       cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+                                   GFP_ATOMIC);
        if (!cmd.va)
                return -ENOMEM;
 
index 3f6749f..4c21834 100644 (file)
@@ -274,8 +274,8 @@ static int lancer_cmd_read_file(struct be_adapter *adapter, u8 *file_name,
        int status = 0;
 
        read_cmd.size = LANCER_READ_FILE_CHUNK;
-       read_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, read_cmd.size,
-                                         &read_cmd.dma, GFP_ATOMIC);
+       read_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, read_cmd.size,
+                                        &read_cmd.dma, GFP_ATOMIC);
 
        if (!read_cmd.va) {
                dev_err(&adapter->pdev->dev,
@@ -815,7 +815,7 @@ static int be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
        }
 
        cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config);
-       cmd.va = dma_zalloc_coherent(dev, cmd.size, &cmd.dma, GFP_KERNEL);
+       cmd.va = dma_alloc_coherent(dev, cmd.size, &cmd.dma, GFP_KERNEL);
        if (!cmd.va)
                return -ENOMEM;
 
@@ -851,9 +851,9 @@ static int be_test_ddr_dma(struct be_adapter *adapter)
        };
 
        ddrdma_cmd.size = sizeof(struct be_cmd_req_ddrdma_test);
-       ddrdma_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
-                                           ddrdma_cmd.size, &ddrdma_cmd.dma,
-                                           GFP_KERNEL);
+       ddrdma_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+                                          ddrdma_cmd.size, &ddrdma_cmd.dma,
+                                          GFP_KERNEL);
        if (!ddrdma_cmd.va)
                return -ENOMEM;
 
@@ -1014,9 +1014,9 @@ static int be_read_eeprom(struct net_device *netdev,
 
        memset(&eeprom_cmd, 0, sizeof(struct be_dma_mem));
        eeprom_cmd.size = sizeof(struct be_cmd_req_seeprom_read);
-       eeprom_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
-                                           eeprom_cmd.size, &eeprom_cmd.dma,
-                                           GFP_KERNEL);
+       eeprom_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+                                          eeprom_cmd.size, &eeprom_cmd.dma,
+                                          GFP_KERNEL);
 
        if (!eeprom_cmd.va)
                return -ENOMEM;
index 852f5bf..d502690 100644 (file)
@@ -167,8 +167,8 @@ static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q,
        q->len = len;
        q->entry_size = entry_size;
        mem->size = len * entry_size;
-       mem->va = dma_zalloc_coherent(&adapter->pdev->dev, mem->size, &mem->dma,
-                                     GFP_KERNEL);
+       mem->va = dma_alloc_coherent(&adapter->pdev->dev, mem->size,
+                                    &mem->dma, GFP_KERNEL);
        if (!mem->va)
                return -ENOMEM;
        return 0;
@@ -5766,9 +5766,9 @@ static int be_drv_init(struct be_adapter *adapter)
        int status = 0;
 
        mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16;
-       mbox_mem_alloc->va = dma_zalloc_coherent(dev, mbox_mem_alloc->size,
-                                                &mbox_mem_alloc->dma,
-                                                GFP_KERNEL);
+       mbox_mem_alloc->va = dma_alloc_coherent(dev, mbox_mem_alloc->size,
+                                               &mbox_mem_alloc->dma,
+                                               GFP_KERNEL);
        if (!mbox_mem_alloc->va)
                return -ENOMEM;
 
@@ -5777,8 +5777,8 @@ static int be_drv_init(struct be_adapter *adapter)
        mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16);
 
        rx_filter->size = sizeof(struct be_cmd_req_rx_filter);
-       rx_filter->va = dma_zalloc_coherent(dev, rx_filter->size,
-                                           &rx_filter->dma, GFP_KERNEL);
+       rx_filter->va = dma_alloc_coherent(dev, rx_filter->size,
+                                          &rx_filter->dma, GFP_KERNEL);
        if (!rx_filter->va) {
                status = -ENOMEM;
                goto free_mbox;
@@ -5792,8 +5792,8 @@ static int be_drv_init(struct be_adapter *adapter)
                stats_cmd->size = sizeof(struct be_cmd_req_get_stats_v1);
        else
                stats_cmd->size = sizeof(struct be_cmd_req_get_stats_v2);
-       stats_cmd->va = dma_zalloc_coherent(dev, stats_cmd->size,
-                                           &stats_cmd->dma, GFP_KERNEL);
+       stats_cmd->va = dma_alloc_coherent(dev, stats_cmd->size,
+                                          &stats_cmd->dma, GFP_KERNEL);
        if (!stats_cmd->va) {
                status = -ENOMEM;
                goto free_rx_filter;
index 4d67322..3e5e971 100644 (file)
@@ -935,16 +935,14 @@ static int ftgmac100_alloc_rings(struct ftgmac100 *priv)
                return -ENOMEM;
 
        /* Allocate descriptors */
-       priv->rxdes = dma_zalloc_coherent(priv->dev,
-                                         MAX_RX_QUEUE_ENTRIES *
-                                         sizeof(struct ftgmac100_rxdes),
-                                         &priv->rxdes_dma, GFP_KERNEL);
+       priv->rxdes = dma_alloc_coherent(priv->dev,
+                                        MAX_RX_QUEUE_ENTRIES * sizeof(struct ftgmac100_rxdes),
+                                        &priv->rxdes_dma, GFP_KERNEL);
        if (!priv->rxdes)
                return -ENOMEM;
-       priv->txdes = dma_zalloc_coherent(priv->dev,
-                                         MAX_TX_QUEUE_ENTRIES *
-                                         sizeof(struct ftgmac100_txdes),
-                                         &priv->txdes_dma, GFP_KERNEL);
+       priv->txdes = dma_alloc_coherent(priv->dev,
+                                        MAX_TX_QUEUE_ENTRIES * sizeof(struct ftgmac100_txdes),
+                                        &priv->txdes_dma, GFP_KERNEL);
        if (!priv->txdes)
                return -ENOMEM;
 
index 084f24d..2a0e820 100644 (file)
@@ -734,10 +734,9 @@ static int ftmac100_alloc_buffers(struct ftmac100 *priv)
 {
        int i;
 
-       priv->descs = dma_zalloc_coherent(priv->dev,
-                                         sizeof(struct ftmac100_descs),
-                                         &priv->descs_dma_addr,
-                                         GFP_KERNEL);
+       priv->descs = dma_alloc_coherent(priv->dev,
+                                        sizeof(struct ftmac100_descs),
+                                        &priv->descs_dma_addr, GFP_KERNEL);
        if (!priv->descs)
                return -ENOMEM;
 
index f53090c..dfebc30 100644 (file)
@@ -2051,6 +2051,7 @@ dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
        bool nonlinear = skb_is_nonlinear(skb);
        struct rtnl_link_stats64 *percpu_stats;
        struct dpaa_percpu_priv *percpu_priv;
+       struct netdev_queue *txq;
        struct dpaa_priv *priv;
        struct qm_fd fd;
        int offset = 0;
@@ -2100,6 +2101,11 @@ dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
        if (unlikely(err < 0))
                goto skb_to_fd_failed;
 
+       txq = netdev_get_tx_queue(net_dev, queue_mapping);
+
+       /* LLTX requires to do our own update of trans_start */
+       txq->trans_start = jiffies;
+
        if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
                fd.cmd |= cpu_to_be32(FM_FD_CMD_UPD);
                skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
index 809a155..f6d244c 100644 (file)
@@ -9,8 +9,9 @@ config FSL_DPAA2_ETH
 
 config FSL_DPAA2_PTP_CLOCK
        tristate "Freescale DPAA2 PTP Clock"
-       depends on FSL_DPAA2_ETH && POSIX_TIMERS
-       select PTP_1588_CLOCK
+       depends on FSL_DPAA2_ETH
+       imply PTP_1588_CLOCK
+       default y
        help
          This driver adds support for using the DPAA2 1588 timer module
          as a PTP clock.
index ae0f88b..697c242 100644 (file)
@@ -2098,6 +2098,7 @@ static int fec_enet_get_regs_len(struct net_device *ndev)
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
        defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \
        defined(CONFIG_ARM64) || defined(CONFIG_COMPILE_TEST)
+static __u32 fec_enet_register_version = 2;
 static u32 fec_enet_register_offset[] = {
        FEC_IEVENT, FEC_IMASK, FEC_R_DES_ACTIVE_0, FEC_X_DES_ACTIVE_0,
        FEC_ECNTRL, FEC_MII_DATA, FEC_MII_SPEED, FEC_MIB_CTRLSTAT, FEC_R_CNTRL,
@@ -2128,6 +2129,7 @@ static u32 fec_enet_register_offset[] = {
        IEEE_R_FDXFC, IEEE_R_OCTETS_OK
 };
 #else
+static __u32 fec_enet_register_version = 1;
 static u32 fec_enet_register_offset[] = {
        FEC_ECNTRL, FEC_IEVENT, FEC_IMASK, FEC_IVEC, FEC_R_DES_ACTIVE_0,
        FEC_R_DES_ACTIVE_1, FEC_R_DES_ACTIVE_2, FEC_X_DES_ACTIVE_0,
@@ -2149,6 +2151,8 @@ static void fec_enet_get_regs(struct net_device *ndev,
        u32 *buf = (u32 *)regbuf;
        u32 i, off;
 
+       regs->version = fec_enet_register_version;
+
        memset(buf, 0, regs->len);
 
        for (i = 0; i < ARRAY_SIZE(fec_enet_register_offset); i++) {
@@ -3467,7 +3471,7 @@ fec_probe(struct platform_device *pdev)
        if (ret)
                goto failed_clk_ipg;
 
-       fep->reg_phy = devm_regulator_get(&pdev->dev, "phy");
+       fep->reg_phy = devm_regulator_get_optional(&pdev->dev, "phy");
        if (!IS_ERR(fep->reg_phy)) {
                ret = regulator_enable(fep->reg_phy);
                if (ret) {
index b90bab7..c1968b3 100644 (file)
@@ -369,7 +369,7 @@ static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id)
                dma_unmap_single(dev->dev.parent, bd->skb_pa, skb->len,
                                 DMA_TO_DEVICE);
 
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
        }
        spin_unlock(&priv->lock);
 
index c3d539e..eb3e65e 100644 (file)
@@ -1879,6 +1879,8 @@ static void ucc_geth_free_tx(struct ucc_geth_private *ugeth)
        u16 i, j;
        u8 __iomem *bd;
 
+       netdev_reset_queue(ugeth->ndev);
+
        ug_info = ugeth->ug_info;
        uf_info = &ug_info->uf_info;
 
index 471805e..e5d853b 100644 (file)
@@ -1006,8 +1006,8 @@ static int hix5hd2_init_hw_desc_queue(struct hix5hd2_priv *priv)
 
        for (i = 0; i < QUEUE_NUMS; i++) {
                size = priv->pool[i].count * sizeof(struct hix5hd2_desc);
-               virt_addr = dma_zalloc_coherent(dev, size, &phys_addr,
-                                               GFP_KERNEL);
+               virt_addr = dma_alloc_coherent(dev, size, &phys_addr,
+                                              GFP_KERNEL);
                if (virt_addr == NULL)
                        goto error_free_pool;
 
index ad1779f..a78bfaf 100644 (file)
@@ -147,12 +147,10 @@ static void hns_ae_put_handle(struct hnae_handle *handle)
        struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle);
        int i;
 
-       vf_cb->mac_cb    = NULL;
-
-       kfree(vf_cb);
-
        for (i = 0; i < handle->q_num; i++)
                hns_ae_get_ring_pair(handle->qs[i])->used_by_vf = 0;
+
+       kfree(vf_cb);
 }
 
 static int hns_ae_wait_flow_down(struct hnae_handle *handle)
index 3b9e74b..b8155f5 100644 (file)
@@ -3081,6 +3081,7 @@ int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset)
        dsaf_dev = dev_get_drvdata(&pdev->dev);
        if (!dsaf_dev) {
                dev_err(&pdev->dev, "dsaf_dev is NULL\n");
+               put_device(&pdev->dev);
                return -ENODEV;
        }
 
@@ -3088,6 +3089,7 @@ int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset)
        if (AE_IS_VER1(dsaf_dev->dsaf_ver)) {
                dev_err(dsaf_dev->dev, "%s v1 chip doesn't support RoCE!\n",
                        dsaf_dev->ae_dev.name);
+               put_device(&pdev->dev);
                return -ENODEV;
        }
 
index 5748d3f..60e7d7a 100644 (file)
@@ -1170,6 +1170,13 @@ int hns_nic_init_phy(struct net_device *ndev, struct hnae_handle *h)
        if (!h->phy_dev)
                return 0;
 
+       ethtool_convert_legacy_u32_to_link_mode(supported, h->if_support);
+       linkmode_and(phy_dev->supported, phy_dev->supported, supported);
+       linkmode_copy(phy_dev->advertising, phy_dev->supported);
+
+       if (h->phy_if == PHY_INTERFACE_MODE_XGMII)
+               phy_dev->autoneg = false;
+
        if (h->phy_if != PHY_INTERFACE_MODE_XGMII) {
                phy_dev->dev_flags = 0;
 
@@ -1181,16 +1188,6 @@ int hns_nic_init_phy(struct net_device *ndev, struct hnae_handle *h)
        if (unlikely(ret))
                return -ENODEV;
 
-       ethtool_convert_legacy_u32_to_link_mode(supported, h->if_support);
-       linkmode_and(phy_dev->supported, phy_dev->supported, supported);
-       linkmode_copy(phy_dev->advertising, phy_dev->supported);
-
-       if (h->phy_if == PHY_INTERFACE_MODE_XGMII)
-               phy_dev->autoneg = false;
-
-       if (h->phy_if == PHY_INTERFACE_MODE_SGMII)
-               phy_stop(phy_dev);
-
        return 0;
 }
 
@@ -2421,6 +2418,8 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
 out_notify_fail:
        (void)cancel_work_sync(&priv->service_task);
 out_read_prop_fail:
+       /* safe for ACPI FW */
+       of_node_put(to_of_node(priv->fwnode));
        free_netdev(ndev);
        return ret;
 }
@@ -2450,6 +2449,9 @@ static int hns_nic_dev_remove(struct platform_device *pdev)
        set_bit(NIC_STATE_REMOVING, &priv->state);
        (void)cancel_work_sync(&priv->service_task);
 
+       /* safe for ACPI FW */
+       of_node_put(to_of_node(priv->fwnode));
+
        free_netdev(ndev);
        return 0;
 }
index 8e9b958..ce15d23 100644 (file)
@@ -1157,16 +1157,18 @@ static int hns_get_regs_len(struct net_device *net_dev)
  */
 static int hns_nic_nway_reset(struct net_device *netdev)
 {
-       int ret = 0;
        struct phy_device *phy = netdev->phydev;
 
-       if (netif_running(netdev)) {
-               /* if autoneg is disabled, don't restart auto-negotiation */
-               if (phy && phy->autoneg == AUTONEG_ENABLE)
-                       ret = genphy_restart_aneg(phy);
-       }
+       if (!netif_running(netdev))
+               return 0;
 
-       return ret;
+       if (!phy)
+               return -EOPNOTSUPP;
+
+       if (phy->autoneg != AUTONEG_ENABLE)
+               return -EINVAL;
+
+       return genphy_restart_aneg(phy);
 }
 
 static u32
index 07cd587..1bf7a5f 100644 (file)
@@ -2041,9 +2041,8 @@ static int hns3_alloc_desc(struct hns3_enet_ring *ring)
 {
        int size = ring->desc_num * sizeof(ring->desc[0]);
 
-       ring->desc = dma_zalloc_coherent(ring_to_dev(ring), size,
-                                        &ring->desc_dma_addr,
-                                        GFP_KERNEL);
+       ring->desc = dma_alloc_coherent(ring_to_dev(ring), size,
+                                       &ring->desc_dma_addr, GFP_KERNEL);
        if (!ring->desc)
                return -ENOMEM;
 
index 8af0cef..e483a6e 100644 (file)
@@ -39,9 +39,8 @@ static int hclge_alloc_cmd_desc(struct hclge_cmq_ring *ring)
 {
        int size  = ring->desc_num * sizeof(struct hclge_desc);
 
-       ring->desc = dma_zalloc_coherent(cmq_ring_to_dev(ring),
-                                        size, &ring->desc_dma_addr,
-                                        GFP_KERNEL);
+       ring->desc = dma_alloc_coherent(cmq_ring_to_dev(ring), size,
+                                       &ring->desc_dma_addr, GFP_KERNEL);
        if (!ring->desc)
                return -ENOMEM;
 
index d5765c8..4e78e88 100644 (file)
@@ -115,9 +115,8 @@ static int hclgevf_alloc_cmd_desc(struct hclgevf_cmq_ring *ring)
 {
        int size = ring->desc_num * sizeof(struct hclgevf_desc);
 
-       ring->desc = dma_zalloc_coherent(cmq_ring_to_dev(ring),
-                                        size, &ring->desc_dma_addr,
-                                        GFP_KERNEL);
+       ring->desc = dma_alloc_coherent(cmq_ring_to_dev(ring), size,
+                                       &ring->desc_dma_addr, GFP_KERNEL);
        if (!ring->desc)
                return -ENOMEM;
 
index 017e084..baf5cc2 100644 (file)
@@ -321,7 +321,7 @@ static int hns_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
                }
 
                hns_mdio_cmd_write(mdio_dev, is_c45,
-                                  MDIO_C45_WRITE_ADDR, phy_id, devad);
+                                  MDIO_C45_READ, phy_id, devad);
        }
 
        /* Step 5: waitting for MDIO_COMMAND_REG 's mdio_start==0,*/
index c40603a..b4fefb4 100644 (file)
@@ -613,8 +613,8 @@ static int alloc_cmd_buf(struct hinic_api_cmd_chain *chain,
        u8 *cmd_vaddr;
        int err = 0;
 
-       cmd_vaddr = dma_zalloc_coherent(&pdev->dev, API_CMD_BUF_SIZE,
-                                       &cmd_paddr, GFP_KERNEL);
+       cmd_vaddr = dma_alloc_coherent(&pdev->dev, API_CMD_BUF_SIZE,
+                                      &cmd_paddr, GFP_KERNEL);
        if (!cmd_vaddr) {
                dev_err(&pdev->dev, "Failed to allocate API CMD DMA memory\n");
                return -ENOMEM;
@@ -663,8 +663,8 @@ static int api_cmd_create_cell(struct hinic_api_cmd_chain *chain,
        dma_addr_t node_paddr;
        int err;
 
-       node = dma_zalloc_coherent(&pdev->dev, chain->cell_size,
-                                  &node_paddr, GFP_KERNEL);
+       node = dma_alloc_coherent(&pdev->dev, chain->cell_size, &node_paddr,
+                                 GFP_KERNEL);
        if (!node) {
                dev_err(&pdev->dev, "Failed to allocate dma API CMD cell\n");
                return -ENOMEM;
@@ -821,10 +821,10 @@ static int api_chain_init(struct hinic_api_cmd_chain *chain,
        if (!chain->cell_ctxt)
                return -ENOMEM;
 
-       chain->wb_status = dma_zalloc_coherent(&pdev->dev,
-                                              sizeof(*chain->wb_status),
-                                              &chain->wb_status_paddr,
-                                              GFP_KERNEL);
+       chain->wb_status = dma_alloc_coherent(&pdev->dev,
+                                             sizeof(*chain->wb_status),
+                                             &chain->wb_status_paddr,
+                                             GFP_KERNEL);
        if (!chain->wb_status) {
                dev_err(&pdev->dev, "Failed to allocate DMA wb status\n");
                return -ENOMEM;
index 7cb8b9b..683e675 100644 (file)
@@ -593,10 +593,10 @@ static int alloc_eq_pages(struct hinic_eq *eq)
        }
 
        for (pg = 0; pg < eq->num_pages; pg++) {
-               eq->virt_addr[pg] = dma_zalloc_coherent(&pdev->dev,
-                                                       eq->page_size,
-                                                       &eq->dma_addr[pg],
-                                                       GFP_KERNEL);
+               eq->virt_addr[pg] = dma_alloc_coherent(&pdev->dev,
+                                                      eq->page_size,
+                                                      &eq->dma_addr[pg],
+                                                      GFP_KERNEL);
                if (!eq->virt_addr[pg]) {
                        err = -ENOMEM;
                        goto err_dma_alloc;
index 8e58976..a322a22 100644 (file)
@@ -355,9 +355,9 @@ int hinic_io_create_qps(struct hinic_func_to_io *func_to_io,
                goto err_sq_db;
        }
 
-       ci_addr_base = dma_zalloc_coherent(&pdev->dev, CI_TABLE_SIZE(num_qps),
-                                          &func_to_io->ci_dma_base,
-                                          GFP_KERNEL);
+       ci_addr_base = dma_alloc_coherent(&pdev->dev, CI_TABLE_SIZE(num_qps),
+                                         &func_to_io->ci_dma_base,
+                                         GFP_KERNEL);
        if (!ci_addr_base) {
                dev_err(&pdev->dev, "Failed to allocate CI area\n");
                err = -ENOMEM;
index bbf9bdd..d62cf50 100644 (file)
@@ -336,9 +336,9 @@ static int alloc_rq_cqe(struct hinic_rq *rq)
                goto err_cqe_dma_arr_alloc;
 
        for (i = 0; i < wq->q_depth; i++) {
-               rq->cqe[i] = dma_zalloc_coherent(&pdev->dev,
-                                                sizeof(*rq->cqe[i]),
-                                                &rq->cqe_dma[i], GFP_KERNEL);
+               rq->cqe[i] = dma_alloc_coherent(&pdev->dev,
+                                               sizeof(*rq->cqe[i]),
+                                               &rq->cqe_dma[i], GFP_KERNEL);
                if (!rq->cqe[i])
                        goto err_cqe_alloc;
        }
@@ -415,8 +415,8 @@ int hinic_init_rq(struct hinic_rq *rq, struct hinic_hwif *hwif,
 
        /* HW requirements: Must be at least 32 bit */
        pi_size = ALIGN(sizeof(*rq->pi_virt_addr), sizeof(u32));
-       rq->pi_virt_addr = dma_zalloc_coherent(&pdev->dev, pi_size,
-                                              &rq->pi_dma_addr, GFP_KERNEL);
+       rq->pi_virt_addr = dma_alloc_coherent(&pdev->dev, pi_size,
+                                             &rq->pi_dma_addr, GFP_KERNEL);
        if (!rq->pi_virt_addr) {
                dev_err(&pdev->dev, "Failed to allocate PI address\n");
                err = -ENOMEM;
index 1dfa7eb..cb66e70 100644 (file)
@@ -114,8 +114,8 @@ static int queue_alloc_page(struct hinic_hwif *hwif, u64 **vaddr, u64 *paddr,
        struct pci_dev *pdev = hwif->pdev;
        dma_addr_t dma_addr;
 
-       *vaddr = dma_zalloc_coherent(&pdev->dev, page_sz, &dma_addr,
-                                    GFP_KERNEL);
+       *vaddr = dma_alloc_coherent(&pdev->dev, page_sz, &dma_addr,
+                                   GFP_KERNEL);
        if (!*vaddr) {
                dev_err(&pdev->dev, "Failed to allocate dma for wqs page\n");
                return -ENOMEM;
@@ -482,8 +482,8 @@ static int alloc_wq_pages(struct hinic_wq *wq, struct hinic_hwif *hwif,
                u64 *paddr = &wq->block_vaddr[i];
                dma_addr_t dma_addr;
 
-               *vaddr = dma_zalloc_coherent(&pdev->dev, wq->wq_page_size,
-                                            &dma_addr, GFP_KERNEL);
+               *vaddr = dma_alloc_coherent(&pdev->dev, wq->wq_page_size,
+                                           &dma_addr, GFP_KERNEL);
                if (!*vaddr) {
                        dev_err(&pdev->dev, "Failed to allocate wq page\n");
                        goto err_alloc_wq_pages;
index d719668..9292975 100644 (file)
@@ -1310,7 +1310,7 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id)
                                                dev->stats.tx_aborted_errors++;
                                }
 
-                               dev_kfree_skb_irq(skb);
+                               dev_consume_skb_irq(skb);
 
                                tx_cmd->cmd.command = 0; /* Mark free */
                                break;
index fff09dc..787d5ac 100644 (file)
@@ -636,8 +636,8 @@ static int mal_probe(struct platform_device *ofdev)
        bd_size = sizeof(struct mal_descriptor) *
                (NUM_TX_BUFF * mal->num_tx_chans +
                 NUM_RX_BUFF * mal->num_rx_chans);
-       mal->bd_virt = dma_zalloc_coherent(&ofdev->dev, bd_size, &mal->bd_dma,
-                                          GFP_KERNEL);
+       mal->bd_virt = dma_alloc_coherent(&ofdev->dev, bd_size, &mal->bd_dma,
+                                         GFP_KERNEL);
        if (mal->bd_virt == NULL) {
                err = -ENOMEM;
                goto fail_unmap;
index 098d876..dd71d5d 100644 (file)
@@ -1313,7 +1313,6 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
        unsigned long lpar_rc;
        u16 mss = 0;
 
-restart_poll:
        while (frames_processed < budget) {
                if (!ibmveth_rxq_pending_buffer(adapter))
                        break;
@@ -1401,7 +1400,6 @@ restart_poll:
                    napi_reschedule(napi)) {
                        lpar_rc = h_vio_signal(adapter->vdev->unit_address,
                                               VIO_IRQ_DISABLE);
-                       goto restart_poll;
                }
        }
 
index 31fb76e..a1246e8 100644 (file)
@@ -159,7 +159,7 @@ config IXGBE
        tristate "Intel(R) 10GbE PCI Express adapters support"
        depends on PCI
        select MDIO
-       select MDIO_DEVICE
+       select PHYLIB
        imply PTP_1588_CLOCK
        ---help---
          This driver supports Intel(R) 10GbE PCI Express family of
index 2569a16..a410085 100644 (file)
@@ -993,8 +993,8 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
 
        txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
        txdr->size = ALIGN(txdr->size, 4096);
-       txdr->desc = dma_zalloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
-                                        GFP_KERNEL);
+       txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
+                                       GFP_KERNEL);
        if (!txdr->desc) {
                ret_val = 2;
                goto err_nomem;
@@ -1051,8 +1051,8 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
        }
 
        rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc);
-       rxdr->desc = dma_zalloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
-                                        GFP_KERNEL);
+       rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
+                                       GFP_KERNEL);
        if (!rxdr->desc) {
                ret_val = 6;
                goto err_nomem;
index 308c006..189f231 100644 (file)
@@ -2305,8 +2305,8 @@ static int e1000_alloc_ring_dma(struct e1000_adapter *adapter,
 {
        struct pci_dev *pdev = adapter->pdev;
 
-       ring->desc = dma_zalloc_coherent(&pdev->dev, ring->size, &ring->dma,
-                                        GFP_KERNEL);
+       ring->desc = dma_alloc_coherent(&pdev->dev, ring->size, &ring->dma,
+                                       GFP_KERNEL);
        if (!ring->desc)
                return -ENOMEM;
 
index 4d40878..f52e2c4 100644 (file)
@@ -109,8 +109,8 @@ int i40e_allocate_dma_mem_d(struct i40e_hw *hw, struct i40e_dma_mem *mem,
        struct i40e_pf *pf = (struct i40e_pf *)hw->back;
 
        mem->size = ALIGN(size, alignment);
-       mem->va = dma_zalloc_coherent(&pf->pdev->dev, mem->size,
-                                     &mem->pa, GFP_KERNEL);
+       mem->va = dma_alloc_coherent(&pf->pdev->dev, mem->size, &mem->pa,
+                                    GFP_KERNEL);
        if (!mem->va)
                return -ENOMEM;
 
index fe1592a..ca54e26 100644 (file)
@@ -515,7 +515,7 @@ struct igb_adapter {
        /* OS defined structs */
        struct pci_dev *pdev;
 
-       struct mutex stats64_lock;
+       spinlock_t stats64_lock;
        struct rtnl_link_stats64 stats64;
 
        /* structs defined in e1000_hw.h */
index 7426060..c576710 100644 (file)
@@ -2295,7 +2295,7 @@ static void igb_get_ethtool_stats(struct net_device *netdev,
        int i, j;
        char *p;
 
-       mutex_lock(&adapter->stats64_lock);
+       spin_lock(&adapter->stats64_lock);
        igb_update_stats(adapter);
 
        for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) {
@@ -2338,7 +2338,7 @@ static void igb_get_ethtool_stats(struct net_device *netdev,
                } while (u64_stats_fetch_retry_irq(&ring->rx_syncp, start));
                i += IGB_RX_QUEUE_STATS_LEN;
        }
-       mutex_unlock(&adapter->stats64_lock);
+       spin_unlock(&adapter->stats64_lock);
 }
 
 static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
index 87bdf16..7137e7f 100644 (file)
@@ -2203,9 +2203,9 @@ void igb_down(struct igb_adapter *adapter)
        del_timer_sync(&adapter->phy_info_timer);
 
        /* record the stats before reset*/
-       mutex_lock(&adapter->stats64_lock);
+       spin_lock(&adapter->stats64_lock);
        igb_update_stats(adapter);
-       mutex_unlock(&adapter->stats64_lock);
+       spin_unlock(&adapter->stats64_lock);
 
        adapter->link_speed = 0;
        adapter->link_duplex = 0;
@@ -3840,7 +3840,7 @@ static int igb_sw_init(struct igb_adapter *adapter)
        adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
 
        spin_lock_init(&adapter->nfc_lock);
-       mutex_init(&adapter->stats64_lock);
+       spin_lock_init(&adapter->stats64_lock);
 #ifdef CONFIG_PCI_IOV
        switch (hw->mac.type) {
        case e1000_82576:
@@ -5406,9 +5406,9 @@ no_wait:
                }
        }
 
-       mutex_lock(&adapter->stats64_lock);
+       spin_lock(&adapter->stats64_lock);
        igb_update_stats(adapter);
-       mutex_unlock(&adapter->stats64_lock);
+       spin_unlock(&adapter->stats64_lock);
 
        for (i = 0; i < adapter->num_tx_queues; i++) {
                struct igb_ring *tx_ring = adapter->tx_ring[i];
@@ -6235,10 +6235,10 @@ static void igb_get_stats64(struct net_device *netdev,
 {
        struct igb_adapter *adapter = netdev_priv(netdev);
 
-       mutex_lock(&adapter->stats64_lock);
+       spin_lock(&adapter->stats64_lock);
        igb_update_stats(adapter);
        memcpy(stats, &adapter->stats64, sizeof(*stats));
-       mutex_unlock(&adapter->stats64_lock);
+       spin_unlock(&adapter->stats64_lock);
 }
 
 /**
index 1d4d168..e5ac2d3 100644 (file)
@@ -680,8 +680,8 @@ ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
        txdr->size = txdr->count * sizeof(struct ixgb_tx_desc);
        txdr->size = ALIGN(txdr->size, 4096);
 
-       txdr->desc = dma_zalloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
-                                        GFP_KERNEL);
+       txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
+                                       GFP_KERNEL);
        if (!txdr->desc) {
                vfree(txdr->buffer_info);
                return -ENOMEM;
@@ -763,8 +763,8 @@ ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
        rxdr->size = rxdr->count * sizeof(struct ixgb_rx_desc);
        rxdr->size = ALIGN(rxdr->size, 4096);
 
-       rxdr->desc = dma_zalloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
-                                        GFP_KERNEL);
+       rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
+                                       GFP_KERNEL);
 
        if (!rxdr->desc) {
                vfree(rxdr->buffer_info);
index e087547..16066c2 100644 (file)
@@ -2044,9 +2044,9 @@ static int mvpp2_aggr_txq_init(struct platform_device *pdev,
        u32 txq_dma;
 
        /* Allocate memory for TX descriptors */
-       aggr_txq->descs = dma_zalloc_coherent(&pdev->dev,
-                               MVPP2_AGGR_TXQ_SIZE * MVPP2_DESC_ALIGNED_SIZE,
-                               &aggr_txq->descs_dma, GFP_KERNEL);
+       aggr_txq->descs = dma_alloc_coherent(&pdev->dev,
+                                            MVPP2_AGGR_TXQ_SIZE * MVPP2_DESC_ALIGNED_SIZE,
+                                            &aggr_txq->descs_dma, GFP_KERNEL);
        if (!aggr_txq->descs)
                return -ENOMEM;
 
index 742f0c1..6d55e3d 100644 (file)
@@ -825,7 +825,7 @@ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (!cgx->cgx_cmd_workq) {
                dev_err(dev, "alloc workqueue failed for cgx cmd");
                err = -ENOMEM;
-               goto err_release_regions;
+               goto err_free_irq_vectors;
        }
 
        list_add(&cgx->cgx_list, &cgx_list);
@@ -841,6 +841,8 @@ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 err_release_lmac:
        cgx_lmac_exit(cgx);
        list_del(&cgx->cgx_list);
+err_free_irq_vectors:
+       pci_free_irq_vectors(pdev);
 err_release_regions:
        pci_release_regions(pdev);
 err_disable_device:
index ec50a21..e332e82 100644 (file)
@@ -64,7 +64,7 @@ static inline int qmem_alloc(struct device *dev, struct qmem **q,
 
        qmem->entry_sz = entry_sz;
        qmem->alloc_sz = (qsize * entry_sz) + OTX2_ALIGN;
-       qmem->base = dma_zalloc_coherent(dev, qmem->alloc_sz,
+       qmem->base = dma_alloc_coherent(dev, qmem->alloc_sz,
                                         &qmem->iova, GFP_KERNEL);
        if (!qmem->base)
                return -ENOMEM;
index 0bd4351..f8a6d6e 100644 (file)
@@ -557,9 +557,9 @@ static int init_hash_table(struct pxa168_eth_private *pep)
         * table is full.
         */
        if (!pep->htpr) {
-               pep->htpr = dma_zalloc_coherent(pep->dev->dev.parent,
-                                               HASH_ADDR_TABLE_SIZE,
-                                               &pep->htpr_dma, GFP_KERNEL);
+               pep->htpr = dma_alloc_coherent(pep->dev->dev.parent,
+                                              HASH_ADDR_TABLE_SIZE,
+                                              &pep->htpr_dma, GFP_KERNEL);
                if (!pep->htpr)
                        return -ENOMEM;
        } else {
@@ -1044,9 +1044,9 @@ static int rxq_init(struct net_device *dev)
        pep->rx_desc_count = 0;
        size = pep->rx_ring_size * sizeof(struct rx_desc);
        pep->rx_desc_area_size = size;
-       pep->p_rx_desc_area = dma_zalloc_coherent(pep->dev->dev.parent, size,
-                                                 &pep->rx_desc_dma,
-                                                 GFP_KERNEL);
+       pep->p_rx_desc_area = dma_alloc_coherent(pep->dev->dev.parent, size,
+                                                &pep->rx_desc_dma,
+                                                GFP_KERNEL);
        if (!pep->p_rx_desc_area)
                goto out;
 
@@ -1103,9 +1103,9 @@ static int txq_init(struct net_device *dev)
        pep->tx_desc_count = 0;
        size = pep->tx_ring_size * sizeof(struct tx_desc);
        pep->tx_desc_area_size = size;
-       pep->p_tx_desc_area = dma_zalloc_coherent(pep->dev->dev.parent, size,
-                                                 &pep->tx_desc_dma,
-                                                 GFP_KERNEL);
+       pep->p_tx_desc_area = dma_alloc_coherent(pep->dev->dev.parent, size,
+                                                &pep->tx_desc_dma,
+                                                GFP_KERNEL);
        if (!pep->p_tx_desc_area)
                goto out;
        /* Initialize the next_desc_ptr links in the Tx descriptors ring */
index 04fd1f1..654ac53 100644 (file)
@@ -152,8 +152,10 @@ static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs,
        memset(p, 0, regs->len);
        memcpy_fromio(p, io, B3_RAM_ADDR);
 
-       memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
-                     regs->len - B3_RI_WTO_R1);
+       if (regs->len > B3_RI_WTO_R1) {
+               memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
+                             regs->len - B3_RI_WTO_R1);
+       }
 }
 
 /* Wake on Lan only supported on Yukon chips with rev 1 or above */
index 399f565..49f926b 100644 (file)
@@ -258,11 +258,6 @@ static void mtk_phy_link_adjust(struct net_device *dev)
 
        mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
 
-       if (dev->phydev->link)
-               netif_carrier_on(dev);
-       else
-               netif_carrier_off(dev);
-
        if (!of_phy_is_fixed_link(mac->of_node))
                phy_print_status(dev->phydev);
 }
@@ -347,17 +342,6 @@ static int mtk_phy_connect(struct net_device *dev)
        if (mtk_phy_connect_node(eth, mac, np))
                goto err_phy;
 
-       dev->phydev->autoneg = AUTONEG_ENABLE;
-       dev->phydev->speed = 0;
-       dev->phydev->duplex = 0;
-
-       phy_set_max_speed(dev->phydev, SPEED_1000);
-       phy_support_asym_pause(dev->phydev);
-       linkmode_copy(dev->phydev->advertising, dev->phydev->supported);
-       linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
-                        dev->phydev->advertising);
-       phy_start_aneg(dev->phydev);
-
        of_node_put(np);
 
        return 0;
@@ -598,10 +582,10 @@ static int mtk_init_fq_dma(struct mtk_eth *eth)
        dma_addr_t dma_addr;
        int i;
 
-       eth->scratch_ring = dma_zalloc_coherent(eth->dev,
-                                               cnt * sizeof(struct mtk_tx_dma),
-                                               &eth->phy_scratch_ring,
-                                               GFP_ATOMIC);
+       eth->scratch_ring = dma_alloc_coherent(eth->dev,
+                                              cnt * sizeof(struct mtk_tx_dma),
+                                              &eth->phy_scratch_ring,
+                                              GFP_ATOMIC);
        if (unlikely(!eth->scratch_ring))
                return -ENOMEM;
 
@@ -1213,8 +1197,8 @@ static int mtk_tx_alloc(struct mtk_eth *eth)
        if (!ring->buf)
                goto no_tx_mem;
 
-       ring->dma = dma_zalloc_coherent(eth->dev, MTK_DMA_SIZE * sz,
-                                       &ring->phys, GFP_ATOMIC);
+       ring->dma = dma_alloc_coherent(eth->dev, MTK_DMA_SIZE * sz,
+                                      &ring->phys, GFP_ATOMIC);
        if (!ring->dma)
                goto no_tx_mem;
 
@@ -1310,9 +1294,9 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
                        return -ENOMEM;
        }
 
-       ring->dma = dma_zalloc_coherent(eth->dev,
-                                       rx_dma_size * sizeof(*ring->dma),
-                                       &ring->phys, GFP_ATOMIC);
+       ring->dma = dma_alloc_coherent(eth->dev,
+                                      rx_dma_size * sizeof(*ring->dma),
+                                      &ring->phys, GFP_ATOMIC);
        if (!ring->dma)
                return -ENOMEM;
 
index 9af34e0..dbc483e 100644 (file)
@@ -584,8 +584,8 @@ static int mlx4_buf_direct_alloc(struct mlx4_dev *dev, int size,
        buf->npages       = 1;
        buf->page_shift   = get_order(size) + PAGE_SHIFT;
        buf->direct.buf   =
-               dma_zalloc_coherent(&dev->persist->pdev->dev,
-                                   size, &t, GFP_KERNEL);
+               dma_alloc_coherent(&dev->persist->pdev->dev, size, &t,
+                                  GFP_KERNEL);
        if (!buf->direct.buf)
                return -ENOMEM;
 
@@ -624,8 +624,8 @@ int mlx4_buf_alloc(struct mlx4_dev *dev, int size, int max_direct,
 
                for (i = 0; i < buf->nbufs; ++i) {
                        buf->page_list[i].buf =
-                               dma_zalloc_coherent(&dev->persist->pdev->dev,
-                                                   PAGE_SIZE, &t, GFP_KERNEL);
+                               dma_alloc_coherent(&dev->persist->pdev->dev,
+                                                  PAGE_SIZE, &t, GFP_KERNEL);
                        if (!buf->page_list[i].buf)
                                goto err_free;
 
index db909b6..65f8a4b 100644 (file)
@@ -306,14 +306,16 @@ static int mlx4_init_user_cqes(void *buf, int entries, int cqe_size)
 
        if (entries_per_copy < entries) {
                for (i = 0; i < entries / entries_per_copy; i++) {
-                       err = copy_to_user(buf, init_ents, PAGE_SIZE);
+                       err = copy_to_user((void __user *)buf, init_ents, PAGE_SIZE) ?
+                               -EFAULT : 0;
                        if (err)
                                goto out;
 
                        buf += PAGE_SIZE;
                }
        } else {
-               err = copy_to_user(buf, init_ents, entries * cqe_size);
+               err = copy_to_user((void __user *)buf, init_ents, entries * cqe_size) ?
+                       -EFAULT : 0;
        }
 
 out:
index 9a0881c..6c01314 100644 (file)
@@ -617,6 +617,8 @@ static int get_fixed_ipv6_csum(__wsum hw_checksum, struct sk_buff *skb,
 }
 #endif
 
+#define short_frame(size) ((size) <= ETH_ZLEN + ETH_FCS_LEN)
+
 /* We reach this function only after checking that any of
  * the (IPv4 | IPv6) bits are set in cqe->status.
  */
@@ -624,9 +626,20 @@ static int check_csum(struct mlx4_cqe *cqe, struct sk_buff *skb, void *va,
                      netdev_features_t dev_features)
 {
        __wsum hw_checksum = 0;
+       void *hdr;
+
+       /* CQE csum doesn't cover padding octets in short ethernet
+        * frames. And the pad field is appended prior to calculating
+        * and appending the FCS field.
+        *
+        * Detecting these padded frames requires to verify and parse
+        * IP headers, so we simply force all those small frames to skip
+        * checksum complete.
+        */
+       if (short_frame(skb->len))
+               return -EINVAL;
 
-       void *hdr = (u8 *)va + sizeof(struct ethhdr);
-
+       hdr = (u8 *)va + sizeof(struct ethhdr);
        hw_checksum = csum_unfold((__force __sum16)cqe->checksum);
 
        if (cqe->vlan_my_qpn & cpu_to_be32(MLX4_CQE_CVLAN_PRESENT_MASK) &&
@@ -819,6 +832,11 @@ xdp_drop_no_cnt:
                skb_record_rx_queue(skb, cq_ring);
 
                if (likely(dev->features & NETIF_F_RXCSUM)) {
+                       /* TODO: For IP non TCP/UDP packets when csum complete is
+                        * not an option (not supported or any other reason) we can
+                        * actually check cqe IPOK status bit and report
+                        * CHECKSUM_UNNECESSARY rather than CHECKSUM_NONE
+                        */
                        if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_TCP |
                                                       MLX4_CQE_STATUS_UDP)) &&
                            (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
index 7df728f..6e501af 100644 (file)
@@ -2067,9 +2067,11 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
 {
        struct mlx4_cmd_mailbox *mailbox;
        __be32 *outbox;
+       u64 qword_field;
        u32 dword_field;
-       int err;
+       u16 word_field;
        u8 byte_field;
+       int err;
        static const u8 a0_dmfs_query_hw_steering[] =  {
                [0] = MLX4_STEERING_DMFS_A0_DEFAULT,
                [1] = MLX4_STEERING_DMFS_A0_DYNAMIC,
@@ -2097,19 +2099,32 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
 
        /* QPC/EEC/CQC/EQC/RDMARC attributes */
 
-       MLX4_GET(param->qpc_base,      outbox, INIT_HCA_QPC_BASE_OFFSET);
-       MLX4_GET(param->log_num_qps,   outbox, INIT_HCA_LOG_QP_OFFSET);
-       MLX4_GET(param->srqc_base,     outbox, INIT_HCA_SRQC_BASE_OFFSET);
-       MLX4_GET(param->log_num_srqs,  outbox, INIT_HCA_LOG_SRQ_OFFSET);
-       MLX4_GET(param->cqc_base,      outbox, INIT_HCA_CQC_BASE_OFFSET);
-       MLX4_GET(param->log_num_cqs,   outbox, INIT_HCA_LOG_CQ_OFFSET);
-       MLX4_GET(param->altc_base,     outbox, INIT_HCA_ALTC_BASE_OFFSET);
-       MLX4_GET(param->auxc_base,     outbox, INIT_HCA_AUXC_BASE_OFFSET);
-       MLX4_GET(param->eqc_base,      outbox, INIT_HCA_EQC_BASE_OFFSET);
-       MLX4_GET(param->log_num_eqs,   outbox, INIT_HCA_LOG_EQ_OFFSET);
-       MLX4_GET(param->num_sys_eqs,   outbox, INIT_HCA_NUM_SYS_EQS_OFFSET);
-       MLX4_GET(param->rdmarc_base,   outbox, INIT_HCA_RDMARC_BASE_OFFSET);
-       MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET);
+       MLX4_GET(qword_field, outbox, INIT_HCA_QPC_BASE_OFFSET);
+       param->qpc_base = qword_field & ~((u64)0x1f);
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_QP_OFFSET);
+       param->log_num_qps = byte_field & 0x1f;
+       MLX4_GET(qword_field, outbox, INIT_HCA_SRQC_BASE_OFFSET);
+       param->srqc_base = qword_field & ~((u64)0x1f);
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_SRQ_OFFSET);
+       param->log_num_srqs = byte_field & 0x1f;
+       MLX4_GET(qword_field, outbox, INIT_HCA_CQC_BASE_OFFSET);
+       param->cqc_base = qword_field & ~((u64)0x1f);
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_CQ_OFFSET);
+       param->log_num_cqs = byte_field & 0x1f;
+       MLX4_GET(qword_field, outbox, INIT_HCA_ALTC_BASE_OFFSET);
+       param->altc_base = qword_field;
+       MLX4_GET(qword_field, outbox, INIT_HCA_AUXC_BASE_OFFSET);
+       param->auxc_base = qword_field;
+       MLX4_GET(qword_field, outbox, INIT_HCA_EQC_BASE_OFFSET);
+       param->eqc_base = qword_field & ~((u64)0x1f);
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_EQ_OFFSET);
+       param->log_num_eqs = byte_field & 0x1f;
+       MLX4_GET(word_field, outbox, INIT_HCA_NUM_SYS_EQS_OFFSET);
+       param->num_sys_eqs = word_field & 0xfff;
+       MLX4_GET(qword_field, outbox, INIT_HCA_RDMARC_BASE_OFFSET);
+       param->rdmarc_base = qword_field & ~((u64)0x1f);
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_RD_OFFSET);
+       param->log_rd_per_qp = byte_field & 0x7;
 
        MLX4_GET(dword_field, outbox, INIT_HCA_FLAGS_OFFSET);
        if (dword_field & (1 << INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN)) {
@@ -2128,22 +2143,21 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
        /* steering attributes */
        if (param->steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) {
                MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET);
-               MLX4_GET(param->log_mc_entry_sz, outbox,
-                        INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
-               MLX4_GET(param->log_mc_table_sz, outbox,
-                        INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
-               MLX4_GET(byte_field, outbox,
-                        INIT_HCA_FS_A0_OFFSET);
+               MLX4_GET(byte_field, outbox, INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
+               param->log_mc_entry_sz = byte_field & 0x1f;
+               MLX4_GET(byte_field, outbox, INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
+               param->log_mc_table_sz = byte_field & 0x1f;
+               MLX4_GET(byte_field, outbox, INIT_HCA_FS_A0_OFFSET);
                param->dmfs_high_steer_mode =
                        a0_dmfs_query_hw_steering[(byte_field >> 6) & 3];
        } else {
                MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET);
-               MLX4_GET(param->log_mc_entry_sz, outbox,
-                        INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
-               MLX4_GET(param->log_mc_hash_sz,  outbox,
-                        INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
-               MLX4_GET(param->log_mc_table_sz, outbox,
-                        INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
+               MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
+               param->log_mc_entry_sz = byte_field & 0x1f;
+               MLX4_GET(byte_field,  outbox, INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
+               param->log_mc_hash_sz = byte_field & 0x1f;
+               MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
+               param->log_mc_table_sz = byte_field & 0x1f;
        }
 
        /* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */
@@ -2167,15 +2181,18 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
        /* TPT attributes */
 
        MLX4_GET(param->dmpt_base,  outbox, INIT_HCA_DMPT_BASE_OFFSET);
-       MLX4_GET(param->mw_enabled, outbox, INIT_HCA_TPT_MW_OFFSET);
-       MLX4_GET(param->log_mpt_sz, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET);
+       MLX4_GET(byte_field, outbox, INIT_HCA_TPT_MW_OFFSET);
+       param->mw_enabled = byte_field >> 7;
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET);
+       param->log_mpt_sz = byte_field & 0x3f;
        MLX4_GET(param->mtt_base,   outbox, INIT_HCA_MTT_BASE_OFFSET);
        MLX4_GET(param->cmpt_base,  outbox, INIT_HCA_CMPT_BASE_OFFSET);
 
        /* UAR attributes */
 
        MLX4_GET(param->uar_page_sz, outbox, INIT_HCA_UAR_PAGE_SZ_OFFSET);
-       MLX4_GET(param->log_uar_sz, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET);
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET);
+       param->log_uar_sz = byte_field & 0xf;
 
        /* phv_check enable */
        MLX4_GET(byte_field, outbox, INIT_HCA_CACHELINE_SZ_OFFSET);
index 4b43511..d89a3da 100644 (file)
@@ -57,12 +57,12 @@ static void mlx4_free_icm_pages(struct mlx4_dev *dev, struct mlx4_icm_chunk *chu
        int i;
 
        if (chunk->nsg > 0)
-               pci_unmap_sg(dev->persist->pdev, chunk->mem, chunk->npages,
-                            PCI_DMA_BIDIRECTIONAL);
+               dma_unmap_sg(&dev->persist->pdev->dev, chunk->sg, chunk->npages,
+                            DMA_BIDIRECTIONAL);
 
        for (i = 0; i < chunk->npages; ++i)
-               __free_pages(sg_page(&chunk->mem[i]),
-                            get_order(chunk->mem[i].length));
+               __free_pages(sg_page(&chunk->sg[i]),
+                            get_order(chunk->sg[i].length));
 }
 
 static void mlx4_free_icm_coherent(struct mlx4_dev *dev, struct mlx4_icm_chunk *chunk)
@@ -71,9 +71,9 @@ static void mlx4_free_icm_coherent(struct mlx4_dev *dev, struct mlx4_icm_chunk *
 
        for (i = 0; i < chunk->npages; ++i)
                dma_free_coherent(&dev->persist->pdev->dev,
-                                 chunk->mem[i].length,
-                                 lowmem_page_address(sg_page(&chunk->mem[i])),
-                                 sg_dma_address(&chunk->mem[i]));
+                                 chunk->buf[i].size,
+                                 chunk->buf[i].addr,
+                                 chunk->buf[i].dma_addr);
 }
 
 void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent)
@@ -111,22 +111,21 @@ static int mlx4_alloc_icm_pages(struct scatterlist *mem, int order,
        return 0;
 }
 
-static int mlx4_alloc_icm_coherent(struct device *dev, struct scatterlist *mem,
-                                   int order, gfp_t gfp_mask)
+static int mlx4_alloc_icm_coherent(struct device *dev, struct mlx4_icm_buf *buf,
+                                  int order, gfp_t gfp_mask)
 {
-       void *buf = dma_alloc_coherent(dev, PAGE_SIZE << order,
-                                      &sg_dma_address(mem), gfp_mask);
-       if (!buf)
+       buf->addr = dma_alloc_coherent(dev, PAGE_SIZE << order,
+                                      &buf->dma_addr, gfp_mask);
+       if (!buf->addr)
                return -ENOMEM;
 
-       if (offset_in_page(buf)) {
-               dma_free_coherent(dev, PAGE_SIZE << order,
-                                 buf, sg_dma_address(mem));
+       if (offset_in_page(buf->addr)) {
+               dma_free_coherent(dev, PAGE_SIZE << order, buf->addr,
+                                 buf->dma_addr);
                return -ENOMEM;
        }
 
-       sg_set_buf(mem, buf, PAGE_SIZE << order);
-       sg_dma_len(mem) = PAGE_SIZE << order;
+       buf->size = PAGE_SIZE << order;
        return 0;
 }
 
@@ -159,21 +158,21 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
 
        while (npages > 0) {
                if (!chunk) {
-                       chunk = kmalloc_node(sizeof(*chunk),
+                       chunk = kzalloc_node(sizeof(*chunk),
                                             gfp_mask & ~(__GFP_HIGHMEM |
                                                          __GFP_NOWARN),
                                             dev->numa_node);
                        if (!chunk) {
-                               chunk = kmalloc(sizeof(*chunk),
+                               chunk = kzalloc(sizeof(*chunk),
                                                gfp_mask & ~(__GFP_HIGHMEM |
                                                             __GFP_NOWARN));
                                if (!chunk)
                                        goto fail;
                        }
+                       chunk->coherent = coherent;
 
-                       sg_init_table(chunk->mem, MLX4_ICM_CHUNK_LEN);
-                       chunk->npages = 0;
-                       chunk->nsg    = 0;
+                       if (!coherent)
+                               sg_init_table(chunk->sg, MLX4_ICM_CHUNK_LEN);
                        list_add_tail(&chunk->list, &icm->chunk_list);
                }
 
@@ -186,10 +185,10 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
 
                if (coherent)
                        ret = mlx4_alloc_icm_coherent(&dev->persist->pdev->dev,
-                                                     &chunk->mem[chunk->npages],
-                                                     cur_order, mask);
+                                               &chunk->buf[chunk->npages],
+                                               cur_order, mask);
                else
-                       ret = mlx4_alloc_icm_pages(&chunk->mem[chunk->npages],
+                       ret = mlx4_alloc_icm_pages(&chunk->sg[chunk->npages],
                                                   cur_order, mask,
                                                   dev->numa_node);
 
@@ -205,9 +204,9 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
                if (coherent)
                        ++chunk->nsg;
                else if (chunk->npages == MLX4_ICM_CHUNK_LEN) {
-                       chunk->nsg = pci_map_sg(dev->persist->pdev, chunk->mem,
-                                               chunk->npages,
-                                               PCI_DMA_BIDIRECTIONAL);
+                       chunk->nsg = dma_map_sg(&dev->persist->pdev->dev,
+                                               chunk->sg, chunk->npages,
+                                               DMA_BIDIRECTIONAL);
 
                        if (chunk->nsg <= 0)
                                goto fail;
@@ -220,9 +219,8 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
        }
 
        if (!coherent && chunk) {
-               chunk->nsg = pci_map_sg(dev->persist->pdev, chunk->mem,
-                                       chunk->npages,
-                                       PCI_DMA_BIDIRECTIONAL);
+               chunk->nsg = dma_map_sg(&dev->persist->pdev->dev, chunk->sg,
+                                       chunk->npages, DMA_BIDIRECTIONAL);
 
                if (chunk->nsg <= 0)
                        goto fail;
@@ -320,7 +318,7 @@ void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj,
        u64 idx;
        struct mlx4_icm_chunk *chunk;
        struct mlx4_icm *icm;
-       struct page *page = NULL;
+       void *addr = NULL;
 
        if (!table->lowmem)
                return NULL;
@@ -336,28 +334,49 @@ void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj,
 
        list_for_each_entry(chunk, &icm->chunk_list, list) {
                for (i = 0; i < chunk->npages; ++i) {
+                       dma_addr_t dma_addr;
+                       size_t len;
+
+                       if (table->coherent) {
+                               len = chunk->buf[i].size;
+                               dma_addr = chunk->buf[i].dma_addr;
+                               addr = chunk->buf[i].addr;
+                       } else {
+                               struct page *page;
+
+                               len = sg_dma_len(&chunk->sg[i]);
+                               dma_addr = sg_dma_address(&chunk->sg[i]);
+
+                               /* XXX: we should never do this for highmem
+                                * allocation.  This function either needs
+                                * to be split, or the kernel virtual address
+                                * return needs to be made optional.
+                                */
+                               page = sg_page(&chunk->sg[i]);
+                               addr = lowmem_page_address(page);
+                       }
+
                        if (dma_handle && dma_offset >= 0) {
-                               if (sg_dma_len(&chunk->mem[i]) > dma_offset)
-                                       *dma_handle = sg_dma_address(&chunk->mem[i]) +
-                                               dma_offset;
-                               dma_offset -= sg_dma_len(&chunk->mem[i]);
+                               if (len > dma_offset)
+                                       *dma_handle = dma_addr + dma_offset;
+                               dma_offset -= len;
                        }
+
                        /*
                         * DMA mapping can merge pages but not split them,
                         * so if we found the page, dma_handle has already
                         * been assigned to.
                         */
-                       if (chunk->mem[i].length > offset) {
-                               page = sg_page(&chunk->mem[i]);
+                       if (len > offset)
                                goto out;
-                       }
-                       offset -= chunk->mem[i].length;
+                       offset -= len;
                }
        }
 
+       addr = NULL;
 out:
        mutex_unlock(&table->mutex);
-       return page ? lowmem_page_address(page) + offset : NULL;
+       return addr ? addr + offset : NULL;
 }
 
 int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
index c9169a4..d199874 100644 (file)
@@ -47,11 +47,21 @@ enum {
        MLX4_ICM_PAGE_SIZE      = 1 << MLX4_ICM_PAGE_SHIFT,
 };
 
+struct mlx4_icm_buf {
+       void                    *addr;
+       size_t                  size;
+       dma_addr_t              dma_addr;
+};
+
 struct mlx4_icm_chunk {
        struct list_head        list;
        int                     npages;
        int                     nsg;
-       struct scatterlist      mem[MLX4_ICM_CHUNK_LEN];
+       bool                    coherent;
+       union {
+               struct scatterlist      sg[MLX4_ICM_CHUNK_LEN];
+               struct mlx4_icm_buf     buf[MLX4_ICM_CHUNK_LEN];
+       };
 };
 
 struct mlx4_icm {
@@ -114,12 +124,18 @@ static inline void mlx4_icm_next(struct mlx4_icm_iter *iter)
 
 static inline dma_addr_t mlx4_icm_addr(struct mlx4_icm_iter *iter)
 {
-       return sg_dma_address(&iter->chunk->mem[iter->page_idx]);
+       if (iter->chunk->coherent)
+               return iter->chunk->buf[iter->page_idx].dma_addr;
+       else
+               return sg_dma_address(&iter->chunk->sg[iter->page_idx]);
 }
 
 static inline unsigned long mlx4_icm_size(struct mlx4_icm_iter *iter)
 {
-       return sg_dma_len(&iter->chunk->mem[iter->page_idx]);
+       if (iter->chunk->coherent)
+               return iter->chunk->buf[iter->page_idx].size;
+       else
+               return sg_dma_len(&iter->chunk->sg[iter->page_idx]);
 }
 
 int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm);
index 456f300..421b9c3 100644 (file)
@@ -63,8 +63,8 @@ static void *mlx5_dma_zalloc_coherent_node(struct mlx5_core_dev *dev,
        mutex_lock(&priv->alloc_mutex);
        original_node = dev_to_node(&dev->pdev->dev);
        set_dev_node(&dev->pdev->dev, node);
-       cpu_handle = dma_zalloc_coherent(&dev->pdev->dev, size,
-                                        dma_handle, GFP_KERNEL);
+       cpu_handle = dma_alloc_coherent(&dev->pdev->dev, size, dma_handle,
+                                       GFP_KERNEL);
        set_dev_node(&dev->pdev->dev, original_node);
        mutex_unlock(&priv->alloc_mutex);
        return cpu_handle;
index d3125cd..e267ff9 100644 (file)
@@ -1583,6 +1583,24 @@ no_trig:
        spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags);
 }
 
+void mlx5_cmd_flush(struct mlx5_core_dev *dev)
+{
+       struct mlx5_cmd *cmd = &dev->cmd;
+       int i;
+
+       for (i = 0; i < cmd->max_reg_cmds; i++)
+               while (down_trylock(&cmd->sem))
+                       mlx5_cmd_trigger_completions(dev);
+
+       while (down_trylock(&cmd->pages_sem))
+               mlx5_cmd_trigger_completions(dev);
+
+       /* Unlock cmdif */
+       up(&cmd->pages_sem);
+       for (i = 0; i < cmd->max_reg_cmds; i++)
+               up(&cmd->sem);
+}
+
 static int status_to_err(u8 status)
 {
        return status ? -1 : 0; /* TBD more meaningful codes */
@@ -1789,8 +1807,8 @@ static int alloc_cmd_page(struct mlx5_core_dev *dev, struct mlx5_cmd *cmd)
 {
        struct device *ddev = &dev->pdev->dev;
 
-       cmd->cmd_alloc_buf = dma_zalloc_coherent(ddev, MLX5_ADAPTER_PAGE_SIZE,
-                                                &cmd->alloc_dma, GFP_KERNEL);
+       cmd->cmd_alloc_buf = dma_alloc_coherent(ddev, MLX5_ADAPTER_PAGE_SIZE,
+                                               &cmd->alloc_dma, GFP_KERNEL);
        if (!cmd->cmd_alloc_buf)
                return -ENOMEM;
 
@@ -1804,9 +1822,9 @@ static int alloc_cmd_page(struct mlx5_core_dev *dev, struct mlx5_cmd *cmd)
 
        dma_free_coherent(ddev, MLX5_ADAPTER_PAGE_SIZE, cmd->cmd_alloc_buf,
                          cmd->alloc_dma);
-       cmd->cmd_alloc_buf = dma_zalloc_coherent(ddev,
-                                                2 * MLX5_ADAPTER_PAGE_SIZE - 1,
-                                                &cmd->alloc_dma, GFP_KERNEL);
+       cmd->cmd_alloc_buf = dma_alloc_coherent(ddev,
+                                               2 * MLX5_ADAPTER_PAGE_SIZE - 1,
+                                               &cmd->alloc_dma, GFP_KERNEL);
        if (!cmd->cmd_alloc_buf)
                return -ENOMEM;
 
index 8fa8fdd..448a925 100644 (file)
@@ -657,6 +657,7 @@ struct mlx5e_channel_stats {
 enum {
        MLX5E_STATE_OPENED,
        MLX5E_STATE_DESTROYING,
+       MLX5E_STATE_XDP_TX_ENABLED,
 };
 
 struct mlx5e_rqt {
index 046948e..f3c7ab6 100644 (file)
@@ -256,6 +256,7 @@ int mlx5e_tc_tun_create_header_ipv4(struct mlx5e_priv *priv,
        e->m_neigh.family = n->ops->family;
        memcpy(&e->m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
        e->out_dev = out_dev;
+       e->route_dev = route_dev;
 
        /* It's important to add the neigh to the hash table before checking
         * the neigh validity state. So if we'll get a notification, in case the
@@ -369,6 +370,7 @@ int mlx5e_tc_tun_create_header_ipv6(struct mlx5e_priv *priv,
        e->m_neigh.family = n->ops->family;
        memcpy(&e->m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
        e->out_dev = out_dev;
+       e->route_dev = route_dev;
 
        /* It's importent to add the neigh to the hash table before checking
         * the neigh validity state. So if we'll get a notification, in case the
@@ -612,16 +614,18 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev,
                       struct mlx5_flow_spec *spec,
                       struct tc_cls_flower_offload *f,
                       void *headers_c,
-                      void *headers_v)
+                      void *headers_v, u8 *match_level)
 {
        int tunnel_type;
        int err = 0;
 
        tunnel_type = mlx5e_tc_tun_get_type(filter_dev);
        if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_VXLAN) {
+               *match_level = MLX5_MATCH_L4;
                err = mlx5e_tc_tun_parse_vxlan(priv, spec, f,
                                               headers_c, headers_v);
        } else if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_GRETAP) {
+               *match_level = MLX5_MATCH_L3;
                err = mlx5e_tc_tun_parse_gretap(priv, spec, f,
                                                headers_c, headers_v);
        } else {
index 706ce7b..b63f15d 100644 (file)
@@ -39,6 +39,6 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev,
                       struct mlx5_flow_spec *spec,
                       struct tc_cls_flower_offload *f,
                       void *headers_c,
-                      void *headers_v);
+                      void *headers_v, u8 *match_level);
 
 #endif //__MLX5_EN_TC_TUNNEL_H__
index 3740177..03b2a9f 100644 (file)
@@ -365,7 +365,8 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
        int sq_num;
        int i;
 
-       if (unlikely(!test_bit(MLX5E_STATE_OPENED, &priv->state)))
+       /* this flag is sufficient, no need to test internal sq state */
+       if (unlikely(!mlx5e_xdp_tx_is_enabled(priv)))
                return -ENETDOWN;
 
        if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
@@ -378,9 +379,6 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
 
        sq = &priv->channels.c[sq_num]->xdpsq;
 
-       if (unlikely(!test_bit(MLX5E_SQ_STATE_ENABLED, &sq->state)))
-               return -ENETDOWN;
-
        for (i = 0; i < n; i++) {
                struct xdp_frame *xdpf = frames[i];
                struct mlx5e_xdp_info xdpi;
index 3a67cb3..ee27a7c 100644 (file)
@@ -50,6 +50,23 @@ void mlx5e_xdp_rx_poll_complete(struct mlx5e_rq *rq);
 int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
                   u32 flags);
 
+static inline void mlx5e_xdp_tx_enable(struct mlx5e_priv *priv)
+{
+       set_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
+}
+
+static inline void mlx5e_xdp_tx_disable(struct mlx5e_priv *priv)
+{
+       clear_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
+       /* let other device's napi(s) see our new state */
+       synchronize_rcu();
+}
+
+static inline bool mlx5e_xdp_tx_is_enabled(struct mlx5e_priv *priv)
+{
+       return test_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
+}
+
 static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_xdpsq *sq)
 {
        if (sq->doorbell_cseg) {
index c9df081..47233b9 100644 (file)
@@ -354,9 +354,6 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
 
        new_channels.params = priv->channels.params;
        new_channels.params.num_channels = count;
-       if (!netif_is_rxfh_configured(priv->netdev))
-               mlx5e_build_default_indir_rqt(priv->rss_params.indirection_rqt,
-                                             MLX5E_INDIR_RQT_SIZE, count);
 
        if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
                priv->channels.params = new_channels.params;
@@ -372,6 +369,10 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
        if (arfs_enabled)
                mlx5e_arfs_disable(priv);
 
+       if (!netif_is_rxfh_configured(priv->netdev))
+               mlx5e_build_default_indir_rqt(priv->rss_params.indirection_rqt,
+                                             MLX5E_INDIR_RQT_SIZE, count);
+
        /* Switch to new channels, set new parameters and close old ones */
        mlx5e_switch_priv_channels(priv, &new_channels, NULL);
 
@@ -844,9 +845,12 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
        ethtool_link_ksettings_add_link_mode(link_ksettings, supported,
                                             Autoneg);
 
-       if (get_fec_supported_advertised(mdev, link_ksettings))
+       err = get_fec_supported_advertised(mdev, link_ksettings);
+       if (err) {
                netdev_dbg(priv->netdev, "%s: FEC caps query failed: %d\n",
                           __func__, err);
+               err = 0; /* don't fail caps query because of FEC error */
+       }
 
        if (!an_disable_admin)
                ethtool_link_ksettings_add_link_mode(link_ksettings,
index 8cfd2ec..93e50cc 100644 (file)
@@ -950,7 +950,7 @@ static int mlx5e_open_rq(struct mlx5e_channel *c,
        if (params->rx_dim_enabled)
                __set_bit(MLX5E_RQ_STATE_AM, &c->rq.state);
 
-       if (params->pflags & MLX5E_PFLAG_RX_NO_CSUM_COMPLETE)
+       if (MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_NO_CSUM_COMPLETE))
                __set_bit(MLX5E_RQ_STATE_NO_CSUM_COMPLETE, &c->rq.state);
 
        return 0;
@@ -2938,6 +2938,7 @@ void mlx5e_activate_priv_channels(struct mlx5e_priv *priv)
 
        mlx5e_build_tx2sq_maps(priv);
        mlx5e_activate_channels(&priv->channels);
+       mlx5e_xdp_tx_enable(priv);
        netif_tx_start_all_queues(priv->netdev);
 
        if (mlx5e_is_vport_rep(priv))
@@ -2959,6 +2960,7 @@ void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv)
         */
        netif_tx_stop_all_queues(priv->netdev);
        netif_tx_disable(priv->netdev);
+       mlx5e_xdp_tx_disable(priv);
        mlx5e_deactivate_channels(&priv->channels);
 }
 
index 96cc0c6..ef9e472 100644 (file)
@@ -58,7 +58,8 @@ struct mlx5e_rep_indr_block_priv {
        struct list_head list;
 };
 
-static void mlx5e_rep_indr_unregister_block(struct net_device *netdev);
+static void mlx5e_rep_indr_unregister_block(struct mlx5e_rep_priv *rpriv,
+                                           struct net_device *netdev);
 
 static void mlx5e_rep_get_drvinfo(struct net_device *dev,
                                  struct ethtool_drvinfo *drvinfo)
@@ -179,6 +180,7 @@ static void mlx5e_rep_update_sw_counters(struct mlx5e_priv *priv)
 
                        s->tx_packets           += sq_stats->packets;
                        s->tx_bytes             += sq_stats->bytes;
+                       s->tx_queue_dropped     += sq_stats->dropped;
                }
        }
 }
@@ -594,6 +596,10 @@ static void mlx5e_rep_update_flows(struct mlx5e_priv *priv,
        if (neigh_connected && !(e->flags & MLX5_ENCAP_ENTRY_VALID)) {
                ether_addr_copy(e->h_dest, ha);
                ether_addr_copy(eth->h_dest, ha);
+               /* Update the encap source mac, in case that we delete
+                * the flows when encap source mac changed.
+                */
+               ether_addr_copy(eth->h_source, e->route_dev->dev_addr);
 
                mlx5e_tc_encap_flows_add(priv, e);
        }
@@ -663,7 +669,7 @@ static void mlx5e_rep_indr_clean_block_privs(struct mlx5e_rep_priv *rpriv)
        struct list_head *head = &rpriv->uplink_priv.tc_indr_block_priv_list;
 
        list_for_each_entry_safe(cb_priv, temp, head, list) {
-               mlx5e_rep_indr_unregister_block(cb_priv->netdev);
+               mlx5e_rep_indr_unregister_block(rpriv, cb_priv->netdev);
                kfree(cb_priv);
        }
 }
@@ -735,7 +741,7 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
 
                err = tcf_block_cb_register(f->block,
                                            mlx5e_rep_indr_setup_block_cb,
-                                           netdev, indr_priv, f->extack);
+                                           indr_priv, indr_priv, f->extack);
                if (err) {
                        list_del(&indr_priv->list);
                        kfree(indr_priv);
@@ -743,14 +749,15 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
 
                return err;
        case TC_BLOCK_UNBIND:
+               indr_priv = mlx5e_rep_indr_block_priv_lookup(rpriv, netdev);
+               if (!indr_priv)
+                       return -ENOENT;
+
                tcf_block_cb_unregister(f->block,
                                        mlx5e_rep_indr_setup_block_cb,
-                                       netdev);
-               indr_priv = mlx5e_rep_indr_block_priv_lookup(rpriv, netdev);
-               if (indr_priv) {
-                       list_del(&indr_priv->list);
-                       kfree(indr_priv);
-               }
+                                       indr_priv);
+               list_del(&indr_priv->list);
+               kfree(indr_priv);
 
                return 0;
        default:
@@ -779,7 +786,7 @@ static int mlx5e_rep_indr_register_block(struct mlx5e_rep_priv *rpriv,
 
        err = __tc_indr_block_cb_register(netdev, rpriv,
                                          mlx5e_rep_indr_setup_tc_cb,
-                                         netdev);
+                                         rpriv);
        if (err) {
                struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
 
@@ -789,10 +796,11 @@ static int mlx5e_rep_indr_register_block(struct mlx5e_rep_priv *rpriv,
        return err;
 }
 
-static void mlx5e_rep_indr_unregister_block(struct net_device *netdev)
+static void mlx5e_rep_indr_unregister_block(struct mlx5e_rep_priv *rpriv,
+                                           struct net_device *netdev)
 {
        __tc_indr_block_cb_unregister(netdev, mlx5e_rep_indr_setup_tc_cb,
-                                     netdev);
+                                     rpriv);
 }
 
 static int mlx5e_nic_rep_netdevice_event(struct notifier_block *nb,
@@ -811,7 +819,7 @@ static int mlx5e_nic_rep_netdevice_event(struct notifier_block *nb,
                mlx5e_rep_indr_register_block(rpriv, netdev);
                break;
        case NETDEV_UNREGISTER:
-               mlx5e_rep_indr_unregister_block(netdev);
+               mlx5e_rep_indr_unregister_block(rpriv, netdev);
                break;
        }
        return NOTIFY_OK;
@@ -1122,9 +1130,17 @@ static int mlx5e_rep_get_phys_port_name(struct net_device *dev,
        struct mlx5e_priv *priv = netdev_priv(dev);
        struct mlx5e_rep_priv *rpriv = priv->ppriv;
        struct mlx5_eswitch_rep *rep = rpriv->rep;
-       int ret;
+       int ret, pf_num;
+
+       ret = mlx5_lag_get_pf_num(priv->mdev, &pf_num);
+       if (ret)
+               return ret;
+
+       if (rep->vport == FDB_UPLINK_VPORT)
+               ret = snprintf(buf, len, "p%d", pf_num);
+       else
+               ret = snprintf(buf, len, "pf%dvf%d", pf_num, rep->vport - 1);
 
-       ret = snprintf(buf, len, "%d", rep->vport - 1);
        if (ret >= len)
                return -EOPNOTSUPP;
 
@@ -1281,6 +1297,18 @@ static int mlx5e_uplink_rep_set_mac(struct net_device *netdev, void *addr)
        return 0;
 }
 
+static int mlx5e_uplink_rep_set_vf_vlan(struct net_device *dev, int vf, u16 vlan, u8 qos,
+                                       __be16 vlan_proto)
+{
+       netdev_warn_once(dev, "legacy vf vlan setting isn't supported in switchdev mode\n");
+
+       if (vlan != 0)
+               return -EOPNOTSUPP;
+
+       /* allow setting 0-vid for compatibility with libvirt */
+       return 0;
+}
+
 static const struct switchdev_ops mlx5e_rep_switchdev_ops = {
        .switchdev_port_attr_get        = mlx5e_attr_get,
 };
@@ -1315,6 +1343,7 @@ static const struct net_device_ops mlx5e_netdev_ops_uplink_rep = {
        .ndo_set_vf_rate         = mlx5e_set_vf_rate,
        .ndo_get_vf_config       = mlx5e_get_vf_config,
        .ndo_get_vf_stats        = mlx5e_get_vf_stats,
+       .ndo_set_vf_vlan         = mlx5e_uplink_rep_set_vf_vlan,
 };
 
 bool mlx5e_eswitch_rep(struct net_device *netdev)
index edd7228..36eafc8 100644 (file)
@@ -148,6 +148,7 @@ struct mlx5e_encap_entry {
        unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
 
        struct net_device *out_dev;
+       struct net_device *route_dev;
        int tunnel_type;
        int tunnel_hlen;
        int reformat_type;
index 1d0bb5f..f86e480 100644 (file)
@@ -732,6 +732,8 @@ static u8 get_ip_proto(struct sk_buff *skb, int network_depth, __be16 proto)
                                            ((struct ipv6hdr *)ip_p)->nexthdr;
 }
 
+#define short_frame(size) ((size) <= ETH_ZLEN + ETH_FCS_LEN)
+
 static inline void mlx5e_handle_csum(struct net_device *netdev,
                                     struct mlx5_cqe64 *cqe,
                                     struct mlx5e_rq *rq,
@@ -754,6 +756,17 @@ static inline void mlx5e_handle_csum(struct net_device *netdev,
        if (unlikely(test_bit(MLX5E_RQ_STATE_NO_CSUM_COMPLETE, &rq->state)))
                goto csum_unnecessary;
 
+       /* CQE csum doesn't cover padding octets in short ethernet
+        * frames. And the pad field is appended prior to calculating
+        * and appending the FCS field.
+        *
+        * Detecting these padded frames requires to verify and parse
+        * IP headers, so we simply force all those small frames to be
+        * CHECKSUM_UNNECESSARY even if they are not padded.
+        */
+       if (short_frame(skb->len))
+               goto csum_unnecessary;
+
        if (likely(is_last_ethertype_ip(skb, &network_depth, &proto))) {
                if (unlikely(get_ip_proto(skb, network_depth, proto) == IPPROTO_SCTP))
                        goto csum_unnecessary;
index cae6c6d..b5c1b03 100644 (file)
@@ -128,6 +128,7 @@ struct mlx5e_tc_flow_parse_attr {
        struct net_device *filter_dev;
        struct mlx5_flow_spec spec;
        int num_mod_hdr_actions;
+       int max_mod_hdr_actions;
        void *mod_hdr_actions;
        int mirred_ifindex[MLX5_MAX_FLOW_FWD_VPORTS];
 };
@@ -1302,7 +1303,7 @@ static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
 static int parse_tunnel_attr(struct mlx5e_priv *priv,
                             struct mlx5_flow_spec *spec,
                             struct tc_cls_flower_offload *f,
-                            struct net_device *filter_dev)
+                            struct net_device *filter_dev, u8 *match_level)
 {
        struct netlink_ext_ack *extack = f->common.extack;
        void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
@@ -1317,7 +1318,7 @@ static int parse_tunnel_attr(struct mlx5e_priv *priv,
        int err = 0;
 
        err = mlx5e_tc_tun_parse(filter_dev, priv, spec, f,
-                                headers_c, headers_v);
+                                headers_c, headers_v, match_level);
        if (err) {
                NL_SET_ERR_MSG_MOD(extack,
                                   "failed to parse tunnel attributes");
@@ -1426,7 +1427,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                              struct mlx5_flow_spec *spec,
                              struct tc_cls_flower_offload *f,
                              struct net_device *filter_dev,
-                             u8 *match_level)
+                             u8 *match_level, u8 *tunnel_match_level)
 {
        struct netlink_ext_ack *extack = f->common.extack;
        void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
@@ -1477,7 +1478,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                switch (key->addr_type) {
                case FLOW_DISSECTOR_KEY_IPV4_ADDRS:
                case FLOW_DISSECTOR_KEY_IPV6_ADDRS:
-                       if (parse_tunnel_attr(priv, spec, f, filter_dev))
+                       if (parse_tunnel_attr(priv, spec, f, filter_dev, tunnel_match_level))
                                return -EOPNOTSUPP;
                        break;
                default:
@@ -1826,11 +1827,11 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
        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;
-       u8 match_level;
        int err;
 
-       err = __parse_cls_flower(priv, spec, f, filter_dev, &match_level);
+       err = __parse_cls_flower(priv, spec, f, filter_dev, &match_level, &tunnel_match_level);
 
        if (!err && (flow->flags & MLX5E_TC_FLOW_ESWITCH)) {
                rep = rpriv->rep;
@@ -1846,10 +1847,12 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
                }
        }
 
-       if (flow->flags & MLX5E_TC_FLOW_ESWITCH)
+       if (flow->flags & MLX5E_TC_FLOW_ESWITCH) {
                flow->esw_attr->match_level = match_level;
-       else
+               flow->esw_attr->tunnel_match_level = tunnel_match_level;
+       } else {
                flow->nic_attr->match_level = match_level;
+       }
 
        return err;
 }
@@ -1934,9 +1937,9 @@ static struct mlx5_fields fields[] = {
        OFFLOAD(UDP_DPORT, 2, udp.dest,   0),
 };
 
-/* On input attr->num_mod_hdr_actions tells how many HW actions can be parsed at
- * max from the SW pedit action. On success, it says how many HW actions were
- * actually parsed.
+/* On input attr->max_mod_hdr_actions tells how many HW actions can be parsed at
+ * max from the SW pedit action. On success, attr->num_mod_hdr_actions
+ * says how many HW actions were actually parsed.
  */
 static int offload_pedit_fields(struct pedit_headers *masks,
                                struct pedit_headers *vals,
@@ -1960,9 +1963,11 @@ static int offload_pedit_fields(struct pedit_headers *masks,
        add_vals = &vals[TCA_PEDIT_KEY_EX_CMD_ADD];
 
        action_size = MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto);
-       action = parse_attr->mod_hdr_actions;
-       max_actions = parse_attr->num_mod_hdr_actions;
-       nactions = 0;
+       action = parse_attr->mod_hdr_actions +
+                parse_attr->num_mod_hdr_actions * action_size;
+
+       max_actions = parse_attr->max_mod_hdr_actions;
+       nactions = parse_attr->num_mod_hdr_actions;
 
        for (i = 0; i < ARRAY_SIZE(fields); i++) {
                f = &fields[i];
@@ -2073,7 +2078,7 @@ static int alloc_mod_hdr_actions(struct mlx5e_priv *priv,
        if (!parse_attr->mod_hdr_actions)
                return -ENOMEM;
 
-       parse_attr->num_mod_hdr_actions = max_actions;
+       parse_attr->max_mod_hdr_actions = max_actions;
        return 0;
 }
 
@@ -2119,9 +2124,11 @@ static int parse_tc_pedit_action(struct mlx5e_priv *priv,
                        goto out_err;
        }
 
-       err = alloc_mod_hdr_actions(priv, a, namespace, parse_attr);
-       if (err)
-               goto out_err;
+       if (!parse_attr->mod_hdr_actions) {
+               err = alloc_mod_hdr_actions(priv, a, namespace, parse_attr);
+               if (err)
+                       goto out_err;
+       }
 
        err = offload_pedit_fields(masks, vals, parse_attr, extack);
        if (err < 0)
@@ -2179,6 +2186,7 @@ static bool csum_offload_supported(struct mlx5e_priv *priv,
 
 static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
                                          struct tcf_exts *exts,
+                                         u32 actions,
                                          struct netlink_ext_ack *extack)
 {
        const struct tc_action *a;
@@ -2188,7 +2196,11 @@ static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
        u16 ethertype;
        int nkeys, i;
 
-       headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers);
+       if (actions & MLX5_FLOW_CONTEXT_ACTION_DECAP)
+               headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, inner_headers);
+       else
+               headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers);
+
        ethertype = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ethertype);
 
        /* for non-IP we only re-write MACs, so we're okay */
@@ -2245,7 +2257,7 @@ static bool actions_match_supported(struct mlx5e_priv *priv,
 
        if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
                return modify_header_match_supported(&parse_attr->spec, exts,
-                                                    extack);
+                                                    actions, extack);
 
        return true;
 }
index 598ad7e..0e55cd1 100644 (file)
@@ -387,8 +387,14 @@ netdev_tx_t mlx5e_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb,
        num_wqebbs = DIV_ROUND_UP(ds_cnt, MLX5_SEND_WQEBB_NUM_DS);
        contig_wqebbs_room = mlx5_wq_cyc_get_contig_wqebbs(wq, pi);
        if (unlikely(contig_wqebbs_room < num_wqebbs)) {
+#ifdef CONFIG_MLX5_EN_IPSEC
+               struct mlx5_wqe_eth_seg cur_eth = wqe->eth;
+#endif
                mlx5e_fill_sq_frag_edge(sq, wq, pi, contig_wqebbs_room);
                mlx5e_sq_fetch_wqe(sq, &wqe, &pi);
+#ifdef CONFIG_MLX5_EN_IPSEC
+               wqe->eth = cur_eth;
+#endif
        }
 
        /* fill wqe */
index a44ea7b..5b492b6 100644 (file)
@@ -1134,13 +1134,6 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
        int err = 0;
        u8 *smac_v;
 
-       if (vport->info.spoofchk && !is_valid_ether_addr(vport->info.mac)) {
-               mlx5_core_warn(esw->dev,
-                              "vport[%d] configure ingress rules failed, illegal mac with spoofchk\n",
-                              vport->vport);
-               return -EPERM;
-       }
-
        esw_vport_cleanup_ingress_rules(esw, vport);
 
        if (!vport->info.vlan && !vport->info.qos && !vport->info.spoofchk) {
@@ -1728,7 +1721,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
        int vport_num;
        int err;
 
-       if (!MLX5_ESWITCH_MANAGER(dev))
+       if (!MLX5_VPORT_MANAGER(dev))
                return 0;
 
        esw_info(dev,
@@ -1797,7 +1790,7 @@ abort:
 
 void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
 {
-       if (!esw || !MLX5_ESWITCH_MANAGER(esw->dev))
+       if (!esw || !MLX5_VPORT_MANAGER(esw->dev))
                return;
 
        esw_info(esw->dev, "cleanup\n");
@@ -1827,13 +1820,10 @@ int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
        mutex_lock(&esw->state_lock);
        evport = &esw->vports[vport];
 
-       if (evport->info.spoofchk && !is_valid_ether_addr(mac)) {
+       if (evport->info.spoofchk && !is_valid_ether_addr(mac))
                mlx5_core_warn(esw->dev,
-                              "MAC invalidation is not allowed when spoofchk is on, vport(%d)\n",
+                              "Set invalid MAC while spoofchk is on, vport(%d)\n",
                               vport);
-               err = -EPERM;
-               goto unlock;
-       }
 
        err = mlx5_modify_nic_vport_mac_address(esw->dev, vport, mac);
        if (err) {
@@ -1979,6 +1969,10 @@ int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
        evport = &esw->vports[vport];
        pschk = evport->info.spoofchk;
        evport->info.spoofchk = spoofchk;
+       if (pschk && !is_valid_ether_addr(evport->info.mac))
+               mlx5_core_warn(esw->dev,
+                              "Spoofchk in set while MAC is invalid, vport(%d)\n",
+                              evport->vport);
        if (evport->enabled && esw->mode == SRIOV_LEGACY)
                err = esw_vport_ingress_config(esw, evport);
        if (err)
index 9c89eea..748ff17 100644 (file)
@@ -312,6 +312,7 @@ struct mlx5_esw_flow_attr {
        } dests[MLX5_MAX_FLOW_FWD_VPORTS];
        u32     mod_hdr_id;
        u8      match_level;
+       u8      tunnel_match_level;
        struct mlx5_fc *counter;
        u32     chain;
        u16     prio;
index 53065b6..d4e6fe5 100644 (file)
@@ -160,14 +160,15 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
                MLX5_SET_TO_ONES(fte_match_set_misc, misc,
                                 source_eswitch_owner_vhca_id);
 
-       if (attr->match_level == MLX5_MATCH_NONE)
-               spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
-       else
-               spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS |
-                                             MLX5_MATCH_MISC_PARAMETERS;
-
-       if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP)
-               spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
+       spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
+       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) {
+               spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
+       }
 
        if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
                flow_act.modify_id = attr->mod_hdr_id;
index fbc42b7..5030354 100644 (file)
@@ -211,11 +211,10 @@ static int port_module(struct notifier_block *nb, unsigned long type, void *data
        enum port_module_event_status_type module_status;
        enum port_module_event_error_type error_type;
        struct mlx5_eqe_port_module *module_event_eqe;
-       const char *status_str, *error_str;
+       const char *status_str;
        u8 module_num;
 
        module_event_eqe = &eqe->data.port_module;
-       module_num = module_event_eqe->module;
        module_status = module_event_eqe->module_status &
                        PORT_MODULE_EVENT_MODULE_STATUS_MASK;
        error_type = module_event_eqe->error_type &
@@ -223,25 +222,27 @@ static int port_module(struct notifier_block *nb, unsigned long type, void *data
 
        if (module_status < MLX5_MODULE_STATUS_NUM)
                events->pme_stats.status_counters[module_status]++;
-       status_str = mlx5_pme_status_to_string(module_status);
 
-       if (module_status == MLX5_MODULE_STATUS_ERROR) {
+       if (module_status == MLX5_MODULE_STATUS_ERROR)
                if (error_type < MLX5_MODULE_EVENT_ERROR_NUM)
                        events->pme_stats.error_counters[error_type]++;
-               error_str = mlx5_pme_error_to_string(error_type);
-       }
 
        if (!printk_ratelimit())
                return NOTIFY_OK;
 
-       if (module_status == MLX5_MODULE_STATUS_ERROR)
+       module_num = module_event_eqe->module;
+       status_str = mlx5_pme_status_to_string(module_status);
+       if (module_status == MLX5_MODULE_STATUS_ERROR) {
+               const char *error_str = mlx5_pme_error_to_string(error_type);
+
                mlx5_core_err(events->dev,
                              "Port module event[error]: module %u, %s, %s\n",
                              module_num, status_str, error_str);
-       else
+       } else {
                mlx5_core_info(events->dev,
                               "Port module event: module %u, %s\n",
                               module_num, status_str);
+       }
 
        return NOTIFY_OK;
 }
index 196c073..cb9fa34 100644 (file)
@@ -103,7 +103,7 @@ void mlx5_enter_error_state(struct mlx5_core_dev *dev, bool force)
        mlx5_core_err(dev, "start\n");
        if (pci_channel_offline(dev->pdev) || in_fatal(dev) || force) {
                dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
-               mlx5_cmd_trigger_completions(dev);
+               mlx5_cmd_flush(dev);
        }
 
        mlx5_notifier_call_chain(dev->priv.events, MLX5_DEV_EVENT_SYS_ERROR, (void *)1);
index 3a6baed..2d22338 100644 (file)
@@ -616,6 +616,27 @@ void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev)
        }
 }
 
+int mlx5_lag_get_pf_num(struct mlx5_core_dev *dev, int *pf_num)
+{
+       struct mlx5_lag *ldev;
+       int n;
+
+       ldev = mlx5_lag_dev_get(dev);
+       if (!ldev) {
+               mlx5_core_warn(dev, "no lag device, can't get pf num\n");
+               return -EINVAL;
+       }
+
+       for (n = 0; n < MLX5_MAX_PORTS; n++)
+               if (ldev->pf[n].dev == dev) {
+                       *pf_num = n;
+                       return 0;
+               }
+
+       mlx5_core_warn(dev, "wasn't able to locate pf in the lag device\n");
+       return -EINVAL;
+}
+
 /* Must be called with intf_mutex held */
 void mlx5_lag_remove(struct mlx5_core_dev *dev)
 {
index c68dcea..4fdac02 100644 (file)
@@ -126,6 +126,7 @@ u64 mlx5_read_internal_timer(struct mlx5_core_dev *dev,
                             struct ptp_system_timestamp *sts);
 
 void mlx5_cmd_trigger_completions(struct mlx5_core_dev *dev);
+void mlx5_cmd_flush(struct mlx5_core_dev *dev);
 int mlx5_cq_debugfs_init(struct mlx5_core_dev *dev);
 void mlx5_cq_debugfs_cleanup(struct mlx5_core_dev *dev);
 
@@ -187,6 +188,8 @@ static inline int mlx5_lag_is_lacp_owner(struct mlx5_core_dev *dev)
                    MLX5_CAP_GEN(dev, lag_master);
 }
 
+int mlx5_lag_get_pf_num(struct mlx5_core_dev *dev, int *pf_num);
+
 void mlx5_reload_interface(struct mlx5_core_dev *mdev, int protocol);
 void mlx5_lag_update(struct mlx5_core_dev *dev);
 
index 388f205..370ca94 100644 (file)
@@ -44,14 +44,15 @@ static struct mlx5_core_rsc_common *
 mlx5_get_rsc(struct mlx5_qp_table *table, u32 rsn)
 {
        struct mlx5_core_rsc_common *common;
+       unsigned long flags;
 
-       spin_lock(&table->lock);
+       spin_lock_irqsave(&table->lock, flags);
 
        common = radix_tree_lookup(&table->tree, rsn);
        if (common)
                atomic_inc(&common->refcount);
 
-       spin_unlock(&table->lock);
+       spin_unlock_irqrestore(&table->lock, flags);
 
        return common;
 }
index 080ddd1..b9a25ae 100644 (file)
@@ -78,6 +78,7 @@ config MLXSW_SPECTRUM
        depends on IPV6 || IPV6=n
        depends on NET_IPGRE || NET_IPGRE=n
        depends on IPV6_GRE || IPV6_GRE=n
+       depends on VXLAN || VXLAN=n
        select GENERIC_ALLOCATOR
        select PARMAN
        select OBJAGG
index 66b8098..a2321fe 100644 (file)
@@ -604,29 +604,31 @@ static void mlxsw_pci_cq_tasklet(unsigned long data)
                u16 wqe_counter = mlxsw_pci_cqe_wqe_counter_get(cqe);
                u8 sendq = mlxsw_pci_cqe_sr_get(q->u.cq.v, cqe);
                u8 dqn = mlxsw_pci_cqe_dqn_get(q->u.cq.v, cqe);
+               char ncqe[MLXSW_PCI_CQE_SIZE_MAX];
+
+               memcpy(ncqe, cqe, q->elem_size);
+               mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q);
 
                if (sendq) {
                        struct mlxsw_pci_queue *sdq;
 
                        sdq = mlxsw_pci_sdq_get(mlxsw_pci, dqn);
                        mlxsw_pci_cqe_sdq_handle(mlxsw_pci, sdq,
-                                                wqe_counter, cqe);
+                                                wqe_counter, ncqe);
                        q->u.cq.comp_sdq_count++;
                } else {
                        struct mlxsw_pci_queue *rdq;
 
                        rdq = mlxsw_pci_rdq_get(mlxsw_pci, dqn);
                        mlxsw_pci_cqe_rdq_handle(mlxsw_pci, rdq,
-                                                wqe_counter, q->u.cq.v, cqe);
+                                                wqe_counter, q->u.cq.v, ncqe);
                        q->u.cq.comp_rdq_count++;
                }
                if (++items == credits)
                        break;
        }
-       if (items) {
-               mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q);
+       if (items)
                mlxsw_pci_queue_doorbell_arm_consumer_ring(mlxsw_pci, q);
-       }
 }
 
 static u16 mlxsw_pci_cq_elem_count(const struct mlxsw_pci_queue *q)
@@ -1365,10 +1367,10 @@ static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci,
                u32 val = mlxsw_pci_read32(mlxsw_pci, FW_READY);
 
                if ((val & MLXSW_PCI_FW_READY_MASK) == MLXSW_PCI_FW_READY_MAGIC)
-                       break;
+                       return 0;
                cond_resched();
        } while (time_before(jiffies, end));
-       return 0;
+       return -EBUSY;
 }
 
 static int mlxsw_pci_alloc_irq_vectors(struct mlxsw_pci *mlxsw_pci)
index bb99f6d..ffee38e 100644 (file)
@@ -27,7 +27,7 @@
 
 #define MLXSW_PCI_SW_RESET                     0xF0010
 #define MLXSW_PCI_SW_RESET_RST_BIT             BIT(0)
-#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS       5000
+#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS       13000
 #define MLXSW_PCI_SW_RESET_WAIT_MSECS          100
 #define MLXSW_PCI_FW_READY                     0xA1844
 #define MLXSW_PCI_FW_READY_MASK                        0xFFFF
@@ -53,6 +53,7 @@
 #define MLXSW_PCI_WQE_SIZE     32 /* 32 bytes per element */
 #define MLXSW_PCI_CQE01_SIZE   16 /* 16 bytes per element */
 #define MLXSW_PCI_CQE2_SIZE    32 /* 32 bytes per element */
+#define MLXSW_PCI_CQE_SIZE_MAX MLXSW_PCI_CQE2_SIZE
 #define MLXSW_PCI_EQE_SIZE     16 /* 16 bytes per element */
 #define MLXSW_PCI_WQE_COUNT    (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_WQE_SIZE)
 #define MLXSW_PCI_CQE01_COUNT  (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_CQE01_SIZE)
index eed1045..32519c9 100644 (file)
@@ -5005,12 +5005,15 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
                                                           lower_dev,
                                                           upper_dev);
                } else if (netif_is_lag_master(upper_dev)) {
-                       if (info->linking)
+                       if (info->linking) {
                                err = mlxsw_sp_port_lag_join(mlxsw_sp_port,
                                                             upper_dev);
-                       else
+                       } else {
+                               mlxsw_sp_port_lag_tx_en_set(mlxsw_sp_port,
+                                                           false);
                                mlxsw_sp_port_lag_leave(mlxsw_sp_port,
                                                        upper_dev);
+                       }
                } else if (netif_is_ovs_master(upper_dev)) {
                        if (info->linking)
                                err = mlxsw_sp_port_ovs_join(mlxsw_sp_port);
index b0f2d8e..ac22283 100644 (file)
@@ -72,7 +72,15 @@ mlxsw_sp_acl_ctcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp,
        act_set = mlxsw_afa_block_first_set(rulei->act_block);
        mlxsw_reg_ptce2_flex_action_set_memcpy_to(ptce2_pl, act_set);
 
-       return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl);
+       err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl);
+       if (err)
+               goto err_ptce2_write;
+
+       return 0;
+
+err_ptce2_write:
+       cregion->ops->entry_remove(cregion, centry);
+       return err;
 }
 
 static void
index 1c19fee..2941967 100644 (file)
@@ -1022,7 +1022,6 @@ void mlxsw_sp_acl_erp_mask_put(struct mlxsw_sp_acl_atcam_region *aregion,
 {
        struct objagg_obj *objagg_obj = (struct objagg_obj *) erp_mask;
 
-       ASSERT_RTNL();
        objagg_obj_put(aregion->erp_table->objagg, objagg_obj);
 }
 
@@ -1054,7 +1053,6 @@ void mlxsw_sp_acl_erp_bf_remove(struct mlxsw_sp *mlxsw_sp,
        const struct mlxsw_sp_acl_erp *erp = objagg_obj_root_priv(objagg_obj);
        unsigned int erp_bank;
 
-       ASSERT_RTNL();
        if (!mlxsw_sp_acl_erp_table_is_used(erp->erp_table))
                return;
 
index 055cc69..9d9aa28 100644 (file)
@@ -997,8 +997,8 @@ static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = {
 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_dummy_family = {
        .type                   = MLXSW_SP_FID_TYPE_DUMMY,
        .fid_size               = sizeof(struct mlxsw_sp_fid),
-       .start_index            = MLXSW_SP_RFID_BASE - 1,
-       .end_index              = MLXSW_SP_RFID_BASE - 1,
+       .start_index            = VLAN_N_VID - 1,
+       .end_index              = VLAN_N_VID - 1,
        .ops                    = &mlxsw_sp_fid_dummy_ops,
 };
 
index 0a31fff..fb1c48c 100644 (file)
@@ -816,14 +816,14 @@ int mlxsw_sp_nve_fid_enable(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fid *fid,
        ops = nve->nve_ops_arr[params->type];
 
        if (!ops->can_offload(nve, params->dev, extack))
-               return -EOPNOTSUPP;
+               return -EINVAL;
 
        memset(&config, 0, sizeof(config));
        ops->nve_config(nve, params->dev, &config);
        if (nve->num_nve_tunnels &&
            memcmp(&config, &nve->config, sizeof(config))) {
                NL_SET_ERR_MSG_MOD(extack, "Conflicting NVE tunnels configuration");
-               return -EOPNOTSUPP;
+               return -EINVAL;
        }
 
        err = mlxsw_sp_nve_tunnel_init(mlxsw_sp, &config);
index 1bd2c6e..c772109 100644 (file)
@@ -1078,8 +1078,7 @@ static int
 mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port,
                              struct mlxsw_sp_bridge_port *bridge_port,
                              u16 vid, bool is_untagged, bool is_pvid,
-                             struct netlink_ext_ack *extack,
-                             struct switchdev_trans *trans)
+                             struct netlink_ext_ack *extack)
 {
        u16 pvid = mlxsw_sp_port_pvid_determine(mlxsw_sp_port, vid, is_pvid);
        struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
@@ -1095,9 +1094,6 @@ mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port,
            mlxsw_sp_port_vlan->bridge_port != bridge_port)
                return -EEXIST;
 
-       if (switchdev_trans_ph_prepare(trans))
-               return 0;
-
        if (!mlxsw_sp_port_vlan) {
                mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_create(mlxsw_sp_port,
                                                               vid);
@@ -1188,6 +1184,9 @@ static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
                return err;
        }
 
+       if (switchdev_trans_ph_commit(trans))
+               return 0;
+
        bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
        if (WARN_ON(!bridge_port))
                return -EINVAL;
@@ -1200,7 +1199,7 @@ static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
 
                err = mlxsw_sp_bridge_port_vlan_add(mlxsw_sp_port, bridge_port,
                                                    vid, flag_untagged,
-                                                   flag_pvid, extack, trans);
+                                                   flag_pvid, extack);
                if (err)
                        return err;
        }
@@ -1234,7 +1233,7 @@ mlxsw_sp_bridge_port_fdb_flush(struct mlxsw_sp *mlxsw_sp,
 static enum mlxsw_reg_sfd_rec_policy mlxsw_sp_sfd_rec_policy(bool dynamic)
 {
        return dynamic ? MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_INGRESS :
-                        MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY;
+                        MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_MLAG;
 }
 
 static enum mlxsw_reg_sfd_op mlxsw_sp_sfd_op(bool adding)
@@ -1291,7 +1290,7 @@ out:
 static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
                                     const char *mac, u16 fid, bool adding,
                                     enum mlxsw_reg_sfd_rec_action action,
-                                    bool dynamic)
+                                    enum mlxsw_reg_sfd_rec_policy policy)
 {
        char *sfd_pl;
        u8 num_rec;
@@ -1302,8 +1301,7 @@ static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
                return -ENOMEM;
 
        mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0);
-       mlxsw_reg_sfd_uc_pack(sfd_pl, 0, mlxsw_sp_sfd_rec_policy(dynamic),
-                             mac, fid, action, local_port);
+       mlxsw_reg_sfd_uc_pack(sfd_pl, 0, policy, mac, fid, action, local_port);
        num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl);
        err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
        if (err)
@@ -1322,7 +1320,8 @@ static int mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
                                   bool dynamic)
 {
        return __mlxsw_sp_port_fdb_uc_op(mlxsw_sp, local_port, mac, fid, adding,
-                                        MLXSW_REG_SFD_REC_ACTION_NOP, dynamic);
+                                        MLXSW_REG_SFD_REC_ACTION_NOP,
+                                        mlxsw_sp_sfd_rec_policy(dynamic));
 }
 
 int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid,
@@ -1330,7 +1329,7 @@ int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid,
 {
        return __mlxsw_sp_port_fdb_uc_op(mlxsw_sp, 0, mac, fid, adding,
                                         MLXSW_REG_SFD_REC_ACTION_FORWARD_IP_ROUTER,
-                                        false);
+                                        MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY);
 }
 
 static int mlxsw_sp_port_fdb_uc_lag_op(struct mlxsw_sp *mlxsw_sp, u16 lag_id,
@@ -1808,7 +1807,7 @@ static void
 mlxsw_sp_bridge_port_vlan_del(struct mlxsw_sp_port *mlxsw_sp_port,
                              struct mlxsw_sp_bridge_port *bridge_port, u16 vid)
 {
-       u16 pvid = mlxsw_sp_port->pvid == vid ? 0 : vid;
+       u16 pvid = mlxsw_sp_port->pvid == vid ? 0 : mlxsw_sp_port->pvid;
        struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
 
        mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
@@ -3207,7 +3206,6 @@ mlxsw_sp_switchdev_vxlan_vlan_add(struct mlxsw_sp *mlxsw_sp,
                                  struct mlxsw_sp_bridge_device *bridge_device,
                                  const struct net_device *vxlan_dev, u16 vid,
                                  bool flag_untagged, bool flag_pvid,
-                                 struct switchdev_trans *trans,
                                  struct netlink_ext_ack *extack)
 {
        struct vxlan_dev *vxlan = netdev_priv(vxlan_dev);
@@ -3225,9 +3223,6 @@ mlxsw_sp_switchdev_vxlan_vlan_add(struct mlxsw_sp *mlxsw_sp,
            mlxsw_sp_bridge_8021q_vxlan_dev_find(bridge_device->dev, vid))
                return -EINVAL;
 
-       if (switchdev_trans_ph_prepare(trans))
-               return 0;
-
        if (!netif_running(vxlan_dev))
                return 0;
 
@@ -3345,6 +3340,9 @@ mlxsw_sp_switchdev_vxlan_vlans_add(struct net_device *vxlan_dev,
 
        port_obj_info->handled = true;
 
+       if (switchdev_trans_ph_commit(trans))
+               return 0;
+
        bridge_device = mlxsw_sp_bridge_device_find(mlxsw_sp->bridge, br_dev);
        if (!bridge_device)
                return -EINVAL;
@@ -3358,8 +3356,7 @@ mlxsw_sp_switchdev_vxlan_vlans_add(struct net_device *vxlan_dev,
                err = mlxsw_sp_switchdev_vxlan_vlan_add(mlxsw_sp, bridge_device,
                                                        vxlan_dev, vid,
                                                        flag_untagged,
-                                                       flag_pvid, trans,
-                                                       extack);
+                                                       flag_pvid, extack);
                if (err)
                        return err;
        }
index 20c9377..310807e 100644 (file)
@@ -962,13 +962,10 @@ static void lan743x_phy_link_status_change(struct net_device *netdev)
 
                memset(&ksettings, 0, sizeof(ksettings));
                phy_ethtool_get_link_ksettings(netdev, &ksettings);
-               local_advertisement = phy_read(phydev, MII_ADVERTISE);
-               if (local_advertisement < 0)
-                       return;
-
-               remote_advertisement = phy_read(phydev, MII_LPA);
-               if (remote_advertisement < 0)
-                       return;
+               local_advertisement =
+                       linkmode_adv_to_mii_adv_t(phydev->advertising);
+               remote_advertisement =
+                       linkmode_adv_to_mii_adv_t(phydev->lp_advertising);
 
                lan743x_phy_update_flowcontrol(adapter,
                                               ksettings.base.duplex,
index 5f384f7..19ce0e6 100644 (file)
@@ -3604,9 +3604,9 @@ static int myri10ge_alloc_slices(struct myri10ge_priv *mgp)
        for (i = 0; i < mgp->num_slices; i++) {
                ss = &mgp->ss[i];
                bytes = mgp->max_intr_slots * sizeof(*ss->rx_done.entry);
-               ss->rx_done.entry = dma_zalloc_coherent(&pdev->dev, bytes,
-                                                       &ss->rx_done.bus,
-                                                       GFP_KERNEL);
+               ss->rx_done.entry = dma_alloc_coherent(&pdev->dev, bytes,
+                                                      &ss->rx_done.bus,
+                                                      GFP_KERNEL);
                if (ss->rx_done.entry == NULL)
                        goto abort;
                bytes = sizeof(*ss->fw_stats);
index e97636d..7d2d424 100644 (file)
@@ -2170,9 +2170,9 @@ nfp_net_tx_ring_alloc(struct nfp_net_dp *dp, struct nfp_net_tx_ring *tx_ring)
        tx_ring->cnt = dp->txd_cnt;
 
        tx_ring->size = array_size(tx_ring->cnt, sizeof(*tx_ring->txds));
-       tx_ring->txds = dma_zalloc_coherent(dp->dev, tx_ring->size,
-                                           &tx_ring->dma,
-                                           GFP_KERNEL | __GFP_NOWARN);
+       tx_ring->txds = dma_alloc_coherent(dp->dev, tx_ring->size,
+                                          &tx_ring->dma,
+                                          GFP_KERNEL | __GFP_NOWARN);
        if (!tx_ring->txds) {
                netdev_warn(dp->netdev, "failed to allocate TX descriptor ring memory, requested descriptor count: %d, consider lowering descriptor count\n",
                            tx_ring->cnt);
@@ -2328,9 +2328,9 @@ nfp_net_rx_ring_alloc(struct nfp_net_dp *dp, struct nfp_net_rx_ring *rx_ring)
 
        rx_ring->cnt = dp->rxd_cnt;
        rx_ring->size = array_size(rx_ring->cnt, sizeof(*rx_ring->rxds));
-       rx_ring->rxds = dma_zalloc_coherent(dp->dev, rx_ring->size,
-                                           &rx_ring->dma,
-                                           GFP_KERNEL | __GFP_NOWARN);
+       rx_ring->rxds = dma_alloc_coherent(dp->dev, rx_ring->size,
+                                          &rx_ring->dma,
+                                          GFP_KERNEL | __GFP_NOWARN);
        if (!rx_ring->rxds) {
                netdev_warn(dp->netdev, "failed to allocate RX descriptor ring memory, requested descriptor count: %d, consider lowering descriptor count\n",
                            rx_ring->cnt);
index 0611f23..1e408d1 100644 (file)
@@ -287,9 +287,9 @@ static int nixge_hw_dma_bd_init(struct net_device *ndev)
        priv->rx_bd_ci = 0;
 
        /* Allocate the Tx and Rx buffer descriptors. */
-       priv->tx_bd_v = dma_zalloc_coherent(ndev->dev.parent,
-                                           sizeof(*priv->tx_bd_v) * TX_BD_NUM,
-                                           &priv->tx_bd_p, GFP_KERNEL);
+       priv->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+                                          sizeof(*priv->tx_bd_v) * TX_BD_NUM,
+                                          &priv->tx_bd_p, GFP_KERNEL);
        if (!priv->tx_bd_v)
                goto out;
 
@@ -299,9 +299,9 @@ static int nixge_hw_dma_bd_init(struct net_device *ndev)
        if (!priv->tx_skb)
                goto out;
 
-       priv->rx_bd_v = dma_zalloc_coherent(ndev->dev.parent,
-                                           sizeof(*priv->rx_bd_v) * RX_BD_NUM,
-                                           &priv->rx_bd_p, GFP_KERNEL);
+       priv->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+                                          sizeof(*priv->rx_bd_v) * RX_BD_NUM,
+                                          &priv->rx_bd_p, GFP_KERNEL);
        if (!priv->rx_bd_v)
                goto out;
 
index 43c0c10..552d930 100644 (file)
@@ -1440,8 +1440,8 @@ pch_gbe_alloc_rx_buffers_pool(struct pch_gbe_adapter *adapter,
 
        size = rx_ring->count * bufsz + PCH_GBE_RESERVE_MEMORY;
        rx_ring->rx_buff_pool =
-               dma_zalloc_coherent(&pdev->dev, size,
-                                   &rx_ring->rx_buff_pool_logic, GFP_KERNEL);
+               dma_alloc_coherent(&pdev->dev, size,
+                                  &rx_ring->rx_buff_pool_logic, GFP_KERNEL);
        if (!rx_ring->rx_buff_pool)
                return -ENOMEM;
 
@@ -1755,8 +1755,8 @@ int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter,
 
        tx_ring->size = tx_ring->count * (int)sizeof(struct pch_gbe_tx_desc);
 
-       tx_ring->desc = dma_zalloc_coherent(&pdev->dev, tx_ring->size,
-                                           &tx_ring->dma, GFP_KERNEL);
+       tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size,
+                                          &tx_ring->dma, GFP_KERNEL);
        if (!tx_ring->desc) {
                vfree(tx_ring->buffer_info);
                return -ENOMEM;
@@ -1798,8 +1798,8 @@ int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter,
                return -ENOMEM;
 
        rx_ring->size = rx_ring->count * (int)sizeof(struct pch_gbe_rx_desc);
-       rx_ring->desc = dma_zalloc_coherent(&pdev->dev, rx_ring->size,
-                                           &rx_ring->dma, GFP_KERNEL);
+       rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
+                                                 &rx_ring->dma, GFP_KERNEL);
        if (!rx_ring->desc) {
                vfree(rx_ring->buffer_info);
                return -ENOMEM;
index 8a31a02..d210415 100644 (file)
@@ -401,9 +401,9 @@ static int pasemi_mac_setup_rx_resources(const struct net_device *dev)
        if (pasemi_dma_alloc_ring(&ring->chan, RX_RING_SIZE))
                goto out_ring_desc;
 
-       ring->buffers = dma_zalloc_coherent(&mac->dma_pdev->dev,
-                                           RX_RING_SIZE * sizeof(u64),
-                                           &ring->buf_dma, GFP_KERNEL);
+       ring->buffers = dma_alloc_coherent(&mac->dma_pdev->dev,
+                                          RX_RING_SIZE * sizeof(u64),
+                                          &ring->buf_dma, GFP_KERNEL);
        if (!ring->buffers)
                goto out_ring_desc;
 
index 24a9016..2d8a77c 100644 (file)
@@ -53,7 +53,7 @@
 extern const struct qed_common_ops qed_common_ops_pass;
 
 #define QED_MAJOR_VERSION              8
-#define QED_MINOR_VERSION              33
+#define QED_MINOR_VERSION              37
 #define QED_REVISION_VERSION           0
 #define QED_ENGINEERING_VERSION                20
 
index dc1c1b6..c2ad405 100644 (file)
@@ -936,9 +936,9 @@ static int qed_cxt_src_t2_alloc(struct qed_hwfn *p_hwfn)
                u32 size = min_t(u32, total_size, psz);
                void **p_virt = &p_mngr->t2[i].p_virt;
 
-               *p_virt = dma_zalloc_coherent(&p_hwfn->cdev->pdev->dev,
-                                             size, &p_mngr->t2[i].p_phys,
-                                             GFP_KERNEL);
+               *p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, size,
+                                            &p_mngr->t2[i].p_phys,
+                                            GFP_KERNEL);
                if (!p_mngr->t2[i].p_virt) {
                        rc = -ENOMEM;
                        goto t2_fail;
@@ -1054,8 +1054,8 @@ static int qed_ilt_blk_alloc(struct qed_hwfn *p_hwfn,
                u32 size;
 
                size = min_t(u32, sz_left, p_blk->real_size_in_page);
-               p_virt = dma_zalloc_coherent(&p_hwfn->cdev->pdev->dev, size,
-                                            &p_phys, GFP_KERNEL);
+               p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, size,
+                                           &p_phys, GFP_KERNEL);
                if (!p_virt)
                        return -ENOMEM;
 
@@ -2306,9 +2306,9 @@ qed_cxt_dynamic_ilt_alloc(struct qed_hwfn *p_hwfn,
                goto out0;
        }
 
-       p_virt = dma_zalloc_coherent(&p_hwfn->cdev->pdev->dev,
-                                    p_blk->real_size_in_page, &p_phys,
-                                    GFP_KERNEL);
+       p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
+                                   p_blk->real_size_in_page, &p_phys,
+                                   GFP_KERNEL);
        if (!p_virt) {
                rc = -ENOMEM;
                goto out1;
index 8f65514..2ecaaaa 100644 (file)
@@ -795,19 +795,19 @@ static void qed_init_qm_pq(struct qed_hwfn *p_hwfn,
 
 /* get pq index according to PQ_FLAGS */
 static u16 *qed_init_qm_get_idx_from_flags(struct qed_hwfn *p_hwfn,
-                                          u32 pq_flags)
+                                          unsigned long pq_flags)
 {
        struct qed_qm_info *qm_info = &p_hwfn->qm_info;
 
        /* Can't have multiple flags set here */
-       if (bitmap_weight((unsigned long *)&pq_flags,
+       if (bitmap_weight(&pq_flags,
                          sizeof(pq_flags) * BITS_PER_BYTE) > 1) {
-               DP_ERR(p_hwfn, "requested multiple pq flags 0x%x\n", pq_flags);
+               DP_ERR(p_hwfn, "requested multiple pq flags 0x%lx\n", pq_flags);
                goto err;
        }
 
        if (!(qed_get_pq_flags(p_hwfn) & pq_flags)) {
-               DP_ERR(p_hwfn, "pq flag 0x%x is not set\n", pq_flags);
+               DP_ERR(p_hwfn, "pq flag 0x%lx is not set\n", pq_flags);
                goto err;
        }
 
index 67c02ea..58be1c4 100644 (file)
@@ -609,6 +609,10 @@ qed_sp_update_accept_mode(struct qed_hwfn *p_hwfn,
                          (!!(accept_filter & QED_ACCEPT_MCAST_MATCHED) &&
                           !!(accept_filter & QED_ACCEPT_MCAST_UNMATCHED)));
 
+               SET_FIELD(state, ETH_VPORT_TX_MODE_UCAST_ACCEPT_ALL,
+                         (!!(accept_filter & QED_ACCEPT_UCAST_MATCHED) &&
+                          !!(accept_filter & QED_ACCEPT_UCAST_UNMATCHED)));
+
                SET_FIELD(state, ETH_VPORT_TX_MODE_BCAST_ACCEPT_ALL,
                          !!(accept_filter & QED_ACCEPT_BCAST));
 
@@ -744,6 +748,11 @@ int qed_sp_vport_update(struct qed_hwfn *p_hwfn,
                return rc;
        }
 
+       if (p_params->update_ctl_frame_check) {
+               p_cmn->ctl_frame_mac_check_en = p_params->mac_chk_en;
+               p_cmn->ctl_frame_ethtype_check_en = p_params->ethtype_chk_en;
+       }
+
        /* Update mcast bins for VFs, PF doesn't use this functionality */
        qed_sp_update_mcast_bin(p_hwfn, p_ramrod, p_params);
 
@@ -2207,7 +2216,7 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev,
                        u16 num_queues = 0;
 
                        /* Since the feature controls only queue-zones,
-                        * make sure we have the contexts [rx, tx, xdp] to
+                        * make sure we have the contexts [rx, xdp, tcs] to
                         * match.
                         */
                        for_each_hwfn(cdev, i) {
@@ -2217,7 +2226,8 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev,
                                u16 cids;
 
                                cids = hwfn->pf_params.eth_pf_params.num_cons;
-                               num_queues += min_t(u16, l2_queues, cids / 3);
+                               cids /= (2 + info->num_tc);
+                               num_queues += min_t(u16, l2_queues, cids);
                        }
 
                        /* queues might theoretically be >256, but interrupts'
@@ -2688,7 +2698,8 @@ static int qed_configure_filter_rx_mode(struct qed_dev *cdev,
        if (type == QED_FILTER_RX_MODE_TYPE_PROMISC) {
                accept_flags.rx_accept_filter |= QED_ACCEPT_UCAST_UNMATCHED |
                                                 QED_ACCEPT_MCAST_UNMATCHED;
-               accept_flags.tx_accept_filter |= QED_ACCEPT_MCAST_UNMATCHED;
+               accept_flags.tx_accept_filter |= QED_ACCEPT_UCAST_UNMATCHED |
+                                                QED_ACCEPT_MCAST_UNMATCHED;
        } else if (type == QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC) {
                accept_flags.rx_accept_filter |= QED_ACCEPT_MCAST_UNMATCHED;
                accept_flags.tx_accept_filter |= QED_ACCEPT_MCAST_UNMATCHED;
@@ -2860,7 +2871,8 @@ static int qed_get_coalesce(struct qed_dev *cdev, u16 *coal, void *handle)
        p_hwfn = p_cid->p_owner;
        rc = qed_get_queue_coalesce(p_hwfn, coal, handle);
        if (rc)
-               DP_NOTICE(p_hwfn, "Unable to read queue coalescing\n");
+               DP_VERBOSE(cdev, QED_MSG_DEBUG,
+                          "Unable to read queue coalescing\n");
 
        return rc;
 }
index 8d80f10..7127d5a 100644 (file)
@@ -219,6 +219,9 @@ struct qed_sp_vport_update_params {
        struct qed_rss_params           *rss_params;
        struct qed_filter_accept_flags  accept_flags;
        struct qed_sge_tpa_params       *sge_tpa_params;
+       u8                              update_ctl_frame_check;
+       u8                              mac_chk_en;
+       u8                              ethtype_chk_en;
 };
 
 int qed_sp_vport_update(struct qed_hwfn *p_hwfn,
index 90afd51..b5f419b 100644 (file)
@@ -1619,6 +1619,10 @@ static void qed_ll2_post_rx_buffer_notify_fw(struct qed_hwfn *p_hwfn,
        cq_prod = qed_chain_get_prod_idx(&p_rx->rcq_chain);
        rx_prod.bd_prod = cpu_to_le16(bd_prod);
        rx_prod.cqe_prod = cpu_to_le16(cq_prod);
+
+       /* Make sure chain element is updated before ringing the doorbell */
+       dma_wmb();
+
        DIRECT_REG_WR(p_rx->set_prod_addr, *((u32 *)&rx_prod));
 }
 
@@ -2447,19 +2451,24 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb,
 {
        struct qed_ll2_tx_pkt_info pkt;
        const skb_frag_t *frag;
+       u8 flags = 0, nr_frags;
        int rc = -EINVAL, i;
        dma_addr_t mapping;
        u16 vlan = 0;
-       u8 flags = 0;
 
        if (unlikely(skb->ip_summed != CHECKSUM_NONE)) {
                DP_INFO(cdev, "Cannot transmit a checksummed packet\n");
                return -EINVAL;
        }
 
-       if (1 + skb_shinfo(skb)->nr_frags > CORE_LL2_TX_MAX_BDS_PER_PACKET) {
+       /* Cache number of fragments from SKB since SKB may be freed by
+        * the completion routine after calling qed_ll2_prepare_tx_packet()
+        */
+       nr_frags = skb_shinfo(skb)->nr_frags;
+
+       if (1 + nr_frags > CORE_LL2_TX_MAX_BDS_PER_PACKET) {
                DP_ERR(cdev, "Cannot transmit a packet with %d fragments\n",
-                      1 + skb_shinfo(skb)->nr_frags);
+                      1 + nr_frags);
                return -EINVAL;
        }
 
@@ -2481,7 +2490,7 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb,
        }
 
        memset(&pkt, 0, sizeof(pkt));
-       pkt.num_of_bds = 1 + skb_shinfo(skb)->nr_frags;
+       pkt.num_of_bds = 1 + nr_frags;
        pkt.vlan = vlan;
        pkt.bd_flags = flags;
        pkt.tx_dest = QED_LL2_TX_DEST_NW;
@@ -2492,12 +2501,17 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb,
            test_bit(QED_LL2_XMIT_FLAGS_FIP_DISCOVERY, &xmit_flags))
                pkt.remove_stag = true;
 
+       /* qed_ll2_prepare_tx_packet() may actually send the packet if
+        * there are no fragments in the skb and subsequently the completion
+        * routine may run and free the SKB, so no dereferencing the SKB
+        * beyond this point unless skb has any fragments.
+        */
        rc = qed_ll2_prepare_tx_packet(&cdev->hwfns[0], cdev->ll2->handle,
                                       &pkt, 1);
        if (rc)
                goto err;
 
-       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+       for (i = 0; i < nr_frags; i++) {
                frag = &skb_shinfo(skb)->frags[i];
 
                mapping = skb_frag_dma_map(&cdev->pdev->dev, frag, 0,
index 4179c90..96ab77a 100644 (file)
@@ -382,6 +382,7 @@ void qed_consq_setup(struct qed_hwfn *p_hwfn);
  * @param p_hwfn
  */
 void qed_consq_free(struct qed_hwfn *p_hwfn);
+int qed_spq_pend_post(struct qed_hwfn *p_hwfn);
 
 /**
  * @file
index 888274f..5a495fd 100644 (file)
@@ -604,6 +604,9 @@ int qed_sp_pf_update_stag(struct qed_hwfn *p_hwfn)
 
        p_ent->ramrod.pf_update.update_mf_vlan_flag = true;
        p_ent->ramrod.pf_update.mf_vlan = cpu_to_le16(p_hwfn->hw_info.ovlan);
+       if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits))
+               p_ent->ramrod.pf_update.mf_vlan |=
+                       cpu_to_le16(((u16)p_hwfn->ufp_info.tc << 13));
 
        return qed_spq_post(p_hwfn, p_ent, NULL);
 }
index eb88bbc..ba64ff9 100644 (file)
@@ -397,6 +397,11 @@ int qed_eq_completion(struct qed_hwfn *p_hwfn, void *cookie)
 
        qed_eq_prod_update(p_hwfn, qed_chain_get_prod_idx(p_chain));
 
+       /* Attempt to post pending requests */
+       spin_lock_bh(&p_hwfn->p_spq->lock);
+       rc = qed_spq_pend_post(p_hwfn);
+       spin_unlock_bh(&p_hwfn->p_spq->lock);
+
        return rc;
 }
 
@@ -767,7 +772,7 @@ static int qed_spq_post_list(struct qed_hwfn *p_hwfn,
        return 0;
 }
 
-static int qed_spq_pend_post(struct qed_hwfn *p_hwfn)
+int qed_spq_pend_post(struct qed_hwfn *p_hwfn)
 {
        struct qed_spq *p_spq = p_hwfn->p_spq;
        struct qed_spq_entry *p_ent = NULL;
@@ -905,7 +910,6 @@ int qed_spq_completion(struct qed_hwfn *p_hwfn,
        struct qed_spq_entry    *p_ent = NULL;
        struct qed_spq_entry    *tmp;
        struct qed_spq_entry    *found = NULL;
-       int                     rc;
 
        if (!p_hwfn)
                return -EINVAL;
@@ -963,12 +967,7 @@ int qed_spq_completion(struct qed_hwfn *p_hwfn,
                 */
                qed_spq_return_entry(p_hwfn, found);
 
-       /* Attempt to post pending requests */
-       spin_lock_bh(&p_spq->lock);
-       rc = qed_spq_pend_post(p_hwfn);
-       spin_unlock_bh(&p_spq->lock);
-
-       return rc;
+       return 0;
 }
 
 int qed_consq_alloc(struct qed_hwfn *p_hwfn)
index ca6290f..71a7af1 100644 (file)
@@ -1969,7 +1969,9 @@ static void qed_iov_vf_mbx_start_vport(struct qed_hwfn *p_hwfn,
        params.vport_id = vf->vport_id;
        params.max_buffers_per_cqe = start->max_buffers_per_cqe;
        params.mtu = vf->mtu;
-       params.check_mac = true;
+
+       /* Non trusted VFs should enable control frame filtering */
+       params.check_mac = !vf->p_vf_info.is_trusted_configured;
 
        rc = qed_sp_eth_vport_start(p_hwfn, &params);
        if (rc) {
@@ -5130,6 +5132,9 @@ static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn)
                params.opaque_fid = vf->opaque_fid;
                params.vport_id = vf->vport_id;
 
+               params.update_ctl_frame_check = 1;
+               params.mac_chk_en = !vf_info->is_trusted_configured;
+
                if (vf_info->rx_accept_mode & mask) {
                        flags->update_rx_mode_config = 1;
                        flags->rx_accept_filter = vf_info->rx_accept_mode;
@@ -5147,7 +5152,8 @@ static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn)
                }
 
                if (flags->update_rx_mode_config ||
-                   flags->update_tx_mode_config)
+                   flags->update_tx_mode_config ||
+                   params.update_ctl_frame_check)
                        qed_sp_vport_update(hwfn, &params,
                                            QED_SPQ_MODE_EBLOCK, NULL);
        }
index b6cccf4..5dda547 100644 (file)
@@ -261,6 +261,7 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
        struct pfvf_acquire_resp_tlv *resp = &p_iov->pf2vf_reply->acquire_resp;
        struct pf_vf_pfdev_info *pfdev_info = &resp->pfdev_info;
        struct vf_pf_resc_request *p_resc;
+       u8 retry_cnt = VF_ACQUIRE_THRESH;
        bool resources_acquired = false;
        struct vfpf_acquire_tlv *req;
        int rc = 0, attempts = 0;
@@ -314,6 +315,15 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
 
                /* send acquire request */
                rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
+
+               /* Re-try acquire in case of vf-pf hw channel timeout */
+               if (retry_cnt && rc == -EBUSY) {
+                       DP_VERBOSE(p_hwfn, QED_MSG_IOV,
+                                  "VF retrying to acquire due to VPC timeout\n");
+                       retry_cnt--;
+                       continue;
+               }
+
                if (rc)
                        goto exit;
 
index 613249d..730997b 100644 (file)
@@ -56,7 +56,7 @@
 #include <net/tc_act/tc_gact.h>
 
 #define QEDE_MAJOR_VERSION             8
-#define QEDE_MINOR_VERSION             33
+#define QEDE_MINOR_VERSION             37
 #define QEDE_REVISION_VERSION          0
 #define QEDE_ENGINEERING_VERSION       20
 #define DRV_MODULE_VERSION __stringify(QEDE_MAJOR_VERSION) "." \
@@ -494,6 +494,9 @@ struct qede_reload_args {
 
 /* Datapath functions definition */
 netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev);
+u16 qede_select_queue(struct net_device *dev, struct sk_buff *skb,
+                     struct net_device *sb_dev,
+                     select_queue_fallback_t fallback);
 netdev_features_t qede_features_check(struct sk_buff *skb,
                                      struct net_device *dev,
                                      netdev_features_t features);
index bdf816f..31b046e 100644 (file)
@@ -1695,6 +1695,19 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        return NETDEV_TX_OK;
 }
 
+u16 qede_select_queue(struct net_device *dev, struct sk_buff *skb,
+                     struct net_device *sb_dev,
+                     select_queue_fallback_t fallback)
+{
+       struct qede_dev *edev = netdev_priv(dev);
+       int total_txq;
+
+       total_txq = QEDE_TSS_COUNT(edev) * edev->dev_info.num_tc;
+
+       return QEDE_TSS_COUNT(edev) ?
+               fallback(dev, skb, NULL) % total_txq :  0;
+}
+
 /* 8B udp header + 8B base tunnel header + 32B option length */
 #define QEDE_MAX_TUN_HDR_LEN 48
 
index 5a74fcb..9790f26 100644 (file)
@@ -631,6 +631,7 @@ static const struct net_device_ops qede_netdev_ops = {
        .ndo_open = qede_open,
        .ndo_stop = qede_close,
        .ndo_start_xmit = qede_start_xmit,
+       .ndo_select_queue = qede_select_queue,
        .ndo_set_rx_mode = qede_set_rx_mode,
        .ndo_set_mac_address = qede_set_mac_addr,
        .ndo_validate_addr = eth_validate_addr,
@@ -666,6 +667,7 @@ static const struct net_device_ops qede_netdev_vf_ops = {
        .ndo_open = qede_open,
        .ndo_stop = qede_close,
        .ndo_start_xmit = qede_start_xmit,
+       .ndo_select_queue = qede_select_queue,
        .ndo_set_rx_mode = qede_set_rx_mode,
        .ndo_set_mac_address = qede_set_mac_addr,
        .ndo_validate_addr = eth_validate_addr,
@@ -684,6 +686,7 @@ static const struct net_device_ops qede_netdev_vf_xdp_ops = {
        .ndo_open = qede_open,
        .ndo_stop = qede_close,
        .ndo_start_xmit = qede_start_xmit,
+       .ndo_select_queue = qede_select_queue,
        .ndo_set_rx_mode = qede_set_rx_mode,
        .ndo_set_mac_address = qede_set_mac_addr,
        .ndo_validate_addr = eth_validate_addr,
index d344e9d..af38d3d 100644 (file)
@@ -434,14 +434,14 @@ int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter,
        *(tx_ring->hw_consumer) = 0;
 
        rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx);
-       rq_addr = dma_zalloc_coherent(&adapter->pdev->dev, rq_size,
-                                     &rq_phys_addr, GFP_KERNEL);
+       rq_addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size,
+                                    &rq_phys_addr, GFP_KERNEL);
        if (!rq_addr)
                return -ENOMEM;
 
        rsp_size = SIZEOF_CARDRSP_TX(struct qlcnic_cardrsp_tx_ctx);
-       rsp_addr = dma_zalloc_coherent(&adapter->pdev->dev, rsp_size,
-                                      &rsp_phys_addr, GFP_KERNEL);
+       rsp_addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size,
+                                     &rsp_phys_addr, GFP_KERNEL);
        if (!rsp_addr) {
                err = -ENOMEM;
                goto out_free_rq;
@@ -855,8 +855,8 @@ int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *adapter,
        struct qlcnic_cmd_args cmd;
        size_t  nic_size = sizeof(struct qlcnic_info_le);
 
-       nic_info_addr = dma_zalloc_coherent(&adapter->pdev->dev, nic_size,
-                                           &nic_dma_t, GFP_KERNEL);
+       nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
+                                          &nic_dma_t, GFP_KERNEL);
        if (!nic_info_addr)
                return -ENOMEM;
 
@@ -909,8 +909,8 @@ int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *adapter,
        if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
                return err;
 
-       nic_info_addr = dma_zalloc_coherent(&adapter->pdev->dev, nic_size,
-                                           &nic_dma_t, GFP_KERNEL);
+       nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
+                                          &nic_dma_t, GFP_KERNEL);
        if (!nic_info_addr)
                return -ENOMEM;
 
@@ -964,8 +964,8 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter,
        void *pci_info_addr;
        int err = 0, i;
 
-       pci_info_addr = dma_zalloc_coherent(&adapter->pdev->dev, pci_size,
-                                           &pci_info_dma_t, GFP_KERNEL);
+       pci_info_addr = dma_alloc_coherent(&adapter->pdev->dev, pci_size,
+                                          &pci_info_dma_t, GFP_KERNEL);
        if (!pci_info_addr)
                return -ENOMEM;
 
@@ -1078,8 +1078,8 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
                return -EIO;
        }
 
-       stats_addr = dma_zalloc_coherent(&adapter->pdev->dev, stats_size,
-                                        &stats_dma_t, GFP_KERNEL);
+       stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
+                                       &stats_dma_t, GFP_KERNEL);
        if (!stats_addr)
                return -ENOMEM;
 
@@ -1134,8 +1134,8 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
        if (mac_stats == NULL)
                return -ENOMEM;
 
-       stats_addr = dma_zalloc_coherent(&adapter->pdev->dev, stats_size,
-                                        &stats_dma_t, GFP_KERNEL);
+       stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
+                                       &stats_dma_t, GFP_KERNEL);
        if (!stats_addr)
                return -ENOMEM;
 
index 031f6e6..8d79031 100644 (file)
@@ -776,7 +776,7 @@ int emac_mac_rx_tx_rings_alloc_all(struct emac_adapter *adpt)
                            8 + 2 * 8; /* 8 byte per one Tx and two Rx rings */
 
        ring_header->used = 0;
-       ring_header->v_addr = dma_zalloc_coherent(dev, ring_header->size,
+       ring_header->v_addr = dma_alloc_coherent(dev, ring_header->size,
                                                 &ring_header->dma_addr,
                                                 GFP_KERNEL);
        if (!ring_header->v_addr)
index 44f6e48..4f910c4 100644 (file)
@@ -691,7 +691,7 @@ static void cp_tx (struct cp_private *cp)
                        }
                        bytes_compl += skb->len;
                        pkts_compl++;
-                       dev_kfree_skb_irq(skb);
+                       dev_consume_skb_irq(skb);
                }
 
                cp->tx_skb[tx_tail] = NULL;
index 298930d..6e36b88 100644 (file)
@@ -205,6 +205,8 @@ enum cfg_version {
 };
 
 static const struct pci_device_id rtl8169_pci_tbl[] = {
+       { PCI_VDEVICE(REALTEK,  0x2502), RTL_CFG_1 },
+       { PCI_VDEVICE(REALTEK,  0x2600), RTL_CFG_1 },
        { PCI_VDEVICE(REALTEK,  0x8129), RTL_CFG_0 },
        { PCI_VDEVICE(REALTEK,  0x8136), RTL_CFG_2 },
        { PCI_VDEVICE(REALTEK,  0x8161), RTL_CFG_1 },
@@ -706,6 +708,7 @@ module_param(use_dac, int, 0);
 MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
 module_param_named(debug, debug.msg_enable, int, 0);
 MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
+MODULE_SOFTDEP("pre: realtek");
 MODULE_LICENSE("GPL");
 MODULE_FIRMWARE(FIRMWARE_8168D_1);
 MODULE_FIRMWARE(FIRMWARE_8168D_2);
@@ -1283,11 +1286,13 @@ static u16 rtl_get_events(struct rtl8169_private *tp)
 static void rtl_ack_events(struct rtl8169_private *tp, u16 bits)
 {
        RTL_W16(tp, IntrStatus, bits);
+       mmiowb();
 }
 
 static void rtl_irq_disable(struct rtl8169_private *tp)
 {
        RTL_W16(tp, IntrMask, 0);
+       mmiowb();
 }
 
 #define RTL_EVENT_NAPI_RX      (RxOK | RxErr)
@@ -1679,11 +1684,13 @@ static bool rtl8169_reset_counters(struct rtl8169_private *tp)
 
 static bool rtl8169_update_counters(struct rtl8169_private *tp)
 {
+       u8 val = RTL_R8(tp, ChipCmd);
+
        /*
         * Some chips are unable to dump tally counters when the receiver
-        * is disabled.
+        * is disabled. If 0xff chip may be in a PCI power-save state.
         */
-       if ((RTL_R8(tp, ChipCmd) & CmdRxEnb) == 0)
+       if (!(val & CmdRxEnb) || val == 0xff)
                return true;
 
        return rtl8169_do_counters(tp, CounterDump);
@@ -6067,7 +6074,6 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
        struct device *d = tp_to_dev(tp);
        dma_addr_t mapping;
        u32 opts[2], len;
-       bool stop_queue;
        int frags;
 
        if (unlikely(!rtl_tx_slots_avail(tp, skb_shinfo(skb)->nr_frags))) {
@@ -6109,6 +6115,8 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
 
        txd->opts2 = cpu_to_le32(opts[1]);
 
+       netdev_sent_queue(dev, skb->len);
+
        skb_tx_timestamp(skb);
 
        /* Force memory writes to complete before releasing descriptor */
@@ -6121,14 +6129,16 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
 
        tp->cur_tx += frags + 1;
 
-       stop_queue = !rtl_tx_slots_avail(tp, MAX_SKB_FRAGS);
-       if (unlikely(stop_queue))
-               netif_stop_queue(dev);
+       RTL_W8(tp, TxPoll, NPQ);
 
-       if (__netdev_sent_queue(dev, skb->len, skb->xmit_more))
-               RTL_W8(tp, TxPoll, NPQ);
+       mmiowb();
 
-       if (unlikely(stop_queue)) {
+       if (!rtl_tx_slots_avail(tp, MAX_SKB_FRAGS)) {
+               /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must
+                * not miss a ring update when it notices a stopped queue.
+                */
+               smp_wmb();
+               netif_stop_queue(dev);
                /* Sync with rtl_tx:
                 * - publish queue status and cur_tx ring index (write barrier)
                 * - refresh dirty_tx ring index (read barrier).
@@ -6478,7 +6488,9 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
 
        if (work_done < budget) {
                napi_complete_done(napi, work_done);
+
                rtl_irq_enable(tp);
+               mmiowb();
        }
 
        return work_done;
index ffc1ada..d28c8f9 100644 (file)
@@ -343,7 +343,7 @@ static int ravb_ring_init(struct net_device *ndev, int q)
        int i;
 
        priv->rx_buf_sz = (ndev->mtu <= 1492 ? PKT_BUF_SZ : ndev->mtu) +
-               ETH_HLEN + VLAN_HLEN;
+               ETH_HLEN + VLAN_HLEN + sizeof(__sum16);
 
        /* Allocate RX and TX skb rings */
        priv->rx_skb[q] = kcalloc(priv->num_rx_ring[q],
@@ -524,13 +524,15 @@ static void ravb_rx_csum(struct sk_buff *skb)
 {
        u8 *hw_csum;
 
-       /* The hardware checksum is 2 bytes appended to packet data */
-       if (unlikely(skb->len < 2))
+       /* The hardware checksum is contained in sizeof(__sum16) (2) bytes
+        * appended to packet data
+        */
+       if (unlikely(skb->len < sizeof(__sum16)))
                return;
-       hw_csum = skb_tail_pointer(skb) - 2;
+       hw_csum = skb_tail_pointer(skb) - sizeof(__sum16);
        skb->csum = csum_unfold((__force __sum16)get_unaligned_le16(hw_csum));
        skb->ip_summed = CHECKSUM_COMPLETE;
-       skb_trim(skb, skb->len - 2);
+       skb_trim(skb, skb->len - sizeof(__sum16));
 }
 
 /* Packet receive function for Ethernet AVB */
index 690aee8..6d22dd5 100644 (file)
@@ -400,9 +400,9 @@ static int init_tx_ring(struct device *dev, u8 queue_no,
        }
 
        /* allocate memory for TX descriptors */
-       tx_ring->dma_tx = dma_zalloc_coherent(dev,
-                                             tx_rsize * sizeof(struct sxgbe_tx_norm_desc),
-                                             &tx_ring->dma_tx_phy, GFP_KERNEL);
+       tx_ring->dma_tx = dma_alloc_coherent(dev,
+                                            tx_rsize * sizeof(struct sxgbe_tx_norm_desc),
+                                            &tx_ring->dma_tx_phy, GFP_KERNEL);
        if (!tx_ring->dma_tx)
                return -ENOMEM;
 
@@ -479,9 +479,9 @@ static int init_rx_ring(struct net_device *dev, u8 queue_no,
        rx_ring->queue_no = queue_no;
 
        /* allocate memory for RX descriptors */
-       rx_ring->dma_rx = dma_zalloc_coherent(priv->device,
-                                             rx_rsize * sizeof(struct sxgbe_rx_norm_desc),
-                                             &rx_ring->dma_rx_phy, GFP_KERNEL);
+       rx_ring->dma_rx = dma_alloc_coherent(priv->device,
+                                            rx_rsize * sizeof(struct sxgbe_rx_norm_desc),
+                                            &rx_ring->dma_rx_phy, GFP_KERNEL);
 
        if (rx_ring->dma_rx == NULL)
                return -ENOMEM;
index b6a5005..c080341 100644 (file)
@@ -6046,22 +6046,25 @@ static const struct efx_ef10_nvram_type_info efx_ef10_nvram_types[] = {
        { NVRAM_PARTITION_TYPE_EXPANSION_UEFI,     0,    0, "sfc_uefi" },
        { NVRAM_PARTITION_TYPE_STATUS,             0,    0, "sfc_status" }
 };
+#define EF10_NVRAM_PARTITION_COUNT     ARRAY_SIZE(efx_ef10_nvram_types)
 
 static int efx_ef10_mtd_probe_partition(struct efx_nic *efx,
                                        struct efx_mcdi_mtd_partition *part,
-                                       unsigned int type)
+                                       unsigned int type,
+                                       unsigned long *found)
 {
        MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_METADATA_IN_LEN);
        MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_METADATA_OUT_LENMAX);
        const struct efx_ef10_nvram_type_info *info;
        size_t size, erase_size, outlen;
+       int type_idx = 0;
        bool protected;
        int rc;
 
-       for (info = efx_ef10_nvram_types; ; info++) {
-               if (info ==
-                   efx_ef10_nvram_types + ARRAY_SIZE(efx_ef10_nvram_types))
+       for (type_idx = 0; ; type_idx++) {
+               if (type_idx == EF10_NVRAM_PARTITION_COUNT)
                        return -ENODEV;
+               info = efx_ef10_nvram_types + type_idx;
                if ((type & ~info->type_mask) == info->type)
                        break;
        }
@@ -6074,6 +6077,13 @@ static int efx_ef10_mtd_probe_partition(struct efx_nic *efx,
        if (protected)
                return -ENODEV; /* hide it */
 
+       /* If we've already exposed a partition of this type, hide this
+        * duplicate.  All operations on MTDs are keyed by the type anyway,
+        * so we can't act on the duplicate.
+        */
+       if (__test_and_set_bit(type_idx, found))
+               return -EEXIST;
+
        part->nvram_type = type;
 
        MCDI_SET_DWORD(inbuf, NVRAM_METADATA_IN_TYPE, type);
@@ -6105,6 +6115,7 @@ static int efx_ef10_mtd_probe_partition(struct efx_nic *efx,
 static int efx_ef10_mtd_probe(struct efx_nic *efx)
 {
        MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX);
+       DECLARE_BITMAP(found, EF10_NVRAM_PARTITION_COUNT) = { 0 };
        struct efx_mcdi_mtd_partition *parts;
        size_t outlen, n_parts_total, i, n_parts;
        unsigned int type;
@@ -6133,11 +6144,13 @@ static int efx_ef10_mtd_probe(struct efx_nic *efx)
        for (i = 0; i < n_parts_total; i++) {
                type = MCDI_ARRAY_DWORD(outbuf, NVRAM_PARTITIONS_OUT_TYPE_ID,
                                        i);
-               rc = efx_ef10_mtd_probe_partition(efx, &parts[n_parts], type);
-               if (rc == 0)
-                       n_parts++;
-               else if (rc != -ENODEV)
+               rc = efx_ef10_mtd_probe_partition(efx, &parts[n_parts], type,
+                                                 found);
+               if (rc == -EEXIST || rc == -ENODEV)
+                       continue;
+               if (rc)
                        goto fail;
+               n_parts++;
        }
 
        rc = efx_mtd_add(efx, &parts[0].common, n_parts, sizeof(*parts));
index a8ecb33..9c07b51 100644 (file)
@@ -33,8 +33,8 @@
 int ef4_nic_alloc_buffer(struct ef4_nic *efx, struct ef4_buffer *buffer,
                         unsigned int len, gfp_t gfp_flags)
 {
-       buffer->addr = dma_zalloc_coherent(&efx->pci_dev->dev, len,
-                                          &buffer->dma_addr, gfp_flags);
+       buffer->addr = dma_alloc_coherent(&efx->pci_dev->dev, len,
+                                         &buffer->dma_addr, gfp_flags);
        if (!buffer->addr)
                return -ENOMEM;
        buffer->len = len;
index aa1945a..c2d45a4 100644 (file)
@@ -34,8 +34,8 @@
 int efx_nic_alloc_buffer(struct efx_nic *efx, struct efx_buffer *buffer,
                         unsigned int len, gfp_t gfp_flags)
 {
-       buffer->addr = dma_zalloc_coherent(&efx->pci_dev->dev, len,
-                                          &buffer->dma_addr, gfp_flags);
+       buffer->addr = dma_alloc_coherent(&efx->pci_dev->dev, len,
+                                         &buffer->dma_addr, gfp_flags);
        if (!buffer->addr)
                return -ENOMEM;
        buffer->len = len;
index 703fbbe..0e1b7e9 100644 (file)
@@ -211,8 +211,8 @@ static void meth_check_link(struct net_device *dev)
 static int meth_init_tx_ring(struct meth_private *priv)
 {
        /* Init TX ring */
-       priv->tx_ring = dma_zalloc_coherent(NULL, TX_RING_BUFFER_SIZE,
-                                           &priv->tx_ring_dma, GFP_ATOMIC);
+       priv->tx_ring = dma_alloc_coherent(NULL, TX_RING_BUFFER_SIZE,
+                                          &priv->tx_ring_dma, GFP_ATOMIC);
        if (!priv->tx_ring)
                return -ENOMEM;
 
index 15c62c1..be47d86 100644 (file)
@@ -1037,7 +1037,7 @@ static void epic_tx(struct net_device *dev, struct epic_private *ep)
                skb = ep->tx_skbuff[entry];
                pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr,
                                 skb->len, PCI_DMA_TODEVICE);
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
                ep->tx_skbuff[entry] = NULL;
        }
 
index 05a0948..a181497 100644 (file)
@@ -1029,8 +1029,8 @@ static int netsec_alloc_dring(struct netsec_priv *priv, enum ring_id id)
        struct netsec_desc_ring *dring = &priv->desc_ring[id];
        int i;
 
-       dring->vaddr = dma_zalloc_coherent(priv->dev, DESC_SZ * DESC_NUM,
-                                          &dring->desc_dma, GFP_KERNEL);
+       dring->vaddr = dma_alloc_coherent(priv->dev, DESC_SZ * DESC_NUM,
+                                         &dring->desc_dma, GFP_KERNEL);
        if (!dring->vaddr)
                goto err;
 
index 7b92336..3b174ea 100644 (file)
@@ -1342,8 +1342,10 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
        }
 
        ret = phy_power_on(bsp_priv, true);
-       if (ret)
+       if (ret) {
+               gmac_clk_enable(bsp_priv, false);
                return ret;
+       }
 
        pm_runtime_enable(dev);
        pm_runtime_get_sync(dev);
index 6c5092e..c5e2558 100644 (file)
@@ -263,6 +263,7 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr,
                                  struct stmmac_extra_stats *x, u32 chan)
 {
        u32 intr_status = readl(ioaddr + XGMAC_DMA_CH_STATUS(chan));
+       u32 intr_en = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan));
        int ret = 0;
 
        /* ABNORMAL interrupts */
@@ -282,8 +283,7 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr,
                x->normal_irq_n++;
 
                if (likely(intr_status & XGMAC_RI)) {
-                       u32 value = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan));
-                       if (likely(value & XGMAC_RIE)) {
+                       if (likely(intr_en & XGMAC_RIE)) {
                                x->rx_normal_irq_n++;
                                ret |= handle_rx;
                        }
@@ -295,7 +295,7 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr,
        }
 
        /* Clear interrupts */
-       writel(~0x0, ioaddr + XGMAC_DMA_CH_STATUS(chan));
+       writel(intr_en & intr_status, ioaddr + XGMAC_DMA_CH_STATUS(chan));
 
        return ret;
 }
index d1f61c2..5d85742 100644 (file)
@@ -721,8 +721,11 @@ static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv)
 {
        unsigned long clk = clk_get_rate(priv->plat->stmmac_clk);
 
-       if (!clk)
-               return 0;
+       if (!clk) {
+               clk = priv->plat->clk_ref_rate;
+               if (!clk)
+                       return 0;
+       }
 
        return (usec * (clk / 1000000)) / 256;
 }
@@ -731,8 +734,11 @@ static u32 stmmac_riwt2usec(u32 riwt, struct stmmac_priv *priv)
 {
        unsigned long clk = clk_get_rate(priv->plat->stmmac_clk);
 
-       if (!clk)
-               return 0;
+       if (!clk) {
+               clk = priv->plat->clk_ref_rate;
+               if (!clk)
+                       return 0;
+       }
 
        return (riwt * 256) / (clk / 1000000);
 }
index 0e0a078..685d204 100644 (file)
@@ -1549,22 +1549,18 @@ static int alloc_dma_rx_desc_resources(struct stmmac_priv *priv)
                        goto err_dma;
 
                if (priv->extend_desc) {
-                       rx_q->dma_erx = dma_zalloc_coherent(priv->device,
-                                                           DMA_RX_SIZE *
-                                                           sizeof(struct
-                                                           dma_extended_desc),
-                                                           &rx_q->dma_rx_phy,
-                                                           GFP_KERNEL);
+                       rx_q->dma_erx = dma_alloc_coherent(priv->device,
+                                                          DMA_RX_SIZE * sizeof(struct dma_extended_desc),
+                                                          &rx_q->dma_rx_phy,
+                                                          GFP_KERNEL);
                        if (!rx_q->dma_erx)
                                goto err_dma;
 
                } else {
-                       rx_q->dma_rx = dma_zalloc_coherent(priv->device,
-                                                          DMA_RX_SIZE *
-                                                          sizeof(struct
-                                                          dma_desc),
-                                                          &rx_q->dma_rx_phy,
-                                                          GFP_KERNEL);
+                       rx_q->dma_rx = dma_alloc_coherent(priv->device,
+                                                         DMA_RX_SIZE * sizeof(struct dma_desc),
+                                                         &rx_q->dma_rx_phy,
+                                                         GFP_KERNEL);
                        if (!rx_q->dma_rx)
                                goto err_dma;
                }
@@ -1612,21 +1608,17 @@ static int alloc_dma_tx_desc_resources(struct stmmac_priv *priv)
                        goto err_dma;
 
                if (priv->extend_desc) {
-                       tx_q->dma_etx = dma_zalloc_coherent(priv->device,
-                                                           DMA_TX_SIZE *
-                                                           sizeof(struct
-                                                           dma_extended_desc),
-                                                           &tx_q->dma_tx_phy,
-                                                           GFP_KERNEL);
+                       tx_q->dma_etx = dma_alloc_coherent(priv->device,
+                                                          DMA_TX_SIZE * sizeof(struct dma_extended_desc),
+                                                          &tx_q->dma_tx_phy,
+                                                          GFP_KERNEL);
                        if (!tx_q->dma_etx)
                                goto err_dma;
                } else {
-                       tx_q->dma_tx = dma_zalloc_coherent(priv->device,
-                                                          DMA_TX_SIZE *
-                                                          sizeof(struct
-                                                                 dma_desc),
-                                                          &tx_q->dma_tx_phy,
-                                                          GFP_KERNEL);
+                       tx_q->dma_tx = dma_alloc_coherent(priv->device,
+                                                         DMA_TX_SIZE * sizeof(struct dma_desc),
+                                                         &tx_q->dma_tx_phy,
+                                                         GFP_KERNEL);
                        if (!tx_q->dma_tx)
                                goto err_dma;
                }
@@ -3031,10 +3023,22 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
        tx_q = &priv->tx_queue[queue];
 
+       if (priv->tx_path_in_lpi_mode)
+               stmmac_disable_eee_mode(priv);
+
        /* Manage oversized TCP frames for GMAC4 device */
        if (skb_is_gso(skb) && priv->tso) {
-               if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))
+               if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) {
+                       /*
+                        * There is no way to determine the number of TSO
+                        * capable Queues. Let's use always the Queue 0
+                        * because if TSO is supported then at least this
+                        * one will be capable.
+                        */
+                       skb_set_queue_mapping(skb, 0);
+
                        return stmmac_tso_xmit(skb, dev);
+               }
        }
 
        if (unlikely(stmmac_tx_avail(priv, queue) < nfrags + 1)) {
@@ -3049,9 +3053,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
                return NETDEV_TX_BUSY;
        }
 
-       if (priv->tx_path_in_lpi_mode)
-               stmmac_disable_eee_mode(priv);
-
        entry = tx_q->cur_tx;
        first_entry = entry;
        WARN_ON(tx_q->tx_skbuff[first_entry]);
@@ -3525,27 +3526,28 @@ static int stmmac_napi_poll(struct napi_struct *napi, int budget)
        struct stmmac_channel *ch =
                container_of(napi, struct stmmac_channel, napi);
        struct stmmac_priv *priv = ch->priv_data;
-       int work_done = 0, work_rem = budget;
+       int work_done, rx_done = 0, tx_done = 0;
        u32 chan = ch->index;
 
        priv->xstats.napi_poll++;
 
-       if (ch->has_tx) {
-               int done = stmmac_tx_clean(priv, work_rem, chan);
+       if (ch->has_tx)
+               tx_done = stmmac_tx_clean(priv, budget, chan);
+       if (ch->has_rx)
+               rx_done = stmmac_rx(priv, budget, chan);
 
-               work_done += done;
-               work_rem -= done;
-       }
+       work_done = max(rx_done, tx_done);
+       work_done = min(work_done, budget);
 
-       if (ch->has_rx) {
-               int done = stmmac_rx(priv, work_rem, chan);
+       if (work_done < budget && napi_complete_done(napi, work_done)) {
+               int stat;
 
-               work_done += done;
-               work_rem -= done;
-       }
-
-       if (work_done < budget && napi_complete_done(napi, work_done))
                stmmac_enable_dma_irq(priv, priv->ioaddr, chan);
+               stat = stmmac_dma_interrupt_status(priv, priv->ioaddr,
+                                                  &priv->xstats, chan);
+               if (stat && napi_reschedule(napi))
+                       stmmac_disable_dma_irq(priv, priv->ioaddr, chan);
+       }
 
        return work_done;
 }
@@ -4168,6 +4170,18 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
                        return ret;
        }
 
+       /* Rx Watchdog is available in the COREs newer than the 3.40.
+        * In some case, for example on bugged HW this feature
+        * has to be disable and this can be done by passing the
+        * riwt_off field from the platform.
+        */
+       if (((priv->synopsys_id >= DWMAC_CORE_3_50) ||
+           (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) {
+               priv->use_riwt = 1;
+               dev_info(priv->device,
+                        "Enable RX Mitigation via HW Watchdog Timer\n");
+       }
+
        return 0;
 }
 
@@ -4300,18 +4314,6 @@ int stmmac_dvr_probe(struct device *device,
        if (flow_ctrl)
                priv->flow_ctrl = FLOW_AUTO;    /* RX/TX pause on */
 
-       /* Rx Watchdog is available in the COREs newer than the 3.40.
-        * In some case, for example on bugged HW this feature
-        * has to be disable and this can be done by passing the
-        * riwt_off field from the platform.
-        */
-       if (((priv->synopsys_id >= DWMAC_CORE_3_50) ||
-           (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) {
-               priv->use_riwt = 1;
-               dev_info(priv->device,
-                        "Enable RX Mitigation via HW Watchdog Timer\n");
-       }
-
        /* Setup channels NAPI */
        maxq = max(priv->plat->rx_queues_to_use, priv->plat->tx_queues_to_use);
 
index c54a50d..d819e8e 100644 (file)
@@ -299,7 +299,17 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
  */
 static void stmmac_pci_remove(struct pci_dev *pdev)
 {
+       int i;
+
        stmmac_dvr_remove(&pdev->dev);
+
+       for (i = 0; i <= PCI_STD_RESOURCE_END; i++) {
+               if (pci_resource_len(pdev, i) == 0)
+                       continue;
+               pcim_iounmap_regions(pdev, BIT(i));
+               break;
+       }
+
        pci_disable_device(pdev);
 }
 
index 531294f..58ea18a 100644 (file)
@@ -301,6 +301,8 @@ static int tc_setup_cbs(struct stmmac_priv *priv,
        /* Queue 0 is not AVB capable */
        if (queue <= 0 || queue >= tx_queues_count)
                return -EINVAL;
+       if (!priv->dma_cap.av)
+               return -EOPNOTSUPP;
        if (priv->speed != SPEED_100 && priv->speed != SPEED_1000)
                return -EOPNOTSUPP;
 
index 9020b08..6fc05c1 100644 (file)
@@ -1,22 +1,9 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
 /* cassini.c: Sun Microsystems Cassini(+) ethernet driver.
  *
  * Copyright (C) 2004 Sun Microsystems Inc.
  * Copyright (C) 2003 Adrian Sun (asun@darksunrising.com)
  *
- * 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.  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, see <http://www.gnu.org/licenses/>.
- *
  * This driver uses the sungem driver (c) David Miller
  * (davem@redhat.com) as its basis.
  *
@@ -1911,7 +1898,7 @@ static inline void cas_tx_ringN(struct cas *cp, int ring, int limit)
                cp->net_stats[ring].tx_packets++;
                cp->net_stats[ring].tx_bytes += skb->len;
                spin_unlock(&cp->stat_lock[ring]);
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
        }
        cp->tx_old[ring] = entry;
 
index 13f3860..ae5f05f 100644 (file)
@@ -1,23 +1,10 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0+ */
 /* $Id: cassini.h,v 1.16 2004/08/17 21:15:16 zaumen Exp $
  * cassini.h: Definitions for Sun Microsystems Cassini(+) ethernet driver.
  *
  * Copyright (C) 2004 Sun Microsystems Inc.
  * Copyright (c) 2003 Adrian Sun (asun@darksunrising.com)
  *
- * 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.  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, see <http://www.gnu.org/licenses/>.
- *
  * vendor id: 0x108E (Sun Microsystems, Inc.)
  * device id: 0xabba (Cassini)
  * revision ids: 0x01 = Cassini
index 720b7ac..e9b757b 100644 (file)
@@ -781,7 +781,7 @@ static void bigmac_tx(struct bigmac *bp)
 
                DTX(("skb(%p) ", skb));
                bp->tx_skbs[elem] = NULL;
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
 
                elem = NEXT_TX(elem);
        }
index ff641cf..d007dfe 100644 (file)
@@ -1962,7 +1962,7 @@ static void happy_meal_tx(struct happy_meal *hp)
                        this = &txbase[elem];
                }
 
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
                dev->stats.tx_packets++;
        }
        hp->tx_old = elem;
index dc966dd..b24c111 100644 (file)
@@ -1739,7 +1739,7 @@ static void bdx_tx_cleanup(struct bdx_priv *priv)
                tx_level -= db->rptr->len;      /* '-' koz len is negative */
 
                /* now should come skb pointer - free it */
-               dev_kfree_skb_irq(db->rptr->addr.skb);
+               dev_consume_skb_irq(db->rptr->addr.skb);
                bdx_tx_db_inc_rptr(db);
        }
 
index 810dfc7..e2d47b2 100644 (file)
@@ -608,7 +608,7 @@ static void cpmac_end_xmit(struct net_device *dev, int queue)
                        netdev_dbg(dev, "sent 0x%p, len=%d\n",
                                   desc->skb, desc->skb->len);
 
-               dev_kfree_skb_irq(desc->skb);
+               dev_consume_skb_irq(desc->skb);
                desc->skb = NULL;
                if (__netif_subqueue_stopped(dev, queue))
                        netif_wake_subqueue(dev, queue);
index edcd1e6..37925a1 100644 (file)
@@ -1311,13 +1311,13 @@ static int tsi108_open(struct net_device *dev)
                       data->id, dev->irq, dev->name);
        }
 
-       data->rxring = dma_zalloc_coherent(&data->pdev->dev, rxring_size,
-                       &data->rxdma, GFP_KERNEL);
+       data->rxring = dma_alloc_coherent(&data->pdev->dev, rxring_size,
+                                         &data->rxdma, GFP_KERNEL);
        if (!data->rxring)
                return -ENOMEM;
 
-       data->txring = dma_zalloc_coherent(&data->pdev->dev, txring_size,
-                       &data->txdma, GFP_KERNEL);
+       data->txring = dma_alloc_coherent(&data->pdev->dev, txring_size,
+                                         &data->txdma, GFP_KERNEL);
        if (!data->txring) {
                dma_free_coherent(&data->pdev->dev, rxring_size, data->rxring,
                                    data->rxdma);
index 8241269..27f6cf1 100644 (file)
@@ -1740,7 +1740,7 @@ static void velocity_free_tx_buf(struct velocity_info *vptr,
                dma_unmap_single(vptr->dev, tdinfo->skb_dma[i],
                                 le16_to_cpu(pktlen), DMA_TO_DEVICE);
        }
-       dev_kfree_skb_irq(skb);
+       dev_consume_skb_irq(skb);
        tdinfo->skb = NULL;
 }
 
index 2241f98..15bb058 100644 (file)
@@ -243,15 +243,15 @@ static int temac_dma_bd_init(struct net_device *ndev)
 
        /* allocate the tx and rx ring buffer descriptors. */
        /* returns a virtual address and a physical address. */
-       lp->tx_bd_v = dma_zalloc_coherent(ndev->dev.parent,
-                                         sizeof(*lp->tx_bd_v) * TX_BD_NUM,
-                                         &lp->tx_bd_p, GFP_KERNEL);
+       lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+                                        sizeof(*lp->tx_bd_v) * TX_BD_NUM,
+                                        &lp->tx_bd_p, GFP_KERNEL);
        if (!lp->tx_bd_v)
                goto out;
 
-       lp->rx_bd_v = dma_zalloc_coherent(ndev->dev.parent,
-                                         sizeof(*lp->rx_bd_v) * RX_BD_NUM,
-                                         &lp->rx_bd_p, GFP_KERNEL);
+       lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+                                        sizeof(*lp->rx_bd_v) * RX_BD_NUM,
+                                        &lp->rx_bd_p, GFP_KERNEL);
        if (!lp->rx_bd_v)
                goto out;
 
index 12a1460..0789d8a 100644 (file)
@@ -199,15 +199,15 @@ static int axienet_dma_bd_init(struct net_device *ndev)
        lp->rx_bd_ci = 0;
 
        /* Allocate the Tx and Rx buffer descriptors. */
-       lp->tx_bd_v = dma_zalloc_coherent(ndev->dev.parent,
-                                         sizeof(*lp->tx_bd_v) * TX_BD_NUM,
-                                         &lp->tx_bd_p, GFP_KERNEL);
+       lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+                                        sizeof(*lp->tx_bd_v) * TX_BD_NUM,
+                                        &lp->tx_bd_p, GFP_KERNEL);
        if (!lp->tx_bd_v)
                goto out;
 
-       lp->rx_bd_v = dma_zalloc_coherent(ndev->dev.parent,
-                                         sizeof(*lp->rx_bd_v) * RX_BD_NUM,
-                                         &lp->rx_bd_p, GFP_KERNEL);
+       lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+                                        sizeof(*lp->rx_bd_v) * RX_BD_NUM,
+                                        &lp->rx_bd_p, GFP_KERNEL);
        if (!lp->rx_bd_v)
                goto out;
 
index 61fceee..56b7791 100644 (file)
@@ -1139,9 +1139,9 @@ static int dfx_driver_init(struct net_device *dev, const char *print_name,
 #endif
                                        sizeof(PI_CONSUMER_BLOCK) +
                                        (PI_ALIGN_K_DESC_BLK - 1);
-       bp->kmalloced = top_v = dma_zalloc_coherent(bp->bus_dev, alloc_size,
-                                                   &bp->kmalloced_dma,
-                                                   GFP_ATOMIC);
+       bp->kmalloced = top_v = dma_alloc_coherent(bp->bus_dev, alloc_size,
+                                                  &bp->kmalloced_dma,
+                                                  GFP_ATOMIC);
        if (top_v == NULL)
                return DFX_K_FAILURE;
 
@@ -3512,7 +3512,7 @@ static int dfx_xmt_done(DFX_board_t *bp)
                                 bp->descr_block_virt->xmt_data[comp].long_1,
                                 p_xmt_drv_descr->p_skb->len,
                                 DMA_TO_DEVICE);
-               dev_kfree_skb_irq(p_xmt_drv_descr->p_skb);
+               dev_consume_skb_irq(p_xmt_drv_descr->p_skb);
 
                /*
                 * Move to start of next packet by updating completion index
index 72433f3..5d661f6 100644 (file)
@@ -409,10 +409,10 @@ static  int skfp_driver_init(struct net_device *dev)
        if (bp->SharedMemSize > 0) {
                bp->SharedMemSize += 16;        // for descriptor alignment
 
-               bp->SharedMemAddr = dma_zalloc_coherent(&bp->pdev.dev,
-                                                       bp->SharedMemSize,
-                                                       &bp->SharedMemDMA,
-                                                       GFP_ATOMIC);
+               bp->SharedMemAddr = dma_alloc_coherent(&bp->pdev.dev,
+                                                      bp->SharedMemSize,
+                                                      &bp->SharedMemDMA,
+                                                      GFP_ATOMIC);
                if (!bp->SharedMemAddr) {
                        printk("could not allocate mem for ");
                        printk("hardware module: %ld byte\n",
index 58bbba8..3377ac6 100644 (file)
@@ -1512,9 +1512,13 @@ static void geneve_link_config(struct net_device *dev,
        }
 #if IS_ENABLED(CONFIG_IPV6)
        case AF_INET6: {
-               struct rt6_info *rt = rt6_lookup(geneve->net,
-                                                &info->key.u.ipv6.dst, NULL, 0,
-                                                NULL, 0);
+               struct rt6_info *rt;
+
+               if (!__in6_dev_get(dev))
+                       break;
+
+               rt = rt6_lookup(geneve->net, &info->key.u.ipv6.dst, NULL, 0,
+                               NULL, 0);
 
                if (rt && rt->dst.dev)
                        ldev_mtu = rt->dst.dev->mtu - GENEVE_IPV6_HLEN;
index ef6f766..e859ae2 100644 (file)
@@ -144,6 +144,8 @@ struct hv_netvsc_packet {
        u32 total_data_buflen;
 };
 
+#define NETVSC_HASH_KEYLEN 40
+
 struct netvsc_device_info {
        unsigned char mac_adr[ETH_ALEN];
        u32  num_chn;
@@ -151,6 +153,8 @@ struct netvsc_device_info {
        u32  recv_sections;
        u32  send_section_size;
        u32  recv_section_size;
+
+       u8 rss_key[NETVSC_HASH_KEYLEN];
 };
 
 enum rndis_device_state {
@@ -160,8 +164,6 @@ enum rndis_device_state {
        RNDIS_DEV_DATAINITIALIZED,
 };
 
-#define NETVSC_HASH_KEYLEN 40
-
 struct rndis_device {
        struct net_device *ndev;
 
@@ -209,7 +211,9 @@ int netvsc_recv_callback(struct net_device *net,
 void netvsc_channel_cb(void *context);
 int netvsc_poll(struct napi_struct *napi, int budget);
 
-int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev);
+int rndis_set_subchannel(struct net_device *ndev,
+                        struct netvsc_device *nvdev,
+                        struct netvsc_device_info *dev_info);
 int rndis_filter_open(struct netvsc_device *nvdev);
 int rndis_filter_close(struct netvsc_device *nvdev);
 struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
@@ -1177,7 +1181,7 @@ enum ndis_per_pkt_info_type {
 
 enum rndis_per_pkt_info_interal_type {
        RNDIS_PKTINFO_ID = 1,
-       /* Add more memebers here */
+       /* Add more members here */
 
        RNDIS_PKTINFO_MAX
 };
index 922054c..813d195 100644 (file)
@@ -84,7 +84,7 @@ static void netvsc_subchan_work(struct work_struct *w)
 
        rdev = nvdev->extension;
        if (rdev) {
-               ret = rndis_set_subchannel(rdev->ndev, nvdev);
+               ret = rndis_set_subchannel(rdev->ndev, nvdev, NULL);
                if (ret == 0) {
                        netif_device_attach(rdev->ndev);
                } else {
@@ -1331,7 +1331,7 @@ void netvsc_channel_cb(void *context)
        prefetch(hv_get_ring_buffer(rbi) + rbi->priv_read_index);
 
        if (napi_schedule_prep(&nvchan->napi)) {
-               /* disable interupts from host */
+               /* disable interrupts from host */
                hv_begin_read(rbi);
 
                __napi_schedule_irqoff(&nvchan->napi);
index 91ed15e..256adbd 100644 (file)
@@ -370,7 +370,7 @@ static u32 fill_pg_buf(struct page *page, u32 offset, u32 len,
 {
        int j = 0;
 
-       /* Deal with compund pages by ignoring unused part
+       /* Deal with compound pages by ignoring unused part
         * of the page.
         */
        page += (offset >> PAGE_SHIFT);
@@ -858,6 +858,39 @@ static void netvsc_get_channels(struct net_device *net,
        }
 }
 
+/* Alloc struct netvsc_device_info, and initialize it from either existing
+ * struct netvsc_device, or from default values.
+ */
+static struct netvsc_device_info *netvsc_devinfo_get
+                       (struct netvsc_device *nvdev)
+{
+       struct netvsc_device_info *dev_info;
+
+       dev_info = kzalloc(sizeof(*dev_info), GFP_ATOMIC);
+
+       if (!dev_info)
+               return NULL;
+
+       if (nvdev) {
+               dev_info->num_chn = nvdev->num_chn;
+               dev_info->send_sections = nvdev->send_section_cnt;
+               dev_info->send_section_size = nvdev->send_section_size;
+               dev_info->recv_sections = nvdev->recv_section_cnt;
+               dev_info->recv_section_size = nvdev->recv_section_size;
+
+               memcpy(dev_info->rss_key, nvdev->extension->rss_key,
+                      NETVSC_HASH_KEYLEN);
+       } else {
+               dev_info->num_chn = VRSS_CHANNEL_DEFAULT;
+               dev_info->send_sections = NETVSC_DEFAULT_TX;
+               dev_info->send_section_size = NETVSC_SEND_SECTION_SIZE;
+               dev_info->recv_sections = NETVSC_DEFAULT_RX;
+               dev_info->recv_section_size = NETVSC_RECV_SECTION_SIZE;
+       }
+
+       return dev_info;
+}
+
 static int netvsc_detach(struct net_device *ndev,
                         struct netvsc_device *nvdev)
 {
@@ -909,7 +942,7 @@ static int netvsc_attach(struct net_device *ndev,
                return PTR_ERR(nvdev);
 
        if (nvdev->num_chn > 1) {
-               ret = rndis_set_subchannel(ndev, nvdev);
+               ret = rndis_set_subchannel(ndev, nvdev, dev_info);
 
                /* if unavailable, just proceed with one queue */
                if (ret) {
@@ -943,7 +976,7 @@ static int netvsc_set_channels(struct net_device *net,
        struct net_device_context *net_device_ctx = netdev_priv(net);
        struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev);
        unsigned int orig, count = channels->combined_count;
-       struct netvsc_device_info device_info;
+       struct netvsc_device_info *device_info;
        int ret;
 
        /* We do not support separate count for rx, tx, or other */
@@ -962,24 +995,26 @@ static int netvsc_set_channels(struct net_device *net,
 
        orig = nvdev->num_chn;
 
-       memset(&device_info, 0, sizeof(device_info));
-       device_info.num_chn = count;
-       device_info.send_sections = nvdev->send_section_cnt;
-       device_info.send_section_size = nvdev->send_section_size;
-       device_info.recv_sections = nvdev->recv_section_cnt;
-       device_info.recv_section_size = nvdev->recv_section_size;
+       device_info = netvsc_devinfo_get(nvdev);
+
+       if (!device_info)
+               return -ENOMEM;
+
+       device_info->num_chn = count;
 
        ret = netvsc_detach(net, nvdev);
        if (ret)
-               return ret;
+               goto out;
 
-       ret = netvsc_attach(net, &device_info);
+       ret = netvsc_attach(net, device_info);
        if (ret) {
-               device_info.num_chn = orig;
-               if (netvsc_attach(net, &device_info))
+               device_info->num_chn = orig;
+               if (netvsc_attach(net, device_info))
                        netdev_err(net, "restoring channel setting failed\n");
        }
 
+out:
+       kfree(device_info);
        return ret;
 }
 
@@ -1048,48 +1083,45 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
        struct net_device *vf_netdev = rtnl_dereference(ndevctx->vf_netdev);
        struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
        int orig_mtu = ndev->mtu;
-       struct netvsc_device_info device_info;
+       struct netvsc_device_info *device_info;
        int ret = 0;
 
        if (!nvdev || nvdev->destroy)
                return -ENODEV;
 
+       device_info = netvsc_devinfo_get(nvdev);
+
+       if (!device_info)
+               return -ENOMEM;
+
        /* Change MTU of underlying VF netdev first. */
        if (vf_netdev) {
                ret = dev_set_mtu(vf_netdev, mtu);
                if (ret)
-                       return ret;
+                       goto out;
        }
 
-       memset(&device_info, 0, sizeof(device_info));
-       device_info.num_chn = nvdev->num_chn;
-       device_info.send_sections = nvdev->send_section_cnt;
-       device_info.send_section_size = nvdev->send_section_size;
-       device_info.recv_sections = nvdev->recv_section_cnt;
-       device_info.recv_section_size = nvdev->recv_section_size;
-
        ret = netvsc_detach(ndev, nvdev);
        if (ret)
                goto rollback_vf;
 
        ndev->mtu = mtu;
 
-       ret = netvsc_attach(ndev, &device_info);
-       if (ret)
-               goto rollback;
-
-       return 0;
+       ret = netvsc_attach(ndev, device_info);
+       if (!ret)
+               goto out;
 
-rollback:
        /* Attempt rollback to original MTU */
        ndev->mtu = orig_mtu;
 
-       if (netvsc_attach(ndev, &device_info))
+       if (netvsc_attach(ndev, device_info))
                netdev_err(ndev, "restoring mtu failed\n");
 rollback_vf:
        if (vf_netdev)
                dev_set_mtu(vf_netdev, orig_mtu);
 
+out:
+       kfree(device_info);
        return ret;
 }
 
@@ -1674,7 +1706,7 @@ static int netvsc_set_ringparam(struct net_device *ndev,
 {
        struct net_device_context *ndevctx = netdev_priv(ndev);
        struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
-       struct netvsc_device_info device_info;
+       struct netvsc_device_info *device_info;
        struct ethtool_ringparam orig;
        u32 new_tx, new_rx;
        int ret = 0;
@@ -1694,26 +1726,29 @@ static int netvsc_set_ringparam(struct net_device *ndev,
            new_rx == orig.rx_pending)
                return 0;        /* no change */
 
-       memset(&device_info, 0, sizeof(device_info));
-       device_info.num_chn = nvdev->num_chn;
-       device_info.send_sections = new_tx;
-       device_info.send_section_size = nvdev->send_section_size;
-       device_info.recv_sections = new_rx;
-       device_info.recv_section_size = nvdev->recv_section_size;
+       device_info = netvsc_devinfo_get(nvdev);
+
+       if (!device_info)
+               return -ENOMEM;
+
+       device_info->send_sections = new_tx;
+       device_info->recv_sections = new_rx;
 
        ret = netvsc_detach(ndev, nvdev);
        if (ret)
-               return ret;
+               goto out;
 
-       ret = netvsc_attach(ndev, &device_info);
+       ret = netvsc_attach(ndev, device_info);
        if (ret) {
-               device_info.send_sections = orig.tx_pending;
-               device_info.recv_sections = orig.rx_pending;
+               device_info->send_sections = orig.tx_pending;
+               device_info->recv_sections = orig.rx_pending;
 
-               if (netvsc_attach(ndev, &device_info))
+               if (netvsc_attach(ndev, device_info))
                        netdev_err(ndev, "restoring ringparam failed");
        }
 
+out:
+       kfree(device_info);
        return ret;
 }
 
@@ -2088,7 +2123,7 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
        if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev))
                return NOTIFY_DONE;
 
-       /* if syntihetic interface is a different namespace,
+       /* if synthetic interface is a different namespace,
         * then move the VF to that namespace; join will be
         * done again in that context.
         */
@@ -2167,7 +2202,7 @@ static int netvsc_probe(struct hv_device *dev,
 {
        struct net_device *net = NULL;
        struct net_device_context *net_device_ctx;
-       struct netvsc_device_info device_info;
+       struct netvsc_device_info *device_info = NULL;
        struct netvsc_device *nvdev;
        int ret = -ENOMEM;
 
@@ -2214,21 +2249,21 @@ static int netvsc_probe(struct hv_device *dev,
        netif_set_real_num_rx_queues(net, 1);
 
        /* Notify the netvsc driver of the new device */
-       memset(&device_info, 0, sizeof(device_info));
-       device_info.num_chn = VRSS_CHANNEL_DEFAULT;
-       device_info.send_sections = NETVSC_DEFAULT_TX;
-       device_info.send_section_size = NETVSC_SEND_SECTION_SIZE;
-       device_info.recv_sections = NETVSC_DEFAULT_RX;
-       device_info.recv_section_size = NETVSC_RECV_SECTION_SIZE;
-
-       nvdev = rndis_filter_device_add(dev, &device_info);
+       device_info = netvsc_devinfo_get(NULL);
+
+       if (!device_info) {
+               ret = -ENOMEM;
+               goto devinfo_failed;
+       }
+
+       nvdev = rndis_filter_device_add(dev, device_info);
        if (IS_ERR(nvdev)) {
                ret = PTR_ERR(nvdev);
                netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
                goto rndis_failed;
        }
 
-       memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
+       memcpy(net->dev_addr, device_info->mac_adr, ETH_ALEN);
 
        /* We must get rtnl lock before scheduling nvdev->subchan_work,
         * otherwise netvsc_subchan_work() can get rtnl lock first and wait
@@ -2236,7 +2271,7 @@ static int netvsc_probe(struct hv_device *dev,
         * netvsc_probe() can't get rtnl lock and as a result vmbus_onoffer()
         * -> ... -> device_add() -> ... -> __device_attach() can't get
         * the device lock, so all the subchannels can't be processed --
-        * finally netvsc_subchan_work() hangs for ever.
+        * finally netvsc_subchan_work() hangs forever.
         */
        rtnl_lock();
 
@@ -2266,12 +2301,16 @@ static int netvsc_probe(struct hv_device *dev,
 
        list_add(&net_device_ctx->list, &netvsc_dev_list);
        rtnl_unlock();
+
+       kfree(device_info);
        return 0;
 
 register_failed:
        rtnl_unlock();
        rndis_filter_device_remove(dev, nvdev);
 rndis_failed:
+       kfree(device_info);
+devinfo_failed:
        free_percpu(net_device_ctx->vf_stats);
 no_stats:
        hv_set_drvdata(dev, NULL);
index 8b537a0..73b6059 100644 (file)
@@ -774,8 +774,8 @@ cleanup:
        return ret;
 }
 
-int rndis_filter_set_rss_param(struct rndis_device *rdev,
-                              const u8 *rss_key)
+static int rndis_set_rss_param_msg(struct rndis_device *rdev,
+                                  const u8 *rss_key, u16 flag)
 {
        struct net_device *ndev = rdev->ndev;
        struct rndis_request *request;
@@ -804,7 +804,7 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev,
        rssp->hdr.type = NDIS_OBJECT_TYPE_RSS_PARAMETERS;
        rssp->hdr.rev = NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
        rssp->hdr.size = sizeof(struct ndis_recv_scale_param);
-       rssp->flag = 0;
+       rssp->flag = flag;
        rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 |
                         NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 |
                         NDIS_HASH_TCP_IPV6;
@@ -829,9 +829,12 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev,
 
        wait_for_completion(&request->wait_event);
        set_complete = &request->response_msg.msg.set_complete;
-       if (set_complete->status == RNDIS_STATUS_SUCCESS)
-               memcpy(rdev->rss_key, rss_key, NETVSC_HASH_KEYLEN);
-       else {
+       if (set_complete->status == RNDIS_STATUS_SUCCESS) {
+               if (!(flag & NDIS_RSS_PARAM_FLAG_DISABLE_RSS) &&
+                   !(flag & NDIS_RSS_PARAM_FLAG_HASH_KEY_UNCHANGED))
+                       memcpy(rdev->rss_key, rss_key, NETVSC_HASH_KEYLEN);
+
+       } else {
                netdev_err(ndev, "Fail to set RSS parameters:0x%x\n",
                           set_complete->status);
                ret = -EINVAL;
@@ -842,6 +845,16 @@ cleanup:
        return ret;
 }
 
+int rndis_filter_set_rss_param(struct rndis_device *rdev,
+                              const u8 *rss_key)
+{
+       /* Disable RSS before change */
+       rndis_set_rss_param_msg(rdev, rss_key,
+                               NDIS_RSS_PARAM_FLAG_DISABLE_RSS);
+
+       return rndis_set_rss_param_msg(rdev, rss_key, 0);
+}
+
 static int rndis_filter_query_device_link_status(struct rndis_device *dev,
                                                 struct netvsc_device *net_device)
 {
@@ -1121,7 +1134,9 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)
  * This breaks overlap of processing the host message for the
  * new primary channel with the initialization of sub-channels.
  */
-int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev)
+int rndis_set_subchannel(struct net_device *ndev,
+                        struct netvsc_device *nvdev,
+                        struct netvsc_device_info *dev_info)
 {
        struct nvsp_message *init_packet = &nvdev->channel_init_pkt;
        struct net_device_context *ndev_ctx = netdev_priv(ndev);
@@ -1161,8 +1176,11 @@ int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev)
        wait_event(nvdev->subchan_open,
                   atomic_read(&nvdev->open_chn) == nvdev->num_chn);
 
-       /* ignore failues from setting rss parameters, still have channels */
-       rndis_filter_set_rss_param(rdev, netvsc_hash_key);
+       /* ignore failures from setting rss parameters, still have channels */
+       if (dev_info)
+               rndis_filter_set_rss_param(rdev, dev_info->rss_key);
+       else
+               rndis_filter_set_rss_param(rdev, netvsc_hash_key);
 
        netif_set_real_num_tx_queues(ndev, nvdev->num_chn);
        netif_set_real_num_rx_queues(ndev, nvdev->num_chn);
index 44de81e..c589f5a 100644 (file)
@@ -905,9 +905,9 @@ mcr20a_irq_clean_complete(void *context)
                }
                break;
        case (DAR_IRQSTS1_RXIRQ | DAR_IRQSTS1_SEQIRQ):
-                       /* rx is starting */
-                       dev_dbg(printdev(lp), "RX is starting\n");
-                       mcr20a_handle_rx(lp);
+               /* rx is starting */
+               dev_dbg(printdev(lp), "RX is starting\n");
+               mcr20a_handle_rx(lp);
                break;
        case (DAR_IRQSTS1_RXIRQ | DAR_IRQSTS1_TXIRQ | DAR_IRQSTS1_SEQIRQ):
                if (lp->is_tx) {
index 19bdde6..7cdac77 100644 (file)
@@ -100,12 +100,12 @@ static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval,
                        err = ipvlan_register_nf_hook(read_pnet(&port->pnet));
                        if (!err) {
                                mdev->l3mdev_ops = &ipvl_l3mdev_ops;
-                               mdev->priv_flags |= IFF_L3MDEV_MASTER;
+                               mdev->priv_flags |= IFF_L3MDEV_RX_HANDLER;
                        } else
                                goto fail;
                } else if (port->mode == IPVLAN_MODE_L3S) {
                        /* Old mode was L3S */
-                       mdev->priv_flags &= ~IFF_L3MDEV_MASTER;
+                       mdev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER;
                        ipvlan_unregister_nf_hook(read_pnet(&port->pnet));
                        mdev->l3mdev_ops = NULL;
                }
@@ -167,7 +167,7 @@ static void ipvlan_port_destroy(struct net_device *dev)
        struct sk_buff *skb;
 
        if (port->mode == IPVLAN_MODE_L3S) {
-               dev->priv_flags &= ~IFF_L3MDEV_MASTER;
+               dev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER;
                ipvlan_unregister_nf_hook(dev_net(dev));
                dev->l3mdev_ops = NULL;
        }
index fc726ce..6d06717 100644 (file)
@@ -337,7 +337,7 @@ static void macvlan_process_broadcast(struct work_struct *w)
 
                if (src)
                        dev_put(src->dev);
-               kfree_skb(skb);
+               consume_skb(skb);
        }
 }
 
index 8ebe7f5..f14ba53 100644 (file)
@@ -1,13 +1,7 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
 /* Driver for Asix PHYs
  *
  * Author: Michael Schmitz <schmitzmic@gmail.com>
- *
- * 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.
- *
  */
 #include <linux/kernel.h>
 #include <linux/errno.h>
index 1b35018..a271239 100644 (file)
@@ -197,6 +197,7 @@ static struct phy_driver bcm87xx_driver[] = {
        .phy_id         = PHY_ID_BCM8706,
        .phy_id_mask    = 0xffffffff,
        .name           = "Broadcom BCM8706",
+       .features       = PHY_10GBIT_FEC_FEATURES,
        .config_init    = bcm87xx_config_init,
        .config_aneg    = bcm87xx_config_aneg,
        .read_status    = bcm87xx_read_status,
@@ -208,6 +209,7 @@ static struct phy_driver bcm87xx_driver[] = {
        .phy_id         = PHY_ID_BCM8727,
        .phy_id_mask    = 0xffffffff,
        .name           = "Broadcom BCM8727",
+       .features       = PHY_10GBIT_FEC_FEATURES,
        .config_init    = bcm87xx_config_init,
        .config_aneg    = bcm87xx_config_aneg,
        .read_status    = bcm87xx_read_status,
index 8022cd3..1a4d04a 100644 (file)
@@ -88,6 +88,7 @@ static struct phy_driver cortina_driver[] = {
        .phy_id         = PHY_ID_CS4340,
        .phy_id_mask    = 0xffffffff,
        .name           = "Cortina CS4340",
+       .features       = PHY_10GBIT_FEATURES,
        .config_init    = gen10g_config_init,
        .config_aneg    = gen10g_config_aneg,
        .read_status    = cortina_read_status,
index 18b41bc..6e88072 100644 (file)
@@ -898,14 +898,14 @@ static void decode_txts(struct dp83640_private *dp83640,
                        struct phy_txts *phy_txts)
 {
        struct skb_shared_hwtstamps shhwtstamps;
+       struct dp83640_skb_info *skb_info;
        struct sk_buff *skb;
-       u64 ns;
        u8 overflow;
+       u64 ns;
 
        /* We must already have the skb that triggered this. */
-
+again:
        skb = skb_dequeue(&dp83640->tx_queue);
-
        if (!skb) {
                pr_debug("have timestamp but tx_queue empty\n");
                return;
@@ -920,6 +920,11 @@ static void decode_txts(struct dp83640_private *dp83640,
                }
                return;
        }
+       skb_info = (struct dp83640_skb_info *)skb->cb;
+       if (time_after(jiffies, skb_info->tmo)) {
+               kfree_skb(skb);
+               goto again;
+       }
 
        ns = phy2txts(phy_txts);
        memset(&shhwtstamps, 0, sizeof(shhwtstamps));
@@ -1472,6 +1477,7 @@ static bool dp83640_rxtstamp(struct phy_device *phydev,
 static void dp83640_txtstamp(struct phy_device *phydev,
                             struct sk_buff *skb, int type)
 {
+       struct dp83640_skb_info *skb_info = (struct dp83640_skb_info *)skb->cb;
        struct dp83640_private *dp83640 = phydev->priv;
 
        switch (dp83640->hwts_tx_en) {
@@ -1484,6 +1490,7 @@ static void dp83640_txtstamp(struct phy_device *phydev,
                /* fall through */
        case HWTSTAMP_TX_ON:
                skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+               skb_info->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT;
                skb_queue_tail(&dp83640->tx_queue, skb);
                break;
 
index a9c7c7f..abb7876 100644 (file)
@@ -847,7 +847,6 @@ static int m88e1510_config_init(struct phy_device *phydev)
 
        /* SGMII-to-Copper mode initialization */
        if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
-
                /* Select page 18 */
                err = marvell_set_page(phydev, 18);
                if (err < 0)
@@ -870,21 +869,6 @@ static int m88e1510_config_init(struct phy_device *phydev)
                err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
                if (err < 0)
                        return err;
-
-               /* There appears to be a bug in the 88e1512 when used in
-                * SGMII to copper mode, where the AN advertisement register
-                * clears the pause bits each time a negotiation occurs.
-                * This means we can never be truely sure what was advertised,
-                * so disable Pause support.
-                */
-               linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
-                                  phydev->supported);
-               linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT,
-                                  phydev->supported);
-               linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
-                                  phydev->advertising);
-               linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT,
-                                  phydev->advertising);
        }
 
        return m88e1318_config_init(phydev);
@@ -1046,6 +1030,39 @@ static int m88e1145_config_init(struct phy_device *phydev)
        return 0;
 }
 
+/* The VOD can be out of specification on link up. Poke an
+ * undocumented register, in an undocumented page, with a magic value
+ * to fix this.
+ */
+static int m88e6390_errata(struct phy_device *phydev)
+{
+       int err;
+
+       err = phy_write(phydev, MII_BMCR,
+                       BMCR_ANENABLE | BMCR_SPEED1000 | BMCR_FULLDPLX);
+       if (err)
+               return err;
+
+       usleep_range(300, 400);
+
+       err = phy_write_paged(phydev, 0xf8, 0x08, 0x36);
+       if (err)
+               return err;
+
+       return genphy_soft_reset(phydev);
+}
+
+static int m88e6390_config_aneg(struct phy_device *phydev)
+{
+       int err;
+
+       err = m88e6390_errata(phydev);
+       if (err)
+               return err;
+
+       return m88e1510_config_aneg(phydev);
+}
+
 /**
  * fiber_lpa_mod_linkmode_lpa_t
  * @advertising: the linkmode advertisement settings
@@ -1402,7 +1419,7 @@ static int m88e1318_set_wol(struct phy_device *phydev,
                 * before enabling it if !phy_interrupt_is_valid()
                 */
                if (!phy_interrupt_is_valid(phydev))
-                       phy_read(phydev, MII_M1011_IEVENT);
+                       __phy_read(phydev, MII_M1011_IEVENT);
 
                /* Enable the WOL interrupt */
                err = __phy_modify(phydev, MII_88E1318S_PHY_CSIER, 0,
@@ -2283,7 +2300,7 @@ static struct phy_driver marvell_drivers[] = {
                .features = PHY_GBIT_FEATURES,
                .probe = m88e6390_probe,
                .config_init = &marvell_config_init,
-               .config_aneg = &m88e1510_config_aneg,
+               .config_aneg = &m88e6390_config_aneg,
                .read_status = &marvell_read_status,
                .ack_interrupt = &marvell_ack_interrupt,
                .config_intr = &marvell_config_intr,
index b03fedd..287f3cc 100644 (file)
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Hisilicon Fast Ethernet MDIO Bus Driver
  *
  * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; 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.  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, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/clk.h>
@@ -163,4 +151,4 @@ module_platform_driver(hisi_femac_mdio_driver);
 
 MODULE_DESCRIPTION("Hisilicon Fast Ethernet MAC MDIO interface driver");
 MODULE_AUTHOR("Dongpo Li <lidongpo@hisilicon.com>");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
index 2e59a84..66b9cfe 100644 (file)
@@ -390,6 +390,7 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
        if (IS_ERR(gpiod)) {
                dev_err(&bus->dev, "mii_bus %s couldn't get reset GPIO\n",
                        bus->id);
+               device_del(&bus->dev);
                return PTR_ERR(gpiod);
        } else  if (gpiod) {
                bus->reset_gpiod = gpiod;
index b03bcf2..3ddaf95 100644 (file)
@@ -233,6 +233,7 @@ static struct phy_driver meson_gxl_phy[] = {
                .name           = "Meson GXL Internal PHY",
                .features       = PHY_BASIC_FEATURES,
                .flags          = PHY_IS_INTERNAL,
+               .soft_reset     = genphy_soft_reset,
                .config_init    = meson_gxl_config_init,
                .aneg_done      = genphy_aneg_done,
                .read_status    = meson_gxl_read_status,
index c333847..b1f9599 100644 (file)
@@ -1070,6 +1070,7 @@ static struct phy_driver ksphy_driver[] = {
        .driver_data    = &ksz9021_type,
        .probe          = kszphy_probe,
        .config_init    = ksz9031_config_init,
+       .soft_reset     = genphy_soft_reset,
        .read_status    = ksz9031_read_status,
        .ack_interrupt  = kszphy_ack_interrupt,
        .config_intr    = kszphy_config_intr,
@@ -1098,6 +1099,7 @@ static struct phy_driver ksphy_driver[] = {
        .phy_id         = PHY_ID_KSZ8873MLL,
        .phy_id_mask    = MICREL_PHY_ID_MASK,
        .name           = "Micrel KSZ8873MLL Switch",
+       .features       = PHY_BASIC_FEATURES,
        .config_init    = kszphy_config_init,
        .config_aneg    = ksz8873mll_config_aneg,
        .read_status    = ksz8873mll_read_status,
index d33e7b3..c5675df 100644 (file)
@@ -543,13 +543,6 @@ int phy_start_aneg(struct phy_device *phydev)
 
        mutex_lock(&phydev->lock);
 
-       if (!__phy_is_started(phydev)) {
-               WARN(1, "called from state %s\n",
-                    phy_state_to_str(phydev->state));
-               err = -EBUSY;
-               goto out_unlock;
-       }
-
        if (AUTONEG_DISABLE == phydev->autoneg)
                phy_sanitize_settings(phydev);
 
@@ -560,11 +553,13 @@ int phy_start_aneg(struct phy_device *phydev)
        if (err < 0)
                goto out_unlock;
 
-       if (phydev->autoneg == AUTONEG_ENABLE) {
-               err = phy_check_link_status(phydev);
-       } else {
-               phydev->state = PHY_FORCING;
-               phydev->link_timeout = PHY_FORCE_TIMEOUT;
+       if (phy_is_started(phydev)) {
+               if (phydev->autoneg == AUTONEG_ENABLE) {
+                       err = phy_check_link_status(phydev);
+               } else {
+                       phydev->state = PHY_FORCING;
+                       phydev->link_timeout = PHY_FORCE_TIMEOUT;
+               }
        }
 
 out_unlock:
@@ -714,7 +709,7 @@ void phy_stop_machine(struct phy_device *phydev)
        cancel_delayed_work_sync(&phydev->state_queue);
 
        mutex_lock(&phydev->lock);
-       if (__phy_is_started(phydev))
+       if (phy_is_started(phydev))
                phydev->state = PHY_UP;
        mutex_unlock(&phydev->lock);
 }
@@ -767,9 +762,6 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
 {
        struct phy_device *phydev = phy_dat;
 
-       if (!phy_is_started(phydev))
-               return IRQ_NONE;                /* It can't be ours.  */
-
        if (phydev->drv->did_interrupt && !phydev->drv->did_interrupt(phydev))
                return IRQ_NONE;
 
@@ -847,15 +839,14 @@ EXPORT_SYMBOL(phy_stop_interrupts);
  */
 void phy_stop(struct phy_device *phydev)
 {
-       mutex_lock(&phydev->lock);
-
-       if (!__phy_is_started(phydev)) {
+       if (!phy_is_started(phydev)) {
                WARN(1, "called from state %s\n",
                     phy_state_to_str(phydev->state));
-               mutex_unlock(&phydev->lock);
                return;
        }
 
+       mutex_lock(&phydev->lock);
+
        if (phy_interrupt_is_valid(phydev))
                phy_disable_interrupts(phydev);
 
@@ -994,8 +985,10 @@ void phy_state_machine(struct work_struct *work)
         * state machine would be pointless and possibly error prone when
         * called from phy_disconnect() synchronously.
         */
+       mutex_lock(&phydev->lock);
        if (phy_polling_mode(phydev) && phy_is_started(phydev))
                phy_queue_state_machine(phydev, PHY_STATE_TIME);
+       mutex_unlock(&phydev->lock);
 }
 
 /**
index 5199000..46c8672 100644 (file)
@@ -61,6 +61,9 @@ EXPORT_SYMBOL_GPL(phy_gbit_all_ports_features);
 __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_features) __ro_after_init;
 EXPORT_SYMBOL_GPL(phy_10gbit_features);
 
+__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_fec_features) __ro_after_init;
+EXPORT_SYMBOL_GPL(phy_10gbit_fec_features);
+
 static const int phy_basic_ports_array[] = {
        ETHTOOL_LINK_MODE_Autoneg_BIT,
        ETHTOOL_LINK_MODE_TP_BIT,
@@ -109,6 +112,11 @@ const int phy_10gbit_features_array[1] = {
 };
 EXPORT_SYMBOL_GPL(phy_10gbit_features_array);
 
+const int phy_10gbit_fec_features_array[1] = {
+       ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
+};
+EXPORT_SYMBOL_GPL(phy_10gbit_fec_features_array);
+
 __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) __ro_after_init;
 EXPORT_SYMBOL_GPL(phy_10gbit_full_features);
 
@@ -191,6 +199,10 @@ static void features_init(void)
        linkmode_set_bit_array(phy_10gbit_full_features_array,
                               ARRAY_SIZE(phy_10gbit_full_features_array),
                               phy_10gbit_full_features);
+       /* 10G FEC only */
+       linkmode_set_bit_array(phy_10gbit_fec_features_array,
+                              ARRAY_SIZE(phy_10gbit_fec_features_array),
+                              phy_10gbit_fec_features);
 }
 
 void phy_device_free(struct phy_device *phydev)
@@ -2243,6 +2255,11 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner)
 {
        int retval;
 
+       if (WARN_ON(!new_driver->features)) {
+               pr_err("%s: Driver features are missing\n", new_driver->name);
+               return -EINVAL;
+       }
+
        new_driver->mdiodrv.flags |= MDIO_DEVICE_IS_PHY;
        new_driver->mdiodrv.driver.name = new_driver->name;
        new_driver->mdiodrv.driver.bus = &mdio_bus_type;
index e7becc7..9388032 100644 (file)
@@ -474,6 +474,17 @@ static void phylink_run_resolve(struct phylink *pl)
                queue_work(system_power_efficient_wq, &pl->resolve);
 }
 
+static void phylink_run_resolve_and_disable(struct phylink *pl, int bit)
+{
+       unsigned long state = pl->phylink_disable_state;
+
+       set_bit(bit, &pl->phylink_disable_state);
+       if (state == 0) {
+               queue_work(system_power_efficient_wq, &pl->resolve);
+               flush_work(&pl->resolve);
+       }
+}
+
 static void phylink_fixed_poll(struct timer_list *t)
 {
        struct phylink *pl = container_of(t, struct phylink, link_poll);
@@ -924,9 +935,7 @@ void phylink_stop(struct phylink *pl)
        if (pl->link_an_mode == MLO_AN_FIXED && !IS_ERR(pl->link_gpio))
                del_timer_sync(&pl->link_poll);
 
-       set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
-       queue_work(system_power_efficient_wq, &pl->resolve);
-       flush_work(&pl->resolve);
+       phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED);
 }
 EXPORT_SYMBOL_GPL(phylink_stop);
 
@@ -1632,9 +1641,7 @@ static void phylink_sfp_link_down(void *upstream)
 
        ASSERT_RTNL();
 
-       set_bit(PHYLINK_DISABLE_LINK, &pl->phylink_disable_state);
-       queue_work(system_power_efficient_wq, &pl->resolve);
-       flush_work(&pl->resolve);
+       phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_LINK);
 }
 
 static void phylink_sfp_link_up(void *upstream)
index f1da70b..95abf70 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /**
  * drivers/net/phy/rockchip.c
  *
@@ -6,12 +7,6 @@
  * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
  *
  * David Wu <david.wu@rock-chips.com>
- *
- * 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.
- *
  */
 
 #include <linux/ethtool.h>
@@ -229,4 +224,4 @@ MODULE_DEVICE_TABLE(mdio, rockchip_phy_tbl);
 
 MODULE_AUTHOR("David Wu <david.wu@rock-chips.com>");
 MODULE_DESCRIPTION("Rockchip Ethernet PHY driver");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
index ad9db65..fef701b 100644 (file)
@@ -347,6 +347,7 @@ static int sfp_register_bus(struct sfp_bus *bus)
                                return ret;
                }
        }
+       bus->socket_ops->attach(bus->sfp);
        if (bus->started)
                bus->socket_ops->start(bus->sfp);
        bus->netdev->sfp_bus = bus;
@@ -362,6 +363,7 @@ static void sfp_unregister_bus(struct sfp_bus *bus)
        if (bus->registered) {
                if (bus->started)
                        bus->socket_ops->stop(bus->sfp);
+               bus->socket_ops->detach(bus->sfp);
                if (bus->phydev && ops && ops->disconnect_phy)
                        ops->disconnect_phy(bus->upstream);
        }
index fd8bb99..68c8fbf 100644 (file)
@@ -184,6 +184,7 @@ struct sfp {
 
        struct gpio_desc *gpio[GPIO_MAX];
 
+       bool attached;
        unsigned int state;
        struct delayed_work poll;
        struct delayed_work timeout;
@@ -1475,7 +1476,7 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event)
         */
        switch (sfp->sm_mod_state) {
        default:
-               if (event == SFP_E_INSERT) {
+               if (event == SFP_E_INSERT && sfp->attached) {
                        sfp_module_tx_disable(sfp);
                        sfp_sm_ins_next(sfp, SFP_MOD_PROBE, T_PROBE_INIT);
                }
@@ -1607,6 +1608,19 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event)
        mutex_unlock(&sfp->sm_mutex);
 }
 
+static void sfp_attach(struct sfp *sfp)
+{
+       sfp->attached = true;
+       if (sfp->state & SFP_F_PRESENT)
+               sfp_sm_event(sfp, SFP_E_INSERT);
+}
+
+static void sfp_detach(struct sfp *sfp)
+{
+       sfp->attached = false;
+       sfp_sm_event(sfp, SFP_E_REMOVE);
+}
+
 static void sfp_start(struct sfp *sfp)
 {
        sfp_sm_event(sfp, SFP_E_DEV_UP);
@@ -1667,6 +1681,8 @@ static int sfp_module_eeprom(struct sfp *sfp, struct ethtool_eeprom *ee,
 }
 
 static const struct sfp_socket_ops sfp_module_ops = {
+       .attach = sfp_attach,
+       .detach = sfp_detach,
        .start = sfp_start,
        .stop = sfp_stop,
        .module_info = sfp_module_info,
@@ -1834,10 +1850,6 @@ static int sfp_probe(struct platform_device *pdev)
        dev_info(sfp->dev, "Host maximum power %u.%uW\n",
                 sfp->max_power_mW / 1000, (sfp->max_power_mW / 100) % 10);
 
-       sfp->sfp_bus = sfp_register_socket(sfp->dev, sfp, &sfp_module_ops);
-       if (!sfp->sfp_bus)
-               return -ENOMEM;
-
        /* Get the initial state, and always signal TX disable,
         * since the network interface will not be up.
         */
@@ -1848,10 +1860,6 @@ static int sfp_probe(struct platform_device *pdev)
                sfp->state |= SFP_F_RATE_SELECT;
        sfp_set_state(sfp, sfp->state);
        sfp_module_tx_disable(sfp);
-       rtnl_lock();
-       if (sfp->state & SFP_F_PRESENT)
-               sfp_sm_event(sfp, SFP_E_INSERT);
-       rtnl_unlock();
 
        for (i = 0; i < GPIO_MAX; i++) {
                if (gpio_flags[i] != GPIOD_IN || !sfp->gpio[i])
@@ -1884,6 +1892,10 @@ static int sfp_probe(struct platform_device *pdev)
                dev_warn(sfp->dev,
                         "No tx_disable pin: SFP modules will always be emitting.\n");
 
+       sfp->sfp_bus = sfp_register_socket(sfp->dev, sfp, &sfp_module_ops);
+       if (!sfp->sfp_bus)
+               return -ENOMEM;
+
        return 0;
 }
 
index 31b0acf..64f54b0 100644 (file)
@@ -7,6 +7,8 @@
 struct sfp;
 
 struct sfp_socket_ops {
+       void (*attach)(struct sfp *sfp);
+       void (*detach)(struct sfp *sfp);
        void (*start)(struct sfp *sfp);
        void (*stop)(struct sfp *sfp);
        int (*module_info)(struct sfp *sfp, struct ethtool_modinfo *modinfo);
index 22f3bdd..9124718 100644 (file)
@@ -80,6 +80,7 @@ static struct phy_driver teranetics_driver[] = {
        .phy_id         = PHY_ID_TN2020,
        .phy_id_mask    = 0xffffffff,
        .name           = "Teranetics TN2020",
+       .features       = PHY_10GBIT_FEATURES,
        .soft_reset     = gen10g_no_soft_reset,
        .aneg_done      = teranetics_aneg_done,
        .config_init    = gen10g_config_init,
index 62dc564..f22639f 100644 (file)
@@ -445,6 +445,7 @@ static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev,
        if (pskb_trim_rcsum(skb, len))
                goto drop;
 
+       ph = pppoe_hdr(skb);
        pn = pppoe_pernet(dev_net(dev));
 
        /* Note that get_item does a sock_hold(), so sk_pppox(po)
index afd9d25..958f1cf 100644 (file)
@@ -256,17 +256,6 @@ static void __team_option_inst_mark_removed_port(struct team *team,
        }
 }
 
-static bool __team_option_inst_tmp_find(const struct list_head *opts,
-                                       const struct team_option_inst *needle)
-{
-       struct team_option_inst *opt_inst;
-
-       list_for_each_entry(opt_inst, opts, tmp_list)
-               if (opt_inst == needle)
-                       return true;
-       return false;
-}
-
 static int __team_options_register(struct team *team,
                                   const struct team_option *option,
                                   size_t option_count)
@@ -2460,7 +2449,6 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
        int err = 0;
        int i;
        struct nlattr *nl_option;
-       LIST_HEAD(opt_inst_list);
 
        rtnl_lock();
 
@@ -2480,6 +2468,7 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
                struct nlattr *opt_attrs[TEAM_ATTR_OPTION_MAX + 1];
                struct nlattr *attr;
                struct nlattr *attr_data;
+               LIST_HEAD(opt_inst_list);
                enum team_option_type opt_type;
                int opt_port_ifindex = 0; /* != 0 for per-port options */
                u32 opt_array_index = 0;
@@ -2584,23 +2573,17 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
                        if (err)
                                goto team_put;
                        opt_inst->changed = true;
-
-                       /* dumb/evil user-space can send us duplicate opt,
-                        * keep only the last one
-                        */
-                       if (__team_option_inst_tmp_find(&opt_inst_list,
-                                                       opt_inst))
-                               continue;
-
                        list_add(&opt_inst->tmp_list, &opt_inst_list);
                }
                if (!opt_found) {
                        err = -ENOENT;
                        goto team_put;
                }
-       }
 
-       err = team_nl_send_event_options_get(team, &opt_inst_list);
+               err = team_nl_send_event_options_get(team, &opt_inst_list);
+               if (err)
+                       break;
+       }
 
 team_put:
        team_nl_team_put(team);
index a4fdad4..fed298c 100644 (file)
@@ -856,10 +856,6 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
                err = 0;
        }
 
-       rcu_assign_pointer(tfile->tun, tun);
-       rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
-       tun->numqueues++;
-
        if (tfile->detached) {
                tun_enable_queue(tfile);
        } else {
@@ -870,12 +866,18 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
        if (rtnl_dereference(tun->xdp_prog))
                sock_set_flag(&tfile->sk, SOCK_XDP);
 
-       tun_set_real_num_queues(tun);
-
        /* device is allowed to go away first, so no need to hold extra
         * refcnt.
         */
 
+       /* Publish tfile->tun and tun->tfiles only after we've fully
+        * initialized tfile; otherwise we risk using half-initialized
+        * object.
+        */
+       rcu_assign_pointer(tfile->tun, tun);
+       rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
+       tun->numqueues++;
+       tun_set_real_num_queues(tun);
 out:
        return err;
 }
index 57f1c94..820a2fe 100644 (file)
@@ -1287,6 +1287,20 @@ static const struct driver_info asix112_info = {
 
 #undef ASIX112_DESC
 
+static const struct driver_info trendnet_info = {
+       .description    = "USB-C 3.1 to 5GBASE-T Ethernet Adapter",
+       .bind           = aqc111_bind,
+       .unbind         = aqc111_unbind,
+       .status         = aqc111_status,
+       .link_reset     = aqc111_link_reset,
+       .reset          = aqc111_reset,
+       .stop           = aqc111_stop,
+       .flags          = FLAG_ETHER | FLAG_FRAMING_AX |
+                         FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET,
+       .rx_fixup       = aqc111_rx_fixup,
+       .tx_fixup       = aqc111_tx_fixup,
+};
+
 static int aqc111_suspend(struct usb_interface *intf, pm_message_t message)
 {
        struct usbnet *dev = usb_get_intfdata(intf);
@@ -1440,6 +1454,7 @@ static const struct usb_device_id products[] = {
        {AQC111_USB_ETH_DEV(0x2eca, 0xc101, aqc111_info)},
        {AQC111_USB_ETH_DEV(0x0b95, 0x2790, asix111_info)},
        {AQC111_USB_ETH_DEV(0x0b95, 0x2791, asix112_info)},
+       {AQC111_USB_ETH_DEV(0x20f4, 0xe05a, trendnet_info)},
        { },/* END */
 };
 MODULE_DEVICE_TABLE(usb, products);
index b654f05..3d93993 100644 (file)
@@ -739,8 +739,13 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
        asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, 0, 0, 1, &chipcode, 0);
        chipcode &= AX_CHIPCODE_MASK;
 
-       (chipcode == AX_AX88772_CHIPCODE) ? ax88772_hw_reset(dev, 0) :
-                                           ax88772a_hw_reset(dev, 0);
+       ret = (chipcode == AX_AX88772_CHIPCODE) ? ax88772_hw_reset(dev, 0) :
+                                                 ax88772a_hw_reset(dev, 0);
+
+       if (ret < 0) {
+               netdev_dbg(dev->net, "Failed to reset AX88772: %d\n", ret);
+               return ret;
+       }
 
        /* Read PHYID register *AFTER* the PHY was reset properly */
        phyid = asix_get_phyid(dev);
index b3b3c05..5512a10 100644 (file)
@@ -179,10 +179,8 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
         * probed with) and a slave/data interface; union
         * descriptors sort this all out.
         */
-       info->control = usb_ifnum_to_if(dev->udev,
-       info->u->bMasterInterface0);
-       info->data = usb_ifnum_to_if(dev->udev,
-               info->u->bSlaveInterface0);
+       info->control = usb_ifnum_to_if(dev->udev, info->u->bMasterInterface0);
+       info->data = usb_ifnum_to_if(dev->udev, info->u->bSlaveInterface0);
        if (!info->control || !info->data) {
                dev_dbg(&intf->dev,
                        "master #%u/%p slave #%u/%p\n",
@@ -216,18 +214,16 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
        /* a data interface altsetting does the real i/o */
        d = &info->data->cur_altsetting->desc;
        if (d->bInterfaceClass != USB_CLASS_CDC_DATA) {
-               dev_dbg(&intf->dev, "slave class %u\n",
-                       d->bInterfaceClass);
+               dev_dbg(&intf->dev, "slave class %u\n", d->bInterfaceClass);
                goto bad_desc;
        }
 skip:
-       if (    rndis &&
-               header.usb_cdc_acm_descriptor &&
-               header.usb_cdc_acm_descriptor->bmCapabilities) {
-                       dev_dbg(&intf->dev,
-                               "ACM capabilities %02x, not really RNDIS?\n",
-                               header.usb_cdc_acm_descriptor->bmCapabilities);
-                       goto bad_desc;
+       if (rndis && header.usb_cdc_acm_descriptor &&
+           header.usb_cdc_acm_descriptor->bmCapabilities) {
+               dev_dbg(&intf->dev,
+                       "ACM capabilities %02x, not really RNDIS?\n",
+                       header.usb_cdc_acm_descriptor->bmCapabilities);
+               goto bad_desc;
        }
 
        if (header.usb_cdc_ether_desc && info->ether->wMaxSegmentSize) {
@@ -238,7 +234,7 @@ skip:
        }
 
        if (header.usb_cdc_mdlm_desc &&
-               memcmp(header.usb_cdc_mdlm_desc->bGUID, mbm_guid, 16)) {
+           memcmp(header.usb_cdc_mdlm_desc->bGUID, mbm_guid, 16)) {
                dev_dbg(&intf->dev, "GUID doesn't match\n");
                goto bad_desc;
        }
@@ -302,7 +298,7 @@ skip:
        if (info->control->cur_altsetting->desc.bNumEndpoints == 1) {
                struct usb_endpoint_descriptor  *desc;
 
-               dev->status = &info->control->cur_altsetting->endpoint [0];
+               dev->status = &info->control->cur_altsetting->endpoint[0];
                desc = &dev->status->desc;
                if (!usb_endpoint_is_int_in(desc) ||
                    (le16_to_cpu(desc->wMaxPacketSize)
@@ -847,6 +843,14 @@ static const struct usb_device_id  products[] = {
        .driver_info = 0,
 },
 
+/* USB-C 3.1 to 5GBASE-T Ethernet Adapter (based on AQC111U) */
+{
+       USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0xe05a, USB_CLASS_COMM,
+                                     USB_CDC_SUBCLASS_ETHERNET,
+                                     USB_CDC_PROTO_NONE),
+       .driver_info = 0,
+},
+
 /* WHITELIST!!!
  *
  * CDC Ether uses two interfaces, not necessarily consecutive.
index 774e1ff..735ad83 100644 (file)
@@ -123,6 +123,7 @@ static void qmimux_setup(struct net_device *dev)
        dev->addr_len        = 0;
        dev->flags           = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
        dev->netdev_ops      = &qmimux_netdev_ops;
+       dev->mtu             = 1500;
        dev->needs_free_netdev = true;
 }
 
index 0237250..4cfceb7 100644 (file)
@@ -57,6 +57,8 @@ module_param(napi_tx, bool, 0644);
 #define VIRTIO_XDP_TX          BIT(0)
 #define VIRTIO_XDP_REDIR       BIT(1)
 
+#define VIRTIO_XDP_FLAG        BIT(0)
+
 /* RX packet size EWMA. The average packet size is used to determine the packet
  * buffer size when refilling RX rings. As the entire RX ring may be refilled
  * at once, the weight is chosen so that the EWMA will be insensitive to short-
@@ -252,6 +254,21 @@ struct padded_vnet_hdr {
        char padding[4];
 };
 
+static bool is_xdp_frame(void *ptr)
+{
+       return (unsigned long)ptr & VIRTIO_XDP_FLAG;
+}
+
+static void *xdp_to_ptr(struct xdp_frame *ptr)
+{
+       return (void *)((unsigned long)ptr | VIRTIO_XDP_FLAG);
+}
+
+static struct xdp_frame *ptr_to_xdp(void *ptr)
+{
+       return (struct xdp_frame *)((unsigned long)ptr & ~VIRTIO_XDP_FLAG);
+}
+
 /* Converting between virtqueue no. and kernel tx/rx queue no.
  * 0:rx0 1:tx0 2:rx1 3:tx1 ... 2N:rxN 2N+1:txN 2N+2:cvq
  */
@@ -462,7 +479,8 @@ static int __virtnet_xdp_xmit_one(struct virtnet_info *vi,
 
        sg_init_one(sq->sg, xdpf->data, xdpf->len);
 
-       err = virtqueue_add_outbuf(sq->vq, sq->sg, 1, xdpf, GFP_ATOMIC);
+       err = virtqueue_add_outbuf(sq->vq, sq->sg, 1, xdp_to_ptr(xdpf),
+                                  GFP_ATOMIC);
        if (unlikely(err))
                return -ENOSPC; /* Caller handle free/refcnt */
 
@@ -482,36 +500,47 @@ static int virtnet_xdp_xmit(struct net_device *dev,
 {
        struct virtnet_info *vi = netdev_priv(dev);
        struct receive_queue *rq = vi->rq;
-       struct xdp_frame *xdpf_sent;
        struct bpf_prog *xdp_prog;
        struct send_queue *sq;
        unsigned int len;
+       int packets = 0;
+       int bytes = 0;
        int drops = 0;
        int kicks = 0;
        int ret, err;
+       void *ptr;
        int i;
 
-       sq = virtnet_xdp_sq(vi);
-
-       if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) {
-               ret = -EINVAL;
-               drops = n;
-               goto out;
-       }
-
        /* Only allow ndo_xdp_xmit if XDP is loaded on dev, as this
         * indicate XDP resources have been successfully allocated.
         */
        xdp_prog = rcu_dereference(rq->xdp_prog);
-       if (!xdp_prog) {
-               ret = -ENXIO;
+       if (!xdp_prog)
+               return -ENXIO;
+
+       sq = virtnet_xdp_sq(vi);
+
+       if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) {
+               ret = -EINVAL;
                drops = n;
                goto out;
        }
 
        /* Free up any pending old buffers before queueing new ones. */
-       while ((xdpf_sent = virtqueue_get_buf(sq->vq, &len)) != NULL)
-               xdp_return_frame(xdpf_sent);
+       while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) {
+               if (likely(is_xdp_frame(ptr))) {
+                       struct xdp_frame *frame = ptr_to_xdp(ptr);
+
+                       bytes += frame->len;
+                       xdp_return_frame(frame);
+               } else {
+                       struct sk_buff *skb = ptr;
+
+                       bytes += skb->len;
+                       napi_consume_skb(skb, false);
+               }
+               packets++;
+       }
 
        for (i = 0; i < n; i++) {
                struct xdp_frame *xdpf = frames[i];
@@ -530,6 +559,8 @@ static int virtnet_xdp_xmit(struct net_device *dev,
        }
 out:
        u64_stats_update_begin(&sq->stats.syncp);
+       sq->stats.bytes += bytes;
+       sq->stats.packets += packets;
        sq->stats.xdp_tx += n;
        sq->stats.xdp_tx_drops += drops;
        sq->stats.kicks += kicks;
@@ -1330,20 +1361,28 @@ static int virtnet_receive(struct receive_queue *rq, int budget,
        return stats.packets;
 }
 
-static void free_old_xmit_skbs(struct send_queue *sq)
+static void free_old_xmit_skbs(struct send_queue *sq, bool in_napi)
 {
-       struct sk_buff *skb;
        unsigned int len;
        unsigned int packets = 0;
        unsigned int bytes = 0;
+       void *ptr;
 
-       while ((skb = virtqueue_get_buf(sq->vq, &len)) != NULL) {
-               pr_debug("Sent skb %p\n", skb);
+       while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) {
+               if (likely(!is_xdp_frame(ptr))) {
+                       struct sk_buff *skb = ptr;
 
-               bytes += skb->len;
-               packets++;
+                       pr_debug("Sent skb %p\n", skb);
+
+                       bytes += skb->len;
+                       napi_consume_skb(skb, in_napi);
+               } else {
+                       struct xdp_frame *frame = ptr_to_xdp(ptr);
 
-               dev_consume_skb_any(skb);
+                       bytes += frame->len;
+                       xdp_return_frame(frame);
+               }
+               packets++;
        }
 
        /* Avoid overhead when no packets have been processed
@@ -1358,6 +1397,16 @@ static void free_old_xmit_skbs(struct send_queue *sq)
        u64_stats_update_end(&sq->stats.syncp);
 }
 
+static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q)
+{
+       if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs))
+               return false;
+       else if (q < vi->curr_queue_pairs)
+               return true;
+       else
+               return false;
+}
+
 static void virtnet_poll_cleantx(struct receive_queue *rq)
 {
        struct virtnet_info *vi = rq->vq->vdev->priv;
@@ -1365,11 +1414,11 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
        struct send_queue *sq = &vi->sq[index];
        struct netdev_queue *txq = netdev_get_tx_queue(vi->dev, index);
 
-       if (!sq->napi.weight)
+       if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index))
                return;
 
        if (__netif_tx_trylock(txq)) {
-               free_old_xmit_skbs(sq);
+               free_old_xmit_skbs(sq, true);
                __netif_tx_unlock(txq);
        }
 
@@ -1442,10 +1491,18 @@ static int virtnet_poll_tx(struct napi_struct *napi, int budget)
 {
        struct send_queue *sq = container_of(napi, struct send_queue, napi);
        struct virtnet_info *vi = sq->vq->vdev->priv;
-       struct netdev_queue *txq = netdev_get_tx_queue(vi->dev, vq2txq(sq->vq));
+       unsigned int index = vq2txq(sq->vq);
+       struct netdev_queue *txq;
 
+       if (unlikely(is_xdp_raw_buffer_queue(vi, index))) {
+               /* We don't need to enable cb for XDP */
+               napi_complete_done(napi, 0);
+               return 0;
+       }
+
+       txq = netdev_get_tx_queue(vi->dev, index);
        __netif_tx_lock(txq, raw_smp_processor_id());
-       free_old_xmit_skbs(sq);
+       free_old_xmit_skbs(sq, true);
        __netif_tx_unlock(txq);
 
        virtqueue_napi_complete(napi, sq->vq, 0);
@@ -1514,7 +1571,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
        bool use_napi = sq->napi.weight;
 
        /* Free up any pending old buffers before queueing new ones. */
-       free_old_xmit_skbs(sq);
+       free_old_xmit_skbs(sq, false);
 
        if (use_napi && kick)
                virtqueue_enable_cb_delayed(sq->vq);
@@ -1557,7 +1614,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
                if (!use_napi &&
                    unlikely(!virtqueue_enable_cb_delayed(sq->vq))) {
                        /* More just got used, free them then recheck. */
-                       free_old_xmit_skbs(sq);
+                       free_old_xmit_skbs(sq, false);
                        if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) {
                                netif_start_subqueue(dev, qnum);
                                virtqueue_disable_cb(sq->vq);
@@ -2395,6 +2452,10 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
                return -ENOMEM;
        }
 
+       old_prog = rtnl_dereference(vi->rq[0].xdp_prog);
+       if (!prog && !old_prog)
+               return 0;
+
        if (prog) {
                prog = bpf_prog_add(prog, vi->max_queue_pairs - 1);
                if (IS_ERR(prog))
@@ -2402,36 +2463,62 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
        }
 
        /* Make sure NAPI is not using any XDP TX queues for RX. */
-       if (netif_running(dev))
-               for (i = 0; i < vi->max_queue_pairs; i++)
+       if (netif_running(dev)) {
+               for (i = 0; i < vi->max_queue_pairs; i++) {
                        napi_disable(&vi->rq[i].napi);
+                       virtnet_napi_tx_disable(&vi->sq[i].napi);
+               }
+       }
+
+       if (!prog) {
+               for (i = 0; i < vi->max_queue_pairs; i++) {
+                       rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
+                       if (i == 0)
+                               virtnet_restore_guest_offloads(vi);
+               }
+               synchronize_net();
+       }
 
-       netif_set_real_num_rx_queues(dev, curr_qp + xdp_qp);
        err = _virtnet_set_queues(vi, curr_qp + xdp_qp);
        if (err)
                goto err;
+       netif_set_real_num_rx_queues(dev, curr_qp + xdp_qp);
        vi->xdp_queue_pairs = xdp_qp;
 
-       for (i = 0; i < vi->max_queue_pairs; i++) {
-               old_prog = rtnl_dereference(vi->rq[i].xdp_prog);
-               rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
-               if (i == 0) {
-                       if (!old_prog)
+       if (prog) {
+               for (i = 0; i < vi->max_queue_pairs; i++) {
+                       rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
+                       if (i == 0 && !old_prog)
                                virtnet_clear_guest_offloads(vi);
-                       if (!prog)
-                               virtnet_restore_guest_offloads(vi);
                }
+       }
+
+       for (i = 0; i < vi->max_queue_pairs; i++) {
                if (old_prog)
                        bpf_prog_put(old_prog);
-               if (netif_running(dev))
+               if (netif_running(dev)) {
                        virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
+                       virtnet_napi_tx_enable(vi, vi->sq[i].vq,
+                                              &vi->sq[i].napi);
+               }
        }
 
        return 0;
 
 err:
-       for (i = 0; i < vi->max_queue_pairs; i++)
-               virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
+       if (!prog) {
+               virtnet_clear_guest_offloads(vi);
+               for (i = 0; i < vi->max_queue_pairs; i++)
+                       rcu_assign_pointer(vi->rq[i].xdp_prog, old_prog);
+       }
+
+       if (netif_running(dev)) {
+               for (i = 0; i < vi->max_queue_pairs; i++) {
+                       virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
+                       virtnet_napi_tx_enable(vi, vi->sq[i].vq,
+                                              &vi->sq[i].napi);
+               }
+       }
        if (prog)
                bpf_prog_sub(prog, vi->max_queue_pairs - 1);
        return err;
@@ -2613,16 +2700,6 @@ static void free_receive_page_frags(struct virtnet_info *vi)
                        put_page(vi->rq[i].alloc_frag.page);
 }
 
-static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q)
-{
-       if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs))
-               return false;
-       else if (q < vi->curr_queue_pairs)
-               return true;
-       else
-               return false;
-}
-
 static void free_unused_bufs(struct virtnet_info *vi)
 {
        void *buf;
@@ -2631,10 +2708,10 @@ static void free_unused_bufs(struct virtnet_info *vi)
        for (i = 0; i < vi->max_queue_pairs; i++) {
                struct virtqueue *vq = vi->sq[i].vq;
                while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
-                       if (!is_xdp_raw_buffer_queue(vi, i))
+                       if (!is_xdp_frame(buf))
                                dev_kfree_skb(buf);
                        else
-                               put_page(virt_to_head_page(buf));
+                               xdp_return_frame(ptr_to_xdp(buf));
                }
        }
 
index e454dfc..89984fc 100644 (file)
@@ -535,8 +535,8 @@ vmxnet3_tq_create(struct vmxnet3_tx_queue *tq,
        }
 
        sz = tq->tx_ring.size * sizeof(tq->buf_info[0]);
-       tq->buf_info = dma_zalloc_coherent(&adapter->pdev->dev, sz,
-                                          &tq->buf_info_pa, GFP_KERNEL);
+       tq->buf_info = dma_alloc_coherent(&adapter->pdev->dev, sz,
+                                         &tq->buf_info_pa, GFP_KERNEL);
        if (!tq->buf_info)
                goto err;
 
@@ -1815,8 +1815,8 @@ vmxnet3_rq_create(struct vmxnet3_rx_queue *rq, struct vmxnet3_adapter *adapter)
 
        sz = sizeof(struct vmxnet3_rx_buf_info) * (rq->rx_ring[0].size +
                                                   rq->rx_ring[1].size);
-       bi = dma_zalloc_coherent(&adapter->pdev->dev, sz, &rq->buf_info_pa,
-                                GFP_KERNEL);
+       bi = dma_alloc_coherent(&adapter->pdev->dev, sz, &rq->buf_info_pa,
+                               GFP_KERNEL);
        if (!bi)
                goto err;
 
index 5209ee9..2aae11f 100644 (file)
@@ -2219,7 +2219,7 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
        struct pcpu_sw_netstats *tx_stats, *rx_stats;
        union vxlan_addr loopback;
        union vxlan_addr *remote_ip = &dst_vxlan->default_dst.remote_ip;
-       struct net_device *dev = skb->dev;
+       struct net_device *dev;
        int len = skb->len;
 
        tx_stats = this_cpu_ptr(src_vxlan->dev->tstats);
@@ -2239,9 +2239,15 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
 #endif
        }
 
+       rcu_read_lock();
+       dev = skb->dev;
+       if (unlikely(!(dev->flags & IFF_UP))) {
+               kfree_skb(skb);
+               goto drop;
+       }
+
        if (dst_vxlan->cfg.flags & VXLAN_F_LEARN)
-               vxlan_snoop(skb->dev, &loopback, eth_hdr(skb)->h_source, 0,
-                           vni);
+               vxlan_snoop(dev, &loopback, eth_hdr(skb)->h_source, 0, vni);
 
        u64_stats_update_begin(&tx_stats->syncp);
        tx_stats->tx_packets++;
@@ -2254,8 +2260,10 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
                rx_stats->rx_bytes += len;
                u64_stats_update_end(&rx_stats->syncp);
        } else {
+drop:
                dev->stats.rx_dropped++;
        }
+       rcu_read_unlock();
 }
 
 static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev,
index c0b0f52..27decf8 100644 (file)
@@ -1575,7 +1575,7 @@ try:
                                        dev->stats.tx_packets++;
                                        dev->stats.tx_bytes += skb->len;
                                }
-                               dev_kfree_skb_irq(skb);
+                               dev_consume_skb_irq(skb);
                                dpriv->tx_skbuff[cur] = NULL;
                                ++dpriv->tx_dirty;
                        } else {
index 839fa77..a08f04c 100644 (file)
@@ -279,10 +279,9 @@ static int uhdlc_init(struct ucc_hdlc_private *priv)
        iowrite16be(DEFAULT_HDLC_ADDR, &priv->ucc_pram->haddr4);
 
        /* Get BD buffer */
-       bd_buffer = dma_zalloc_coherent(priv->dev,
-                                       (RX_BD_RING_LEN + TX_BD_RING_LEN) *
-                                       MAX_RX_BUF_LENGTH,
-                                       &bd_dma_addr, GFP_KERNEL);
+       bd_buffer = dma_alloc_coherent(priv->dev,
+                                      (RX_BD_RING_LEN + TX_BD_RING_LEN) * MAX_RX_BUF_LENGTH,
+                                      &bd_dma_addr, GFP_KERNEL);
 
        if (!bd_buffer) {
                dev_err(priv->dev, "Could not allocate buffer descriptors\n");
@@ -483,7 +482,7 @@ static int hdlc_tx_done(struct ucc_hdlc_private *priv)
                memset(priv->tx_buffer +
                       (be32_to_cpu(bd->buf) - priv->dma_tx_addr),
                       0, skb->len);
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
 
                priv->tx_skbuff[priv->skb_dirtytx] = NULL;
                priv->skb_dirtytx =
@@ -1057,6 +1056,54 @@ static const struct net_device_ops uhdlc_ops = {
        .ndo_tx_timeout = uhdlc_tx_timeout,
 };
 
+static int hdlc_map_iomem(char *name, int init_flag, void __iomem **ptr)
+{
+       struct device_node *np;
+       struct platform_device *pdev;
+       struct resource *res;
+       static int siram_init_flag;
+       int ret = 0;
+
+       np = of_find_compatible_node(NULL, NULL, name);
+       if (!np)
+               return -EINVAL;
+
+       pdev = of_find_device_by_node(np);
+       if (!pdev) {
+               pr_err("%pOFn: failed to lookup pdev\n", np);
+               of_node_put(np);
+               return -EINVAL;
+       }
+
+       of_node_put(np);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -EINVAL;
+               goto error_put_device;
+       }
+       *ptr = ioremap(res->start, resource_size(res));
+       if (!*ptr) {
+               ret = -ENOMEM;
+               goto error_put_device;
+       }
+
+       /* We've remapped the addresses, and we don't need the device any
+        * more, so we should release it.
+        */
+       put_device(&pdev->dev);
+
+       if (init_flag && siram_init_flag == 0) {
+               memset_io(*ptr, 0, resource_size(res));
+               siram_init_flag = 1;
+       }
+       return  0;
+
+error_put_device:
+       put_device(&pdev->dev);
+
+       return ret;
+}
+
 static int ucc_hdlc_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -1151,6 +1198,15 @@ static int ucc_hdlc_probe(struct platform_device *pdev)
                ret = ucc_of_parse_tdm(np, utdm, ut_info);
                if (ret)
                        goto free_utdm;
+
+               ret = hdlc_map_iomem("fsl,t1040-qe-si", 0,
+                                    (void __iomem **)&utdm->si_regs);
+               if (ret)
+                       goto free_utdm;
+               ret = hdlc_map_iomem("fsl,t1040-qe-siram", 1,
+                                    (void __iomem **)&utdm->siram);
+               if (ret)
+                       goto unmap_si_regs;
        }
 
        if (of_property_read_u16(np, "fsl,hmask", &uhdlc_priv->hmask))
@@ -1159,7 +1215,7 @@ static int ucc_hdlc_probe(struct platform_device *pdev)
        ret = uhdlc_init(uhdlc_priv);
        if (ret) {
                dev_err(&pdev->dev, "Failed to init uhdlc\n");
-               goto free_utdm;
+               goto undo_uhdlc_init;
        }
 
        dev = alloc_hdlcdev(uhdlc_priv);
@@ -1188,6 +1244,9 @@ static int ucc_hdlc_probe(struct platform_device *pdev)
 free_dev:
        free_netdev(dev);
 undo_uhdlc_init:
+       iounmap(utdm->siram);
+unmap_si_regs:
+       iounmap(utdm->si_regs);
 free_utdm:
        if (uhdlc_priv->tsa)
                kfree(utdm);
index f6d3ecb..2a5668b 100644 (file)
@@ -1553,10 +1553,9 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id,
         * coherent DMA are unsupported
         */
        dest_ring->base_addr_owner_space_unaligned =
-               dma_zalloc_coherent(ar->dev,
-                                   (nentries * sizeof(struct ce_desc) +
-                                    CE_DESC_RING_ALIGN),
-                                   &base_addr, GFP_KERNEL);
+               dma_alloc_coherent(ar->dev,
+                                  (nentries * sizeof(struct ce_desc) + CE_DESC_RING_ALIGN),
+                                  &base_addr, GFP_KERNEL);
        if (!dest_ring->base_addr_owner_space_unaligned) {
                kfree(dest_ring);
                return ERR_PTR(-ENOMEM);
index 399b501..e8891f5 100644 (file)
@@ -548,7 +548,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
        {
                .id = WCN3990_HW_1_0_DEV_VERSION,
                .dev_id = 0,
-               .bus = ATH10K_BUS_PCI,
+               .bus = ATH10K_BUS_SNOC,
                .name = "wcn3990 hw1.0",
                .continuous_frag_desc = true,
                .tx_chain_mask = 0x7,
index e49b367..4975849 100644 (file)
@@ -5169,10 +5169,10 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
        if (vif->type == NL80211_IFTYPE_ADHOC ||
            vif->type == NL80211_IFTYPE_MESH_POINT ||
            vif->type == NL80211_IFTYPE_AP) {
-               arvif->beacon_buf = dma_zalloc_coherent(ar->dev,
-                                                       IEEE80211_MAX_FRAME_LEN,
-                                                       &arvif->beacon_paddr,
-                                                       GFP_ATOMIC);
+               arvif->beacon_buf = dma_alloc_coherent(ar->dev,
+                                                      IEEE80211_MAX_FRAME_LEN,
+                                                      &arvif->beacon_paddr,
+                                                      GFP_ATOMIC);
                if (!arvif->beacon_buf) {
                        ret = -ENOMEM;
                        ath10k_warn(ar, "failed to allocate beacon buffer: %d\n",
index 01b4edb..39e0b1c 100644 (file)
@@ -936,8 +936,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
         */
        alloc_nbytes = min_t(unsigned int, nbytes, DIAG_TRANSFER_LIMIT);
 
-       data_buf = (unsigned char *)dma_zalloc_coherent(ar->dev,
-                                                      alloc_nbytes,
+       data_buf = (unsigned char *)dma_alloc_coherent(ar->dev, alloc_nbytes,
                                                       &ce_data_base,
                                                       GFP_ATOMIC);
 
index ba83740..8e236d1 100644 (file)
@@ -5193,7 +5193,7 @@ static int ath10k_wmi_alloc_chunk(struct ath10k *ar, u32 req_id,
        void *vaddr;
 
        pool_size = num_units * round_up(unit_len, 4);
-       vaddr = dma_zalloc_coherent(ar->dev, pool_size, &paddr, GFP_KERNEL);
+       vaddr = dma_alloc_coherent(ar->dev, pool_size, &paddr, GFP_KERNEL);
 
        if (!vaddr)
                return -ENOMEM;
index 5ab3e31..bab30f7 100644 (file)
@@ -174,9 +174,8 @@ static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn
        int i;
 
        size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc);
-       wcn_ch->cpu_addr = dma_zalloc_coherent(dev, size,
-                                              &wcn_ch->dma_addr,
-                                              GFP_KERNEL);
+       wcn_ch->cpu_addr = dma_alloc_coherent(dev, size, &wcn_ch->dma_addr,
+                                             GFP_KERNEL);
        if (!wcn_ch->cpu_addr)
                return -ENOMEM;
 
@@ -627,9 +626,9 @@ int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn)
                16 - (WCN36XX_BD_CHUNK_SIZE % 8);
 
        s = wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H;
-       cpu_addr = dma_zalloc_coherent(wcn->dev, s,
-                                      &wcn->mgmt_mem_pool.phy_addr,
-                                      GFP_KERNEL);
+       cpu_addr = dma_alloc_coherent(wcn->dev, s,
+                                     &wcn->mgmt_mem_pool.phy_addr,
+                                     GFP_KERNEL);
        if (!cpu_addr)
                goto out_err;
 
@@ -642,9 +641,9 @@ int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn)
                16 - (WCN36XX_BD_CHUNK_SIZE % 8);
 
        s = wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L;
-       cpu_addr = dma_zalloc_coherent(wcn->dev, s,
-                                      &wcn->data_mem_pool.phy_addr,
-                                      GFP_KERNEL);
+       cpu_addr = dma_alloc_coherent(wcn->dev, s,
+                                     &wcn->data_mem_pool.phy_addr,
+                                     GFP_KERNEL);
        if (!cpu_addr)
                goto out_err;
 
index 05a8348..3380aae 100644 (file)
@@ -99,7 +99,7 @@ static int wil_sring_alloc(struct wil6210_priv *wil,
        /* Status messages are allocated and initialized to 0. This is necessary
         * since DR bit should be initialized to 0.
         */
-       sring->va = dma_zalloc_coherent(dev, sz, &sring->pa, GFP_KERNEL);
+       sring->va = dma_alloc_coherent(dev, sz, &sring->pa, GFP_KERNEL);
        if (!sring->va)
                return -ENOMEM;
 
@@ -381,15 +381,15 @@ static int wil_ring_alloc_desc_ring(struct wil6210_priv *wil,
        if (!ring->ctx)
                goto err;
 
-       ring->va = dma_zalloc_coherent(dev, sz, &ring->pa, GFP_KERNEL);
+       ring->va = dma_alloc_coherent(dev, sz, &ring->pa, GFP_KERNEL);
        if (!ring->va)
                goto err_free_ctx;
 
        if (ring->is_rx) {
                sz = sizeof(*ring->edma_rx_swtail.va);
                ring->edma_rx_swtail.va =
-                       dma_zalloc_coherent(dev, sz, &ring->edma_rx_swtail.pa,
-                                           GFP_KERNEL);
+                       dma_alloc_coherent(dev, sz, &ring->edma_rx_swtail.pa,
+                                          GFP_KERNEL);
                if (!ring->edma_rx_swtail.va)
                        goto err_free_va;
        }
index dfc4c34..b34e519 100644 (file)
@@ -431,9 +431,9 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
        u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ?
                                B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE;
 
-       ring->descbase = dma_zalloc_coherent(ring->dev->dev->dma_dev,
-                                            ring_mem_size, &(ring->dmabase),
-                                            GFP_KERNEL);
+       ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
+                                           ring_mem_size, &(ring->dmabase),
+                                           GFP_KERNEL);
        if (!ring->descbase)
                return -ENOMEM;
 
index 1b1da7d..2ce1537 100644 (file)
@@ -331,9 +331,9 @@ void free_descriptor_buffer(struct b43legacy_dmaring *ring,
 static int alloc_ringmemory(struct b43legacy_dmaring *ring)
 {
        /* GFP flags must match the flags in free_ringmemory()! */
-       ring->descbase = dma_zalloc_coherent(ring->dev->dev->dma_dev,
-                                            B43legacy_DMA_RINGMEMSIZE,
-                                            &(ring->dmabase), GFP_KERNEL);
+       ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
+                                           B43legacy_DMA_RINGMEMSIZE,
+                                           &(ring->dmabase), GFP_KERNEL);
        if (!ring->descbase)
                return -ENOMEM;
 
index 16d7dda..0f69b3f 100644 (file)
@@ -1281,10 +1281,10 @@ static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
        u32 addr;
 
        devinfo->shared.scratch =
-               dma_zalloc_coherent(&devinfo->pdev->dev,
-                                       BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
-                                       &devinfo->shared.scratch_dmahandle,
-                                       GFP_KERNEL);
+               dma_alloc_coherent(&devinfo->pdev->dev,
+                                  BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
+                                  &devinfo->shared.scratch_dmahandle,
+                                  GFP_KERNEL);
        if (!devinfo->shared.scratch)
                goto fail;
 
@@ -1298,10 +1298,10 @@ static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
        brcmf_pcie_write_tcm32(devinfo, addr, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
 
        devinfo->shared.ringupd =
-               dma_zalloc_coherent(&devinfo->pdev->dev,
-                                       BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
-                                       &devinfo->shared.ringupd_dmahandle,
-                                       GFP_KERNEL);
+               dma_alloc_coherent(&devinfo->pdev->dev,
+                                  BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
+                                  &devinfo->shared.ringupd_dmahandle,
+                                  GFP_KERNEL);
        if (!devinfo->shared.ringupd)
                goto fail;
 
index 491ca3c..83d5bce 100644 (file)
@@ -1,6 +1,6 @@
 config IWLWIFI
        tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) "
-       depends on PCI && HAS_IOMEM
+       depends on PCI && HAS_IOMEM && CFG80211
        select FW_LOADER
        ---help---
          Select to build the driver supporting the:
@@ -47,6 +47,7 @@ if IWLWIFI
 config IWLWIFI_LEDS
        bool
        depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI
+       depends on IWLMVM || IWLDVM
        select LEDS_TRIGGERS
        select MAC80211_LEDS
        default y
index e965cc5..9e850c2 100644 (file)
@@ -711,30 +711,24 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
         * Allocate the circular buffer of Read Buffer Descriptors
         * (RBDs)
         */
-       rxq->bd = dma_zalloc_coherent(dev,
-                                     free_size * rxq->queue_size,
-                                     &rxq->bd_dma, GFP_KERNEL);
+       rxq->bd = dma_alloc_coherent(dev, free_size * rxq->queue_size,
+                                    &rxq->bd_dma, GFP_KERNEL);
        if (!rxq->bd)
                goto err;
 
        if (trans->cfg->mq_rx_supported) {
-               rxq->used_bd = dma_zalloc_coherent(dev,
-                                                  (use_rx_td ?
-                                                  sizeof(*rxq->cd) :
-                                                  sizeof(__le32)) *
-                                                  rxq->queue_size,
-                                                  &rxq->used_bd_dma,
-                                                  GFP_KERNEL);
+               rxq->used_bd = dma_alloc_coherent(dev,
+                                                 (use_rx_td ? sizeof(*rxq->cd) : sizeof(__le32)) * rxq->queue_size,
+                                                 &rxq->used_bd_dma,
+                                                 GFP_KERNEL);
                if (!rxq->used_bd)
                        goto err;
        }
 
        /* Allocate the driver's pointer to receive buffer status */
-       rxq->rb_stts = dma_zalloc_coherent(dev, use_rx_td ?
-                                          sizeof(__le16) :
-                                          sizeof(struct iwl_rb_status),
-                                          &rxq->rb_stts_dma,
-                                          GFP_KERNEL);
+       rxq->rb_stts = dma_alloc_coherent(dev,
+                                         use_rx_td ? sizeof(__le16) : sizeof(struct iwl_rb_status),
+                                         &rxq->rb_stts_dma, GFP_KERNEL);
        if (!rxq->rb_stts)
                goto err;
 
@@ -742,16 +736,14 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
                return 0;
 
        /* Allocate the driver's pointer to TR tail */
-       rxq->tr_tail = dma_zalloc_coherent(dev, sizeof(__le16),
-                                          &rxq->tr_tail_dma,
-                                          GFP_KERNEL);
+       rxq->tr_tail = dma_alloc_coherent(dev, sizeof(__le16),
+                                         &rxq->tr_tail_dma, GFP_KERNEL);
        if (!rxq->tr_tail)
                goto err;
 
        /* Allocate the driver's pointer to CR tail */
-       rxq->cr_tail = dma_zalloc_coherent(dev, sizeof(__le16),
-                                          &rxq->cr_tail_dma,
-                                          GFP_KERNEL);
+       rxq->cr_tail = dma_alloc_coherent(dev, sizeof(__le16),
+                                         &rxq->cr_tail_dma, GFP_KERNEL);
        if (!rxq->cr_tail)
                goto err;
        /*
@@ -1947,9 +1939,8 @@ int iwl_pcie_alloc_ict(struct iwl_trans *trans)
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
        trans_pcie->ict_tbl =
-               dma_zalloc_coherent(trans->dev, ICT_SIZE,
-                                  &trans_pcie->ict_tbl_dma,
-                                  GFP_KERNEL);
+               dma_alloc_coherent(trans->dev, ICT_SIZE,
+                                  &trans_pcie->ict_tbl_dma, GFP_KERNEL);
        if (!trans_pcie->ict_tbl)
                return -ENOMEM;
 
index 3a4b878..320edca 100644 (file)
@@ -2761,6 +2761,11 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
                                        BIT(NL80211_CHAN_WIDTH_160);
        }
 
+       if (!n_limits) {
+               err = -EINVAL;
+               goto failed_hw;
+       }
+
        data->if_combination.n_limits = n_limits;
        data->if_combination.max_interfaces = 2048;
        data->if_combination.limits = data->if_limits;
index 497e762..b2cabce 100644 (file)
@@ -212,24 +212,24 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev)
        mt76x02_add_rate_power_offset(t, delta);
 }
 
-void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
+void mt76x0_get_power_info(struct mt76x02_dev *dev, s8 *tp)
 {
        struct mt76x0_chan_map {
                u8 chan;
                u8 offset;
        } chan_map[] = {
-               {   2,  0 }, {   4,  1 }, {   6,  2 }, {   8,  3 },
-               {  10,  4 }, {  12,  5 }, {  14,  6 }, {  38,  0 },
-               {  44,  1 }, {  48,  2 }, {  54,  3 }, {  60,  4 },
-               {  64,  5 }, { 102,  6 }, { 108,  7 }, { 112,  8 },
-               { 118,  9 }, { 124, 10 }, { 128, 11 }, { 134, 12 },
-               { 140, 13 }, { 151, 14 }, { 157, 15 }, { 161, 16 },
-               { 167, 17 }, { 171, 18 }, { 173, 19 },
+               {   2,  0 }, {   4,  2 }, {   6,  4 }, {   8,  6 },
+               {  10,  8 }, {  12, 10 }, {  14, 12 }, {  38,  0 },
+               {  44,  2 }, {  48,  4 }, {  54,  6 }, {  60,  8 },
+               {  64, 10 }, { 102, 12 }, { 108, 14 }, { 112, 16 },
+               { 118, 18 }, { 124, 20 }, { 128, 22 }, { 134, 24 },
+               { 140, 26 }, { 151, 28 }, { 157, 30 }, { 161, 32 },
+               { 167, 34 }, { 171, 36 }, { 175, 38 },
        };
        struct ieee80211_channel *chan = dev->mt76.chandef.chan;
        u8 offset, addr;
+       int i, idx = 0;
        u16 data;
-       int i;
 
        if (mt76x0_tssi_enabled(dev)) {
                s8 target_power;
@@ -239,14 +239,14 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
                else
                        data = mt76x02_eeprom_get(dev, MT_EE_2G_TARGET_POWER);
                target_power = (data & 0xff) - dev->mt76.rate_power.ofdm[7];
-               info[0] = target_power + mt76x0_get_delta(dev);
-               info[1] = 0;
+               *tp = target_power + mt76x0_get_delta(dev);
 
                return;
        }
 
        for (i = 0; i < ARRAY_SIZE(chan_map); i++) {
-               if (chan_map[i].chan <= chan->hw_value) {
+               if (chan->hw_value <= chan_map[i].chan) {
+                       idx = (chan->hw_value == chan_map[i].chan);
                        offset = chan_map[i].offset;
                        break;
                }
@@ -258,13 +258,16 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
                addr = MT_EE_TX_POWER_DELTA_BW80 + offset;
        } else {
                switch (chan->hw_value) {
+               case 42:
+                       offset = 2;
+                       break;
                case 58:
                        offset = 8;
                        break;
                case 106:
                        offset = 14;
                        break;
-               case 112:
+               case 122:
                        offset = 20;
                        break;
                case 155:
@@ -277,14 +280,9 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
        }
 
        data = mt76x02_eeprom_get(dev, addr);
-
-       info[0] = data;
-       if (!info[0] || info[0] > 0x3f)
-               info[0] = 5;
-
-       info[1] = data >> 8;
-       if (!info[1] || info[1] > 0x3f)
-               info[1] = 5;
+       *tp = data >> (8 * idx);
+       if (*tp < 0 || *tp > 0x3f)
+               *tp = 5;
 }
 
 static int mt76x0_check_eeprom(struct mt76x02_dev *dev)
index ee9ade9..42b259f 100644 (file)
@@ -26,7 +26,7 @@ struct mt76x02_dev;
 int mt76x0_eeprom_init(struct mt76x02_dev *dev);
 void mt76x0_read_rx_gain(struct mt76x02_dev *dev);
 void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev);
-void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info);
+void mt76x0_get_power_info(struct mt76x02_dev *dev, s8 *tp);
 
 static inline s8 s6_to_s8(u32 val)
 {
index 1eb1a80..b616670 100644 (file)
@@ -845,17 +845,17 @@ static void mt76x0_phy_tssi_calibrate(struct mt76x02_dev *dev)
 void mt76x0_phy_set_txpower(struct mt76x02_dev *dev)
 {
        struct mt76_rate_power *t = &dev->mt76.rate_power;
-       u8 info[2];
+       s8 info;
 
        mt76x0_get_tx_power_per_rate(dev);
-       mt76x0_get_power_info(dev, info);
+       mt76x0_get_power_info(dev, &info);
 
-       mt76x02_add_rate_power_offset(t, info[0]);
+       mt76x02_add_rate_power_offset(t, info);
        mt76x02_limit_rate_power(t, dev->mt76.txpower_conf);
        dev->mt76.txpower_cur = mt76x02_get_max_rate_power(t);
-       mt76x02_add_rate_power_offset(t, -info[0]);
+       mt76x02_add_rate_power_offset(t, -info);
 
-       mt76x02_phy_set_txpower(dev, info[0], info[1]);
+       mt76x02_phy_set_txpower(dev, info, info);
 }
 
 void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on)
index 528cb04..4956a54 100644 (file)
@@ -119,9 +119,9 @@ static int rt2x00mmio_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
        /*
         * Allocate DMA memory for descriptor and buffer.
         */
-       addr = dma_zalloc_coherent(rt2x00dev->dev,
-                                  queue->limit * queue->desc_size, &dma,
-                                  GFP_KERNEL);
+       addr = dma_alloc_coherent(rt2x00dev->dev,
+                                 queue->limit * queue->desc_size, &dma,
+                                 GFP_KERNEL);
        if (!addr)
                return -ENOMEM;
 
index bd10165..4d4b077 100644 (file)
@@ -164,6 +164,12 @@ static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue)
        }
 
        sdio_claim_host(func);
+       /*
+        * To guarantee that the SDIO card is power cycled, as required to make
+        * the FW programming to succeed, let's do a brute force HW reset.
+        */
+       mmc_hw_reset(card->host);
+
        sdio_enable_func(func);
        sdio_release_host(func);
 
@@ -174,20 +180,13 @@ static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue)
 {
        struct sdio_func *func = dev_to_sdio_func(glue->dev);
        struct mmc_card *card = func->card;
-       int error;
 
        sdio_claim_host(func);
        sdio_disable_func(func);
        sdio_release_host(func);
 
        /* Let runtime PM know the card is powered off */
-       error = pm_runtime_put(&card->dev);
-       if (error < 0 && error != -EBUSY) {
-               dev_err(&card->dev, "%s failed: %i\n", __func__, error);
-
-               return error;
-       }
-
+       pm_runtime_put(&card->dev);
        return 0;
 }
 
index 64b2186..3a93e4d 100644 (file)
@@ -530,8 +530,10 @@ static int virt_wifi_newlink(struct net *src_net, struct net_device *dev,
        SET_NETDEV_DEV(dev, &priv->lowerdev->dev);
        dev->ieee80211_ptr = kzalloc(sizeof(*dev->ieee80211_ptr), GFP_KERNEL);
 
-       if (!dev->ieee80211_ptr)
+       if (!dev->ieee80211_ptr) {
+               err = -ENOMEM;
                goto remove_handler;
+       }
 
        dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION;
        dev->ieee80211_ptr->wiphy = common_wiphy;
index 5ee5f40..f1eaa3c 100644 (file)
@@ -1339,10 +1339,10 @@ static int switchtec_ntb_init_shared_mw(struct switchtec_ntb *sndev)
        int rc;
 
        sndev->nr_rsvd_luts++;
-       sndev->self_shared = dma_zalloc_coherent(&sndev->stdev->pdev->dev,
-                                                LUT_SIZE,
-                                                &sndev->self_shared_dma,
-                                                GFP_KERNEL);
+       sndev->self_shared = dma_alloc_coherent(&sndev->stdev->pdev->dev,
+                                               LUT_SIZE,
+                                               &sndev->self_shared_dma,
+                                               GFP_KERNEL);
        if (!sndev->self_shared) {
                dev_err(&sndev->stdev->dev,
                        "unable to allocate memory for shared mw\n");
index 0cf58ca..3cf5027 100644 (file)
@@ -26,6 +26,12 @@ static int nvdimm_probe(struct device *dev)
        struct nvdimm_drvdata *ndd;
        int rc;
 
+       rc = nvdimm_security_setup_events(dev);
+       if (rc < 0) {
+               dev_err(dev, "security event setup failed: %d\n", rc);
+               return rc;
+       }
+
        rc = nvdimm_check_config_data(dev);
        if (rc) {
                /* not required for non-aliased nvdimm, ex. NVDIMM-N */
index 4890310..efe412a 100644 (file)
@@ -578,13 +578,25 @@ struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus,
 }
 EXPORT_SYMBOL_GPL(__nvdimm_create);
 
-int nvdimm_security_setup_events(struct nvdimm *nvdimm)
+static void shutdown_security_notify(void *data)
 {
-       nvdimm->sec.overwrite_state = sysfs_get_dirent(nvdimm->dev.kobj.sd,
-                       "security");
+       struct nvdimm *nvdimm = data;
+
+       sysfs_put(nvdimm->sec.overwrite_state);
+}
+
+int nvdimm_security_setup_events(struct device *dev)
+{
+       struct nvdimm *nvdimm = to_nvdimm(dev);
+
+       if (nvdimm->sec.state < 0 || !nvdimm->sec.ops
+                       || !nvdimm->sec.ops->overwrite)
+               return 0;
+       nvdimm->sec.overwrite_state = sysfs_get_dirent(dev->kobj.sd, "security");
        if (!nvdimm->sec.overwrite_state)
-               return -ENODEV;
-       return 0;
+               return -ENOMEM;
+
+       return devm_add_action_or_reset(dev, shutdown_security_notify, nvdimm);
 }
 EXPORT_SYMBOL_GPL(nvdimm_security_setup_events);
 
index 2b2cf4e..e5ffd57 100644 (file)
@@ -54,12 +54,12 @@ struct nvdimm {
 };
 
 static inline enum nvdimm_security_state nvdimm_security_state(
-               struct nvdimm *nvdimm, bool master)
+               struct nvdimm *nvdimm, enum nvdimm_passphrase_type ptype)
 {
        if (!nvdimm->sec.ops)
                return -ENXIO;
 
-       return nvdimm->sec.ops->state(nvdimm, master);
+       return nvdimm->sec.ops->state(nvdimm, ptype);
 }
 int nvdimm_security_freeze(struct nvdimm *nvdimm);
 #if IS_ENABLED(CONFIG_NVDIMM_KEYS)
index cfde992..379bf43 100644 (file)
@@ -250,6 +250,7 @@ long nvdimm_clear_poison(struct device *dev, phys_addr_t phys,
 void nvdimm_set_aliasing(struct device *dev);
 void nvdimm_set_locked(struct device *dev);
 void nvdimm_clear_locked(struct device *dev);
+int nvdimm_security_setup_events(struct device *dev);
 #if IS_ENABLED(CONFIG_NVDIMM_KEYS)
 int nvdimm_security_unlock(struct device *dev);
 #else
index 08f2c92..6a9dd68 100644 (file)
@@ -1253,6 +1253,7 @@ static u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
         * effects say only one namespace is affected.
         */
        if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) {
+               mutex_lock(&ctrl->scan_lock);
                nvme_start_freeze(ctrl);
                nvme_wait_freeze(ctrl);
        }
@@ -1281,8 +1282,10 @@ static void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects)
         */
        if (effects & NVME_CMD_EFFECTS_LBCC)
                nvme_update_formats(ctrl);
-       if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK))
+       if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) {
                nvme_unfreeze(ctrl);
+               mutex_unlock(&ctrl->scan_lock);
+       }
        if (effects & NVME_CMD_EFFECTS_CCC)
                nvme_init_identify(ctrl);
        if (effects & (NVME_CMD_EFFECTS_NIC | NVME_CMD_EFFECTS_NCC))
@@ -2173,18 +2176,20 @@ static void nvme_init_subnqn(struct nvme_subsystem *subsys, struct nvme_ctrl *ct
        size_t nqnlen;
        int off;
 
-       nqnlen = strnlen(id->subnqn, NVMF_NQN_SIZE);
-       if (nqnlen > 0 && nqnlen < NVMF_NQN_SIZE) {
-               strlcpy(subsys->subnqn, id->subnqn, NVMF_NQN_SIZE);
-               return;
-       }
+       if(!(ctrl->quirks & NVME_QUIRK_IGNORE_DEV_SUBNQN)) {
+               nqnlen = strnlen(id->subnqn, NVMF_NQN_SIZE);
+               if (nqnlen > 0 && nqnlen < NVMF_NQN_SIZE) {
+                       strlcpy(subsys->subnqn, id->subnqn, NVMF_NQN_SIZE);
+                       return;
+               }
 
-       if (ctrl->vs >= NVME_VS(1, 2, 1))
-               dev_warn(ctrl->device, "missing or invalid SUBNQN field.\n");
+               if (ctrl->vs >= NVME_VS(1, 2, 1))
+                       dev_warn(ctrl->device, "missing or invalid SUBNQN field.\n");
+       }
 
        /* Generate a "fake" NQN per Figure 254 in NVMe 1.3 + ECN 001 */
        off = snprintf(subsys->subnqn, NVMF_NQN_SIZE,
-                       "nqn.2014.08.org.nvmexpress:%4x%4x",
+                       "nqn.2014.08.org.nvmexpress:%04x%04x",
                        le16_to_cpu(id->vid), le16_to_cpu(id->ssvid));
        memcpy(subsys->subnqn + off, id->sn, sizeof(id->sn));
        off += sizeof(id->sn);
@@ -2500,7 +2505,6 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
        ctrl->oaes = le32_to_cpu(id->oaes);
        atomic_set(&ctrl->abort_limit, id->acl + 1);
        ctrl->vwc = id->vwc;
-       ctrl->cntlid = le16_to_cpup(&id->cntlid);
        if (id->mdts)
                max_hw_sectors = 1 << (id->mdts + page_shift - 9);
        else
@@ -3400,6 +3404,7 @@ static void nvme_scan_work(struct work_struct *work)
        if (nvme_identify_ctrl(ctrl, &id))
                return;
 
+       mutex_lock(&ctrl->scan_lock);
        nn = le32_to_cpu(id->nn);
        if (ctrl->vs >= NVME_VS(1, 1, 0) &&
            !(ctrl->quirks & NVME_QUIRK_IDENTIFY_CNS)) {
@@ -3408,6 +3413,7 @@ static void nvme_scan_work(struct work_struct *work)
        }
        nvme_scan_ns_sequential(ctrl, nn);
 out_free_id:
+       mutex_unlock(&ctrl->scan_lock);
        kfree(id);
        down_write(&ctrl->namespaces_rwsem);
        list_sort(NULL, &ctrl->namespaces, ns_cmp);
@@ -3651,6 +3657,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
 
        ctrl->state = NVME_CTRL_NEW;
        spin_lock_init(&ctrl->lock);
+       mutex_init(&ctrl->scan_lock);
        INIT_LIST_HEAD(&ctrl->namespaces);
        init_rwsem(&ctrl->namespaces_rwsem);
        ctrl->dev = dev;
index b2ab213..3eb908c 100644 (file)
@@ -874,6 +874,8 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
        if (opts->discovery_nqn) {
                opts->kato = 0;
                opts->nr_io_queues = 0;
+               opts->nr_write_queues = 0;
+               opts->nr_poll_queues = 0;
                opts->duplicate_connect = true;
        }
        if (ctrl_loss_tmo < 0)
index 183ec17..b9fff3b 100644 (file)
@@ -545,8 +545,7 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
        timer_setup(&ctrl->anatt_timer, nvme_anatt_timeout, 0);
        ctrl->ana_log_size = sizeof(struct nvme_ana_rsp_hdr) +
                ctrl->nanagrpid * sizeof(struct nvme_ana_group_desc);
-       if (!(ctrl->anacap & (1 << 6)))
-               ctrl->ana_log_size += ctrl->max_namespaces * sizeof(__le32);
+       ctrl->ana_log_size += ctrl->max_namespaces * sizeof(__le32);
 
        if (ctrl->ana_log_size > ctrl->max_hw_sectors << SECTOR_SHIFT) {
                dev_err(ctrl->device,
@@ -570,6 +569,7 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
        return 0;
 out_free_ana_log_buf:
        kfree(ctrl->ana_log_buf);
+       ctrl->ana_log_buf = NULL;
 out:
        return error;
 }
@@ -577,5 +577,6 @@ out:
 void nvme_mpath_uninit(struct nvme_ctrl *ctrl)
 {
        kfree(ctrl->ana_log_buf);
+       ctrl->ana_log_buf = NULL;
 }
 
index 2b36ac9..c4a1bb4 100644 (file)
@@ -90,6 +90,11 @@ enum nvme_quirks {
         * Set MEDIUM priority on SQ creation
         */
        NVME_QUIRK_MEDIUM_PRIO_SQ               = (1 << 7),
+
+       /*
+        * Ignore device provided subnqn.
+        */
+       NVME_QUIRK_IGNORE_DEV_SUBNQN            = (1 << 8),
 };
 
 /*
@@ -149,6 +154,7 @@ struct nvme_ctrl {
        enum nvme_ctrl_state state;
        bool identified;
        spinlock_t lock;
+       struct mutex scan_lock;
        const struct nvme_ctrl_ops *ops;
        struct request_queue *admin_q;
        struct request_queue *connect_q;
index 5a0bf6a..7fee665 100644 (file)
@@ -95,6 +95,7 @@ struct nvme_dev;
 struct nvme_queue;
 
 static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown);
+static bool __nvme_disable_io_queues(struct nvme_dev *dev, u8 opcode);
 
 /*
  * Represents an NVM Express device.  Each nvme_dev is a PCI function.
@@ -1019,9 +1020,11 @@ static void nvme_complete_cqes(struct nvme_queue *nvmeq, u16 start, u16 end)
 
 static inline void nvme_update_cq_head(struct nvme_queue *nvmeq)
 {
-       if (++nvmeq->cq_head == nvmeq->q_depth) {
+       if (nvmeq->cq_head == nvmeq->q_depth - 1) {
                nvmeq->cq_head = 0;
                nvmeq->cq_phase = !nvmeq->cq_phase;
+       } else {
+               nvmeq->cq_head++;
        }
 }
 
@@ -1420,6 +1423,14 @@ static int nvme_suspend_queue(struct nvme_queue *nvmeq)
        return 0;
 }
 
+static void nvme_suspend_io_queues(struct nvme_dev *dev)
+{
+       int i;
+
+       for (i = dev->ctrl.queue_count - 1; i > 0; i--)
+               nvme_suspend_queue(&dev->queues[i]);
+}
+
 static void nvme_disable_admin_queue(struct nvme_dev *dev, bool shutdown)
 {
        struct nvme_queue *nvmeq = &dev->queues[0];
@@ -1485,8 +1496,8 @@ static int nvme_alloc_queue(struct nvme_dev *dev, int qid, int depth)
        if (dev->ctrl.queue_count > qid)
                return 0;
 
-       nvmeq->cqes = dma_zalloc_coherent(dev->dev, CQ_SIZE(depth),
-                                         &nvmeq->cq_dma_addr, GFP_KERNEL);
+       nvmeq->cqes = dma_alloc_coherent(dev->dev, CQ_SIZE(depth),
+                                        &nvmeq->cq_dma_addr, GFP_KERNEL);
        if (!nvmeq->cqes)
                goto free_nvmeq;
 
@@ -1885,8 +1896,9 @@ static void nvme_free_host_mem(struct nvme_dev *dev)
                struct nvme_host_mem_buf_desc *desc = &dev->host_mem_descs[i];
                size_t size = le32_to_cpu(desc->size) * dev->ctrl.page_size;
 
-               dma_free_coherent(dev->dev, size, dev->host_mem_desc_bufs[i],
-                               le64_to_cpu(desc->addr));
+               dma_free_attrs(dev->dev, size, dev->host_mem_desc_bufs[i],
+                              le64_to_cpu(desc->addr),
+                              DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN);
        }
 
        kfree(dev->host_mem_desc_bufs);
@@ -1915,8 +1927,8 @@ static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred,
        if (dev->ctrl.hmmaxd && dev->ctrl.hmmaxd < max_entries)
                max_entries = dev->ctrl.hmmaxd;
 
-       descs = dma_zalloc_coherent(dev->dev, max_entries * sizeof(*descs),
-                       &descs_dma, GFP_KERNEL);
+       descs = dma_alloc_coherent(dev->dev, max_entries * sizeof(*descs),
+                                  &descs_dma, GFP_KERNEL);
        if (!descs)
                goto out;
 
@@ -1952,8 +1964,9 @@ out_free_bufs:
        while (--i >= 0) {
                size_t size = le32_to_cpu(descs[i].size) * dev->ctrl.page_size;
 
-               dma_free_coherent(dev->dev, size, bufs[i],
-                               le64_to_cpu(descs[i].addr));
+               dma_free_attrs(dev->dev, size, bufs[i],
+                              le64_to_cpu(descs[i].addr),
+                              DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN);
        }
 
        kfree(bufs);
@@ -2028,14 +2041,18 @@ static int nvme_setup_host_mem(struct nvme_dev *dev)
        return ret;
 }
 
+/* irq_queues covers admin queue */
 static void nvme_calc_io_queues(struct nvme_dev *dev, unsigned int irq_queues)
 {
        unsigned int this_w_queues = write_queues;
 
+       WARN_ON(!irq_queues);
+
        /*
-        * Setup read/write queue split
+        * Setup read/write queue split, assign admin queue one independent
+        * irq vector if irq_queues is > 1.
         */
-       if (irq_queues == 1) {
+       if (irq_queues <= 2) {
                dev->io_queues[HCTX_TYPE_DEFAULT] = 1;
                dev->io_queues[HCTX_TYPE_READ] = 0;
                return;
@@ -2043,21 +2060,21 @@ static void nvme_calc_io_queues(struct nvme_dev *dev, unsigned int irq_queues)
 
        /*
         * If 'write_queues' is set, ensure it leaves room for at least
-        * one read queue
+        * one read queue and one admin queue
         */
        if (this_w_queues >= irq_queues)
-               this_w_queues = irq_queues - 1;
+               this_w_queues = irq_queues - 2;
 
        /*
         * If 'write_queues' is set to zero, reads and writes will share
         * a queue set.
         */
        if (!this_w_queues) {
-               dev->io_queues[HCTX_TYPE_DEFAULT] = irq_queues;
+               dev->io_queues[HCTX_TYPE_DEFAULT] = irq_queues - 1;
                dev->io_queues[HCTX_TYPE_READ] = 0;
        } else {
                dev->io_queues[HCTX_TYPE_DEFAULT] = this_w_queues;
-               dev->io_queues[HCTX_TYPE_READ] = irq_queues - this_w_queues;
+               dev->io_queues[HCTX_TYPE_READ] = irq_queues - this_w_queues - 1;
        }
 }
 
@@ -2082,7 +2099,7 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
                this_p_queues = nr_io_queues - 1;
                irq_queues = 1;
        } else {
-               irq_queues = nr_io_queues - this_p_queues;
+               irq_queues = nr_io_queues - this_p_queues + 1;
        }
        dev->io_queues[HCTX_TYPE_POLL] = this_p_queues;
 
@@ -2102,8 +2119,9 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
                 * If we got a failure and we're down to asking for just
                 * 1 + 1 queues, just ask for a single vector. We'll share
                 * that between the single IO queue and the admin queue.
+                * Otherwise, we assign one independent vector to admin queue.
                 */
-               if (result >= 0 && irq_queues > 1)
+               if (irq_queues > 1)
                        irq_queues = irq_sets[0] + irq_sets[1] + 1;
 
                result = pci_alloc_irq_vectors_affinity(pdev, irq_queues,
@@ -2132,6 +2150,12 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
        return result;
 }
 
+static void nvme_disable_io_queues(struct nvme_dev *dev)
+{
+       if (__nvme_disable_io_queues(dev, nvme_admin_delete_sq))
+               __nvme_disable_io_queues(dev, nvme_admin_delete_cq);
+}
+
 static int nvme_setup_io_queues(struct nvme_dev *dev)
 {
        struct nvme_queue *adminq = &dev->queues[0];
@@ -2168,6 +2192,7 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
        } while (1);
        adminq->q_db = dev->dbs;
 
+ retry:
        /* Deregister the admin queue's interrupt */
        pci_free_irq(pdev, 0, adminq);
 
@@ -2185,25 +2210,34 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
        result = max(result - 1, 1);
        dev->max_qid = result + dev->io_queues[HCTX_TYPE_POLL];
 
-       dev_info(dev->ctrl.device, "%d/%d/%d default/read/poll queues\n",
-                                       dev->io_queues[HCTX_TYPE_DEFAULT],
-                                       dev->io_queues[HCTX_TYPE_READ],
-                                       dev->io_queues[HCTX_TYPE_POLL]);
-
        /*
         * Should investigate if there's a performance win from allocating
         * more queues than interrupt vectors; it might allow the submission
         * path to scale better, even if the receive path is limited by the
         * number of interrupts.
         */
-
        result = queue_request_irq(adminq);
        if (result) {
                adminq->cq_vector = -1;
                return result;
        }
        set_bit(NVMEQ_ENABLED, &adminq->flags);
-       return nvme_create_io_queues(dev);
+
+       result = nvme_create_io_queues(dev);
+       if (result || dev->online_queues < 2)
+               return result;
+
+       if (dev->online_queues - 1 < dev->max_qid) {
+               nr_io_queues = dev->online_queues - 1;
+               nvme_disable_io_queues(dev);
+               nvme_suspend_io_queues(dev);
+               goto retry;
+       }
+       dev_info(dev->ctrl.device, "%d/%d/%d default/read/poll queues\n",
+                                       dev->io_queues[HCTX_TYPE_DEFAULT],
+                                       dev->io_queues[HCTX_TYPE_READ],
+                                       dev->io_queues[HCTX_TYPE_POLL]);
+       return 0;
 }
 
 static void nvme_del_queue_end(struct request *req, blk_status_t error)
@@ -2248,7 +2282,7 @@ static int nvme_delete_queue(struct nvme_queue *nvmeq, u8 opcode)
        return 0;
 }
 
-static bool nvme_disable_io_queues(struct nvme_dev *dev, u8 opcode)
+static bool __nvme_disable_io_queues(struct nvme_dev *dev, u8 opcode)
 {
        int nr_queues = dev->online_queues - 1, sent = 0;
        unsigned long timeout;
@@ -2294,7 +2328,6 @@ static int nvme_dev_add(struct nvme_dev *dev)
                dev->tagset.nr_maps = 2; /* default + read */
                if (dev->io_queues[HCTX_TYPE_POLL])
                        dev->tagset.nr_maps++;
-               dev->tagset.nr_maps = HCTX_MAX_TYPES;
                dev->tagset.timeout = NVME_IO_TIMEOUT;
                dev->tagset.numa_node = dev_to_node(dev->dev);
                dev->tagset.queue_depth =
@@ -2410,7 +2443,6 @@ static void nvme_pci_disable(struct nvme_dev *dev)
 
 static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
 {
-       int i;
        bool dead = true;
        struct pci_dev *pdev = to_pci_dev(dev->dev);
 
@@ -2437,13 +2469,11 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
        nvme_stop_queues(&dev->ctrl);
 
        if (!dead && dev->ctrl.queue_count > 0) {
-               if (nvme_disable_io_queues(dev, nvme_admin_delete_sq))
-                       nvme_disable_io_queues(dev, nvme_admin_delete_cq);
+               nvme_disable_io_queues(dev);
                nvme_disable_admin_queue(dev, shutdown);
        }
-       for (i = dev->ctrl.queue_count - 1; i >= 0; i--)
-               nvme_suspend_queue(&dev->queues[i]);
-
+       nvme_suspend_io_queues(dev);
+       nvme_suspend_queue(&dev->queues[0]);
        nvme_pci_disable(dev);
 
        blk_mq_tagset_busy_iter(&dev->tagset, nvme_cancel_request, &dev->ctrl);
@@ -2527,27 +2557,18 @@ static void nvme_reset_work(struct work_struct *work)
        if (dev->ctrl.ctrl_config & NVME_CC_ENABLE)
                nvme_dev_disable(dev, false);
 
-       /*
-        * Introduce CONNECTING state from nvme-fc/rdma transports to mark the
-        * initializing procedure here.
-        */
-       if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_CONNECTING)) {
-               dev_warn(dev->ctrl.device,
-                       "failed to mark controller CONNECTING\n");
-               goto out;
-       }
-
+       mutex_lock(&dev->shutdown_lock);
        result = nvme_pci_enable(dev);
        if (result)
-               goto out;
+               goto out_unlock;
 
        result = nvme_pci_configure_admin_queue(dev);
        if (result)
-               goto out;
+               goto out_unlock;
 
        result = nvme_alloc_admin_tags(dev);
        if (result)
-               goto out;
+               goto out_unlock;
 
        /*
         * Limit the max command size to prevent iod->sg allocations going
@@ -2555,6 +2576,17 @@ static void nvme_reset_work(struct work_struct *work)
         */
        dev->ctrl.max_hw_sectors = NVME_MAX_KB_SZ << 1;
        dev->ctrl.max_segments = NVME_MAX_SEGS;
+       mutex_unlock(&dev->shutdown_lock);
+
+       /*
+        * Introduce CONNECTING state from nvme-fc/rdma transports to mark the
+        * initializing procedure here.
+        */
+       if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_CONNECTING)) {
+               dev_warn(dev->ctrl.device,
+                       "failed to mark controller CONNECTING\n");
+               goto out;
+       }
 
        result = nvme_init_identify(&dev->ctrl);
        if (result)
@@ -2619,6 +2651,8 @@ static void nvme_reset_work(struct work_struct *work)
        nvme_start_ctrl(&dev->ctrl);
        return;
 
+ out_unlock:
+       mutex_unlock(&dev->shutdown_lock);
  out:
        nvme_remove_dead_ctrl(dev, result);
 }
@@ -2946,6 +2980,8 @@ static const struct pci_device_id nvme_id_table[] = {
        { PCI_VDEVICE(INTEL, 0xf1a5),   /* Intel 600P/P3100 */
                .driver_data = NVME_QUIRK_NO_DEEPEST_PS |
                                NVME_QUIRK_MEDIUM_PRIO_SQ },
+       { PCI_VDEVICE(INTEL, 0xf1a6),   /* Intel 760p/Pro 7600p */
+               .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, },
        { PCI_VDEVICE(INTEL, 0x5845),   /* Qemu emulated controller */
                .driver_data = NVME_QUIRK_IDENTIFY_CNS, },
        { PCI_DEVICE(0x1bb1, 0x0100),   /* Seagate Nytro Flash Storage */
index 0a2fd29..52abc3a 100644 (file)
@@ -119,6 +119,7 @@ struct nvme_rdma_ctrl {
 
        struct nvme_ctrl        ctrl;
        bool                    use_inline_data;
+       u32                     io_queues[HCTX_MAX_TYPES];
 };
 
 static inline struct nvme_rdma_ctrl *to_rdma_ctrl(struct nvme_ctrl *ctrl)
@@ -165,8 +166,8 @@ static inline int nvme_rdma_queue_idx(struct nvme_rdma_queue *queue)
 static bool nvme_rdma_poll_queue(struct nvme_rdma_queue *queue)
 {
        return nvme_rdma_queue_idx(queue) >
-               queue->ctrl->ctrl.opts->nr_io_queues +
-               queue->ctrl->ctrl.opts->nr_write_queues;
+               queue->ctrl->io_queues[HCTX_TYPE_DEFAULT] +
+               queue->ctrl->io_queues[HCTX_TYPE_READ];
 }
 
 static inline size_t nvme_rdma_inline_data_size(struct nvme_rdma_queue *queue)
@@ -661,8 +662,21 @@ static int nvme_rdma_alloc_io_queues(struct nvme_rdma_ctrl *ctrl)
        nr_io_queues = min_t(unsigned int, nr_io_queues,
                                ibdev->num_comp_vectors);
 
-       nr_io_queues += min(opts->nr_write_queues, num_online_cpus());
-       nr_io_queues += min(opts->nr_poll_queues, num_online_cpus());
+       if (opts->nr_write_queues) {
+               ctrl->io_queues[HCTX_TYPE_DEFAULT] =
+                               min(opts->nr_write_queues, nr_io_queues);
+               nr_io_queues += ctrl->io_queues[HCTX_TYPE_DEFAULT];
+       } else {
+               ctrl->io_queues[HCTX_TYPE_DEFAULT] = nr_io_queues;
+       }
+
+       ctrl->io_queues[HCTX_TYPE_READ] = nr_io_queues;
+
+       if (opts->nr_poll_queues) {
+               ctrl->io_queues[HCTX_TYPE_POLL] =
+                       min(opts->nr_poll_queues, num_online_cpus());
+               nr_io_queues += ctrl->io_queues[HCTX_TYPE_POLL];
+       }
 
        ret = nvme_set_queue_count(&ctrl->ctrl, &nr_io_queues);
        if (ret)
@@ -1689,18 +1703,28 @@ static enum blk_eh_timer_return
 nvme_rdma_timeout(struct request *rq, bool reserved)
 {
        struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq);
+       struct nvme_rdma_queue *queue = req->queue;
+       struct nvme_rdma_ctrl *ctrl = queue->ctrl;
 
-       dev_warn(req->queue->ctrl->ctrl.device,
-                "I/O %d QID %d timeout, reset controller\n",
-                rq->tag, nvme_rdma_queue_idx(req->queue));
+       dev_warn(ctrl->ctrl.device, "I/O %d QID %d timeout\n",
+                rq->tag, nvme_rdma_queue_idx(queue));
 
-       /* queue error recovery */
-       nvme_rdma_error_recovery(req->queue->ctrl);
+       if (ctrl->ctrl.state != NVME_CTRL_LIVE) {
+               /*
+                * Teardown immediately if controller times out while starting
+                * or we are already started error recovery. all outstanding
+                * requests are completed on shutdown, so we return BLK_EH_DONE.
+                */
+               flush_work(&ctrl->err_work);
+               nvme_rdma_teardown_io_queues(ctrl, false);
+               nvme_rdma_teardown_admin_queue(ctrl, false);
+               return BLK_EH_DONE;
+       }
 
-       /* fail with DNR on cmd timeout */
-       nvme_req(rq)->status = NVME_SC_ABORT_REQ | NVME_SC_DNR;
+       dev_warn(ctrl->ctrl.device, "starting error recovery\n");
+       nvme_rdma_error_recovery(ctrl);
 
-       return BLK_EH_DONE;
+       return BLK_EH_RESET_TIMER;
 }
 
 static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
@@ -1779,17 +1803,15 @@ static int nvme_rdma_map_queues(struct blk_mq_tag_set *set)
        struct nvme_rdma_ctrl *ctrl = set->driver_data;
 
        set->map[HCTX_TYPE_DEFAULT].queue_offset = 0;
-       set->map[HCTX_TYPE_READ].nr_queues = ctrl->ctrl.opts->nr_io_queues;
+       set->map[HCTX_TYPE_DEFAULT].nr_queues =
+                       ctrl->io_queues[HCTX_TYPE_DEFAULT];
+       set->map[HCTX_TYPE_READ].nr_queues = ctrl->io_queues[HCTX_TYPE_READ];
        if (ctrl->ctrl.opts->nr_write_queues) {
                /* separate read/write queues */
-               set->map[HCTX_TYPE_DEFAULT].nr_queues =
-                               ctrl->ctrl.opts->nr_write_queues;
                set->map[HCTX_TYPE_READ].queue_offset =
-                               ctrl->ctrl.opts->nr_write_queues;
+                               ctrl->io_queues[HCTX_TYPE_DEFAULT];
        } else {
                /* mixed read/write queues */
-               set->map[HCTX_TYPE_DEFAULT].nr_queues =
-                               ctrl->ctrl.opts->nr_io_queues;
                set->map[HCTX_TYPE_READ].queue_offset = 0;
        }
        blk_mq_rdma_map_queues(&set->map[HCTX_TYPE_DEFAULT],
@@ -1799,12 +1821,12 @@ static int nvme_rdma_map_queues(struct blk_mq_tag_set *set)
 
        if (ctrl->ctrl.opts->nr_poll_queues) {
                set->map[HCTX_TYPE_POLL].nr_queues =
-                               ctrl->ctrl.opts->nr_poll_queues;
+                               ctrl->io_queues[HCTX_TYPE_POLL];
                set->map[HCTX_TYPE_POLL].queue_offset =
-                               ctrl->ctrl.opts->nr_io_queues;
+                               ctrl->io_queues[HCTX_TYPE_DEFAULT];
                if (ctrl->ctrl.opts->nr_write_queues)
                        set->map[HCTX_TYPE_POLL].queue_offset +=
-                               ctrl->ctrl.opts->nr_write_queues;
+                               ctrl->io_queues[HCTX_TYPE_READ];
                blk_mq_map_queues(&set->map[HCTX_TYPE_POLL]);
        }
        return 0;
index de17491..5f0a004 100644 (file)
@@ -1565,8 +1565,7 @@ static void nvme_tcp_destroy_io_queues(struct nvme_ctrl *ctrl, bool remove)
 {
        nvme_tcp_stop_io_queues(ctrl);
        if (remove) {
-               if (ctrl->ops->flags & NVME_F_FABRICS)
-                       blk_cleanup_queue(ctrl->connect_q);
+               blk_cleanup_queue(ctrl->connect_q);
                blk_mq_free_tag_set(ctrl->tagset);
        }
        nvme_tcp_free_io_queues(ctrl);
@@ -1587,12 +1586,10 @@ static int nvme_tcp_configure_io_queues(struct nvme_ctrl *ctrl, bool new)
                        goto out_free_io_queues;
                }
 
-               if (ctrl->ops->flags & NVME_F_FABRICS) {
-                       ctrl->connect_q = blk_mq_init_queue(ctrl->tagset);
-                       if (IS_ERR(ctrl->connect_q)) {
-                               ret = PTR_ERR(ctrl->connect_q);
-                               goto out_free_tag_set;
-                       }
+               ctrl->connect_q = blk_mq_init_queue(ctrl->tagset);
+               if (IS_ERR(ctrl->connect_q)) {
+                       ret = PTR_ERR(ctrl->connect_q);
+                       goto out_free_tag_set;
                }
        } else {
                blk_mq_update_nr_hw_queues(ctrl->tagset,
@@ -1606,7 +1603,7 @@ static int nvme_tcp_configure_io_queues(struct nvme_ctrl *ctrl, bool new)
        return 0;
 
 out_cleanup_connect_q:
-       if (new && (ctrl->ops->flags & NVME_F_FABRICS))
+       if (new)
                blk_cleanup_queue(ctrl->connect_q);
 out_free_tag_set:
        if (new)
@@ -1620,7 +1617,6 @@ static void nvme_tcp_destroy_admin_queue(struct nvme_ctrl *ctrl, bool remove)
 {
        nvme_tcp_stop_queue(ctrl, 0);
        if (remove) {
-               free_opal_dev(ctrl->opal_dev);
                blk_cleanup_queue(ctrl->admin_q);
                blk_mq_free_tag_set(ctrl->admin_tagset);
        }
@@ -1952,20 +1948,23 @@ nvme_tcp_timeout(struct request *rq, bool reserved)
        struct nvme_tcp_ctrl *ctrl = req->queue->ctrl;
        struct nvme_tcp_cmd_pdu *pdu = req->pdu;
 
-       dev_dbg(ctrl->ctrl.device,
+       dev_warn(ctrl->ctrl.device,
                "queue %d: timeout request %#x type %d\n",
-               nvme_tcp_queue_id(req->queue), rq->tag,
-               pdu->hdr.type);
+               nvme_tcp_queue_id(req->queue), rq->tag, pdu->hdr.type);
 
        if (ctrl->ctrl.state != NVME_CTRL_LIVE) {
-               union nvme_result res = {};
-
-               nvme_req(rq)->flags |= NVME_REQ_CANCELLED;
-               nvme_end_request(rq, cpu_to_le16(NVME_SC_ABORT_REQ), res);
+               /*
+                * Teardown immediately if controller times out while starting
+                * or we are already started error recovery. all outstanding
+                * requests are completed on shutdown, so we return BLK_EH_DONE.
+                */
+               flush_work(&ctrl->err_work);
+               nvme_tcp_teardown_io_queues(&ctrl->ctrl, false);
+               nvme_tcp_teardown_admin_queue(&ctrl->ctrl, false);
                return BLK_EH_DONE;
        }
 
-       /* queue error recovery */
+       dev_warn(ctrl->ctrl.device, "starting error recovery\n");
        nvme_tcp_error_recovery(&ctrl->ctrl);
 
        return BLK_EH_RESET_TIMER;
index a8d23eb..a884e3a 100644 (file)
@@ -139,6 +139,10 @@ static void nvmet_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc);
 static void nvmet_rdma_read_data_done(struct ib_cq *cq, struct ib_wc *wc);
 static void nvmet_rdma_qp_event(struct ib_event *event, void *priv);
 static void nvmet_rdma_queue_disconnect(struct nvmet_rdma_queue *queue);
+static void nvmet_rdma_free_rsp(struct nvmet_rdma_device *ndev,
+                               struct nvmet_rdma_rsp *r);
+static int nvmet_rdma_alloc_rsp(struct nvmet_rdma_device *ndev,
+                               struct nvmet_rdma_rsp *r);
 
 static const struct nvmet_fabrics_ops nvmet_rdma_ops;
 
@@ -182,9 +186,17 @@ nvmet_rdma_get_rsp(struct nvmet_rdma_queue *queue)
        spin_unlock_irqrestore(&queue->rsps_lock, flags);
 
        if (unlikely(!rsp)) {
-               rsp = kmalloc(sizeof(*rsp), GFP_KERNEL);
+               int ret;
+
+               rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
                if (unlikely(!rsp))
                        return NULL;
+               ret = nvmet_rdma_alloc_rsp(queue->dev, rsp);
+               if (unlikely(ret)) {
+                       kfree(rsp);
+                       return NULL;
+               }
+
                rsp->allocated = true;
        }
 
@@ -197,6 +209,7 @@ nvmet_rdma_put_rsp(struct nvmet_rdma_rsp *rsp)
        unsigned long flags;
 
        if (unlikely(rsp->allocated)) {
+               nvmet_rdma_free_rsp(rsp->queue->dev, rsp);
                kfree(rsp);
                return;
        }
index 44b37b2..ad0df78 100644 (file)
@@ -1089,7 +1089,7 @@ out:
 
 static int nvmet_tcp_try_recv_one(struct nvmet_tcp_queue *queue)
 {
-       int result;
+       int result = 0;
 
        if (unlikely(queue->rcv_state == NVMET_TCP_RECV_ERR))
                return 0;
index a09c1c3..49b16f7 100644 (file)
@@ -207,11 +207,8 @@ static void __of_attach_node(struct device_node *np)
 
        if (!of_node_check_flag(np, OF_OVERLAY)) {
                np->name = __of_get_property(np, "name", NULL);
-               np->type = __of_get_property(np, "device_type", NULL);
                if (!np->name)
                        np->name = "<NULL>";
-               if (!np->type)
-                       np->type = "<NULL>";
 
                phandle = __of_get_property(np, "phandle", &sz);
                if (!phandle)
index 7099c65..9cc1461 100644 (file)
@@ -314,12 +314,8 @@ static bool populate_node(const void *blob,
        populate_properties(blob, offset, mem, np, pathp, dryrun);
        if (!dryrun) {
                np->name = of_get_property(np, "name", NULL);
-               np->type = of_get_property(np, "device_type", NULL);
-
                if (!np->name)
                        np->name = "<NULL>";
-               if (!np->type)
-                       np->type = "<NULL>";
        }
 
        *pnp = np;
index 2b5ac43..c423e94 100644 (file)
@@ -423,12 +423,9 @@ static int add_changeset_node(struct overlay_changeset *ovcs,
 
                tchild->parent = target->np;
                tchild->name = __of_get_property(node, "name", NULL);
-               tchild->type = __of_get_property(node, "device_type", NULL);
 
                if (!tchild->name)
                        tchild->name = "<NULL>";
-               if (!tchild->type)
-                       tchild->type = "<NULL>";
 
                /* ignore obsolete "linux,phandle" */
                phandle = __of_get_property(node, "phandle", &size);
index d318506..7eda43c 100644 (file)
@@ -155,7 +155,6 @@ static struct device_node * __init of_pdt_create_node(phandle node,
        dp->parent = parent;
 
        dp->name = of_pdt_get_one_property(node, "name");
-       dp->type = of_pdt_get_one_property(node, "device_type");
        dp->phandle = node;
 
        dp->properties = of_pdt_build_prop_list(node);
index 0843003..8631efa 100644 (file)
@@ -806,6 +806,7 @@ struct device_node *of_graph_get_remote_node(const struct device_node *node,
 
        if (!of_device_is_available(remote)) {
                pr_debug("not available for remote node\n");
+               of_node_put(remote);
                return NULL;
        }
 
index e5507ad..18f1639 100644 (file)
@@ -988,11 +988,9 @@ void _opp_free(struct dev_pm_opp *opp)
        kfree(opp);
 }
 
-static void _opp_kref_release(struct kref *kref)
+static void _opp_kref_release(struct dev_pm_opp *opp,
+                             struct opp_table *opp_table)
 {
-       struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref);
-       struct opp_table *opp_table = opp->opp_table;
-
        /*
         * Notify the changes in the availability of the operable
         * frequency/voltage list.
@@ -1002,7 +1000,22 @@ static void _opp_kref_release(struct kref *kref)
        opp_debug_remove_one(opp);
        list_del(&opp->node);
        kfree(opp);
+}
 
+static void _opp_kref_release_unlocked(struct kref *kref)
+{
+       struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref);
+       struct opp_table *opp_table = opp->opp_table;
+
+       _opp_kref_release(opp, opp_table);
+}
+
+static void _opp_kref_release_locked(struct kref *kref)
+{
+       struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref);
+       struct opp_table *opp_table = opp->opp_table;
+
+       _opp_kref_release(opp, opp_table);
        mutex_unlock(&opp_table->lock);
 }
 
@@ -1013,10 +1026,16 @@ void dev_pm_opp_get(struct dev_pm_opp *opp)
 
 void dev_pm_opp_put(struct dev_pm_opp *opp)
 {
-       kref_put_mutex(&opp->kref, _opp_kref_release, &opp->opp_table->lock);
+       kref_put_mutex(&opp->kref, _opp_kref_release_locked,
+                      &opp->opp_table->lock);
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_put);
 
+static void dev_pm_opp_put_unlocked(struct dev_pm_opp *opp)
+{
+       kref_put(&opp->kref, _opp_kref_release_unlocked);
+}
+
 /**
  * dev_pm_opp_remove()  - Remove an OPP from OPP table
  * @dev:       device for which we do this operation
@@ -1060,6 +1079,40 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq)
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
 
+/**
+ * dev_pm_opp_remove_all_dynamic() - Remove all dynamically created OPPs
+ * @dev:       device for which we do this operation
+ *
+ * This function removes all dynamically created OPPs from the opp table.
+ */
+void dev_pm_opp_remove_all_dynamic(struct device *dev)
+{
+       struct opp_table *opp_table;
+       struct dev_pm_opp *opp, *temp;
+       int count = 0;
+
+       opp_table = _find_opp_table(dev);
+       if (IS_ERR(opp_table))
+               return;
+
+       mutex_lock(&opp_table->lock);
+       list_for_each_entry_safe(opp, temp, &opp_table->opp_list, node) {
+               if (opp->dynamic) {
+                       dev_pm_opp_put_unlocked(opp);
+                       count++;
+               }
+       }
+       mutex_unlock(&opp_table->lock);
+
+       /* Drop the references taken by dev_pm_opp_add() */
+       while (count--)
+               dev_pm_opp_put_opp_table(opp_table);
+
+       /* Drop the reference taken by _find_opp_table() */
+       dev_pm_opp_put_opp_table(opp_table);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_remove_all_dynamic);
+
 struct dev_pm_opp *_opp_allocate(struct opp_table *table)
 {
        struct dev_pm_opp *opp;
index 4310c7a..2ab9240 100644 (file)
@@ -21,13 +21,14 @@ menuconfig PCI
          support for PCI-X and the foundations for PCI Express support.
          Say 'Y' here unless you know what you are doing.
 
+if PCI
+
 config PCI_DOMAINS
        bool
        depends on PCI
 
 config PCI_DOMAINS_GENERIC
        bool
-       depends on PCI
        select PCI_DOMAINS
 
 config PCI_SYSCALL
@@ -37,7 +38,6 @@ source "drivers/pci/pcie/Kconfig"
 
 config PCI_MSI
        bool "Message Signaled Interrupts (MSI and MSI-X)"
-       depends on PCI
        select GENERIC_MSI_IRQ
        help
           This allows device drivers to enable MSI (Message Signaled
@@ -59,7 +59,6 @@ config PCI_MSI_IRQ_DOMAIN
 config PCI_QUIRKS
        default y
        bool "Enable PCI quirk workarounds" if EXPERT
-       depends on PCI
        help
          This enables workarounds for various PCI chipset bugs/quirks.
          Disable this only if your target machine is unaffected by PCI
@@ -67,7 +66,7 @@ config PCI_QUIRKS
 
 config PCI_DEBUG
        bool "PCI Debugging"
-       depends on PCI && DEBUG_KERNEL
+       depends on DEBUG_KERNEL
        help
          Say Y here if you want the PCI core to produce a bunch of debug
          messages to the system log.  Select this if you are having a
@@ -77,7 +76,6 @@ config PCI_DEBUG
 
 config PCI_REALLOC_ENABLE_AUTO
        bool "Enable PCI resource re-allocation detection"
-       depends on PCI
        depends on PCI_IOV
        help
          Say Y here if you want the PCI core to detect if PCI resource
@@ -90,7 +88,6 @@ config PCI_REALLOC_ENABLE_AUTO
 
 config PCI_STUB
        tristate "PCI Stub driver"
-       depends on PCI
        help
          Say Y or M here if you want be able to reserve a PCI device
          when it is going to be assigned to a guest operating system.
@@ -99,7 +96,6 @@ config PCI_STUB
 
 config PCI_PF_STUB
        tristate "PCI PF Stub driver"
-       depends on PCI
        depends on PCI_IOV
        help
          Say Y or M here if you want to enable support for devices that
@@ -111,7 +107,7 @@ config PCI_PF_STUB
 
 config XEN_PCIDEV_FRONTEND
         tristate "Xen PCI Frontend"
-        depends on PCI && X86 && XEN
+        depends on X86 && XEN
         select PCI_XEN
        select XEN_XENBUS_FRONTEND
         default y
@@ -133,7 +129,6 @@ config PCI_BRIDGE_EMUL
 
 config PCI_IOV
        bool "PCI IOV support"
-       depends on PCI
        select PCI_ATS
        help
          I/O Virtualization is a PCI feature supported by some devices
@@ -144,7 +139,6 @@ config PCI_IOV
 
 config PCI_PRI
        bool "PCI PRI support"
-       depends on PCI
        select PCI_ATS
        help
          PRI is the PCI Page Request Interface. It allows PCI devices that are
@@ -154,7 +148,6 @@ config PCI_PRI
 
 config PCI_PASID
        bool "PCI PASID support"
-       depends on PCI
        select PCI_ATS
        help
          Process Address Space Identifiers (PASIDs) can be used by PCI devices
@@ -167,7 +160,7 @@ config PCI_PASID
 
 config PCI_P2PDMA
        bool "PCI peer-to-peer transfer support"
-       depends on PCI && ZONE_DEVICE
+       depends on ZONE_DEVICE
        select GENERIC_ALLOCATOR
        help
          EnableÑ• drivers to do PCI peer-to-peer transactions to and from
@@ -184,12 +177,11 @@ config PCI_P2PDMA
 
 config PCI_LABEL
        def_bool y if (DMI || ACPI)
-       depends on PCI
        select NLS
 
 config PCI_HYPERV
         tristate "Hyper-V PCI Frontend"
-        depends on PCI && X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64
+        depends on X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64
         help
           The PCI device frontend driver allows the kernel to import arbitrary
           PCI devices from a PCI backend to support PCI driver domains.
@@ -198,3 +190,5 @@ source "drivers/pci/hotplug/Kconfig"
 source "drivers/pci/controller/Kconfig"
 source "drivers/pci/endpoint/Kconfig"
 source "drivers/pci/switch/Kconfig"
+
+endif
index 52e47da..80f8430 100644 (file)
@@ -310,6 +310,9 @@ static int imx6_pcie_attach_pd(struct device *dev)
        imx6_pcie->pd_pcie = dev_pm_domain_attach_by_name(dev, "pcie");
        if (IS_ERR(imx6_pcie->pd_pcie))
                return PTR_ERR(imx6_pcie->pd_pcie);
+       /* Do nothing when power domain missing */
+       if (!imx6_pcie->pd_pcie)
+               return 0;
        link = device_link_add(dev, imx6_pcie->pd_pcie,
                        DL_FLAG_STATELESS |
                        DL_FLAG_PM_RUNTIME |
@@ -323,13 +326,13 @@ static int imx6_pcie_attach_pd(struct device *dev)
        if (IS_ERR(imx6_pcie->pd_pcie_phy))
                return PTR_ERR(imx6_pcie->pd_pcie_phy);
 
-       device_link_add(dev, imx6_pcie->pd_pcie_phy,
+       link = device_link_add(dev, imx6_pcie->pd_pcie_phy,
                        DL_FLAG_STATELESS |
                        DL_FLAG_PM_RUNTIME |
                        DL_FLAG_RPM_ACTIVE);
-       if (IS_ERR(link)) {
-               dev_err(dev, "Failed to add device_link to pcie_phy pd: %ld\n", PTR_ERR(link));
-               return PTR_ERR(link);
+       if (!link) {
+               dev_err(dev, "Failed to add device_link to pcie_phy pd.\n");
+               return -EINVAL;
        }
 
        return 0;
index 241ebe0..e35e9ea 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/gpio/consumer.h>
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
 #include <linux/pci.h>
index b171b6b..0c389a3 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/resource.h>
 #include <linux/of_pci.h>
 #include <linux/of_irq.h>
-#include <linux/gpio/consumer.h>
 
 #include "pcie-designware.h"
 
@@ -30,7 +29,6 @@ struct armada8k_pcie {
        struct dw_pcie *pci;
        struct clk *clk;
        struct clk *clk_reg;
-       struct gpio_desc *reset_gpio;
 };
 
 #define PCIE_VENDOR_REGS_OFFSET                0x8000
@@ -139,12 +137,6 @@ static int armada8k_pcie_host_init(struct pcie_port *pp)
        struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
        struct armada8k_pcie *pcie = to_armada8k_pcie(pci);
 
-       if (pcie->reset_gpio) {
-               /* assert and then deassert the reset signal */
-               gpiod_set_value_cansleep(pcie->reset_gpio, 1);
-               msleep(100);
-               gpiod_set_value_cansleep(pcie->reset_gpio, 0);
-       }
        dw_pcie_setup_rc(pp);
        armada8k_pcie_establish_link(pcie);
 
@@ -257,14 +249,6 @@ static int armada8k_pcie_probe(struct platform_device *pdev)
                goto fail_clkreg;
        }
 
-       /* Get reset gpio signal and hold asserted (logically high) */
-       pcie->reset_gpio = devm_gpiod_get_optional(dev, "reset",
-                                                  GPIOD_OUT_HIGH);
-       if (IS_ERR(pcie->reset_gpio)) {
-               ret = PTR_ERR(pcie->reset_gpio);
-               goto fail_clkreg;
-       }
-
        platform_set_drvdata(pdev, pcie);
 
        ret = armada8k_add_pcie_port(pcie, pdev);
index 9deb569..cb3401a 100644 (file)
@@ -602,9 +602,9 @@ int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node)
        }
 
        /* Reserve memory for event queue and make sure memories are zeroed */
-       msi->eq_cpu = dma_zalloc_coherent(pcie->dev,
-                                         msi->nr_eq_region * EQ_MEM_REGION_SIZE,
-                                         &msi->eq_dma, GFP_KERNEL);
+       msi->eq_cpu = dma_alloc_coherent(pcie->dev,
+                                        msi->nr_eq_region * EQ_MEM_REGION_SIZE,
+                                        &msi->eq_dma, GFP_KERNEL);
        if (!msi->eq_cpu) {
                ret = -ENOMEM;
                goto free_irqs;
index 7a1c8a0..4c0b478 100644 (file)
@@ -1168,7 +1168,8 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
                                   const struct irq_affinity *affd)
 {
        static const struct irq_affinity msi_default_affd;
-       int vecs = -ENOSPC;
+       int msix_vecs = -ENOSPC;
+       int msi_vecs = -ENOSPC;
 
        if (flags & PCI_IRQ_AFFINITY) {
                if (!affd)
@@ -1179,16 +1180,17 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
        }
 
        if (flags & PCI_IRQ_MSIX) {
-               vecs = __pci_enable_msix_range(dev, NULL, min_vecs, max_vecs,
-                               affd);
-               if (vecs > 0)
-                       return vecs;
+               msix_vecs = __pci_enable_msix_range(dev, NULL, min_vecs,
+                                                   max_vecs, affd);
+               if (msix_vecs > 0)
+                       return msix_vecs;
        }
 
        if (flags & PCI_IRQ_MSI) {
-               vecs = __pci_enable_msi_range(dev, min_vecs, max_vecs, affd);
-               if (vecs > 0)
-                       return vecs;
+               msi_vecs = __pci_enable_msi_range(dev, min_vecs, max_vecs,
+                                                 affd);
+               if (msi_vecs > 0)
+                       return msi_vecs;
        }
 
        /* use legacy irq if allowed */
@@ -1199,7 +1201,9 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
                }
        }
 
-       return vecs;
+       if (msix_vecs == -ENOSPC)
+               return -ENOSPC;
+       return msi_vecs;
 }
 EXPORT_SYMBOL(pci_alloc_irq_vectors_affinity);
 
index c9d8e3c..c25acac 100644 (file)
@@ -6195,7 +6195,8 @@ static int __init pci_setup(char *str)
                        } else if (!strncmp(str, "pcie_scan_all", 13)) {
                                pci_add_flags(PCI_SCAN_ALL_PCIE_DEVS);
                        } else if (!strncmp(str, "disable_acs_redir=", 18)) {
-                               disable_acs_redir_param = str + 18;
+                               disable_acs_redir_param =
+                                       kstrdup(str + 18, GFP_KERNEL);
                        } else {
                                printk(KERN_ERR "PCI: Unknown option `%s'\n",
                                                str);
index b0a413f..e2a879e 100644 (file)
@@ -639,8 +639,9 @@ static void quirk_synopsys_haps(struct pci_dev *pdev)
                break;
        }
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SYNOPSYS, PCI_ANY_ID,
-                        quirk_synopsys_haps);
+DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_SYNOPSYS, PCI_ANY_ID,
+                              PCI_CLASS_SERIAL_USB_XHCI, 0,
+                              quirk_synopsys_haps);
 
 /*
  * Let's make the southbridge information explicit instead of having to
index 6c5536d..e22766c 100644 (file)
@@ -1373,10 +1373,10 @@ static int switchtec_init_pci(struct switchtec_dev *stdev,
        if (ioread32(&stdev->mmio_mrpc->dma_ver) == 0)
                return 0;
 
-       stdev->dma_mrpc = dma_zalloc_coherent(&stdev->pdev->dev,
-                                             sizeof(*stdev->dma_mrpc),
-                                             &stdev->dma_mrpc_dma_addr,
-                                             GFP_KERNEL);
+       stdev->dma_mrpc = dma_alloc_coherent(&stdev->pdev->dev,
+                                            sizeof(*stdev->dma_mrpc),
+                                            &stdev->dma_mrpc_dma_addr,
+                                            GFP_KERNEL);
        if (stdev->dma_mrpc == NULL)
                return -ENOMEM;
 
index a91fc67..d70ba9b 100644 (file)
@@ -32,7 +32,7 @@
 
 /* register 0x01 */
 #define REF_FREF_SEL_25                BIT(0)
-#define PHY_MODE_SATA          (0x0 << 5)
+#define PHY_BERLIN_MODE_SATA   (0x0 << 5)
 
 /* register 0x02 */
 #define USE_MAX_PLL_RATE       BIT(12)
@@ -102,7 +102,8 @@ static int phy_berlin_sata_power_on(struct phy *phy)
 
        /* set PHY mode and ref freq to 25 MHz */
        phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x01,
-                                   0x00ff, REF_FREF_SEL_25 | PHY_MODE_SATA);
+                                   0x00ff,
+                                   REF_FREF_SEL_25 | PHY_BERLIN_MODE_SATA);
 
        /* set PHY up to 6 Gbps */
        phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x25,
index 6fd6e07..09a77e5 100644 (file)
@@ -31,7 +31,7 @@ static int ath79_usb_phy_power_on(struct phy *phy)
 
        err = reset_control_deassert(priv->reset);
        if (err && priv->no_suspend_override)
-               reset_control_assert(priv->no_suspend_override);
+               reset_control_deassert(priv->no_suspend_override);
 
        return err;
 }
@@ -69,7 +69,7 @@ static int ath79_usb_phy_probe(struct platform_device *pdev)
        if (!priv)
                return -ENOMEM;
 
-       priv->reset = devm_reset_control_get(&pdev->dev, "usb-phy");
+       priv->reset = devm_reset_control_get(&pdev->dev, "phy");
        if (IS_ERR(priv->reset))
                return PTR_ERR(priv->reset);
 
index f137e01..c4709ed 100644 (file)
@@ -82,6 +82,7 @@ config PHY_TI_GMII_SEL
        default y if TI_CPSW=y
        depends on TI_CPSW || COMPILE_TEST
        select GENERIC_PHY
+       select REGMAP
        default m
        help
          This driver supports configuring of the TI CPSW Port mode depending on
index 77fdaa5..a52c5bb 100644 (file)
@@ -204,11 +204,11 @@ static struct phy *phy_gmii_sel_of_xlate(struct device *dev,
 
        if (args->args_count < 1)
                return ERR_PTR(-EINVAL);
+       if (!priv || !priv->if_phys)
+               return ERR_PTR(-ENODEV);
        if (priv->soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN) &&
            args->args_count < 2)
                return ERR_PTR(-EINVAL);
-       if (!priv || !priv->if_phys)
-               return ERR_PTR(-ENODEV);
        if (phy_id > priv->soc_data->num_ports)
                return ERR_PTR(-EINVAL);
        if (phy_id != priv->if_phys[phy_id - 1].id)
index 05044e3..03ec7a5 100644 (file)
@@ -1513,7 +1513,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
                        DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_Strago"),
-                       DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
                },
        },
        {
@@ -1521,7 +1521,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "HP"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Setzer"),
-                       DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
                },
        },
        {
@@ -1529,7 +1529,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Cyan"),
-                       DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
                },
        },
        {
@@ -1537,7 +1537,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Celes"),
-                       DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
                },
        },
        {}
index 1817786..a005cbc 100644 (file)
@@ -45,12 +45,14 @@ config PINCTRL_MT2701
 config PINCTRL_MT7623
        bool "Mediatek MT7623 pin control with generic binding"
        depends on MACH_MT7623 || COMPILE_TEST
+       depends on OF
        default MACH_MT7623
        select PINCTRL_MTK_MOORE
 
 config PINCTRL_MT7629
        bool "Mediatek MT7629 pin control"
        depends on MACH_MT7629 || COMPILE_TEST
+       depends on OF
        default MACH_MT7629
        select PINCTRL_MTK_MOORE
 
@@ -92,6 +94,7 @@ config PINCTRL_MT6797
 
 config PINCTRL_MT7622
        bool "MediaTek MT7622 pin control"
+       depends on OF
        depends on ARM64 || COMPILE_TEST
        default ARM64 && ARCH_MEDIATEK
        select PINCTRL_MTK_MOORE
index b03481e..98905d4 100644 (file)
@@ -832,8 +832,13 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
                break;
 
        case MCP_TYPE_S18:
+               one_regmap_config =
+                       devm_kmemdup(dev, &mcp23x17_regmap,
+                               sizeof(struct regmap_config), GFP_KERNEL);
+               if (!one_regmap_config)
+                       return -ENOMEM;
                mcp->regmap = devm_regmap_init(dev, &mcp23sxx_spi_regmap, mcp,
-                                              &mcp23x17_regmap);
+                                              one_regmap_config);
                mcp->reg_shift = 1;
                mcp->chip.ngpio = 16;
                mcp->chip.label = "mcp23s18";
index aa8b581..ef4268c 100644 (file)
@@ -588,7 +588,7 @@ static const unsigned int h6_irq_bank_map[] = { 1, 5, 6, 7 };
 static const struct sunxi_pinctrl_desc h6_pinctrl_data = {
        .pins = h6_pins,
        .npins = ARRAY_SIZE(h6_pins),
-       .irq_banks = 3,
+       .irq_banks = 4,
        .irq_bank_map = h6_irq_bank_map,
        .irq_read_needs_mux = true,
 };
index 5d9184d..0e7fa69 100644 (file)
@@ -698,26 +698,24 @@ static int sunxi_pmx_request(struct pinctrl_dev *pctldev, unsigned offset)
 {
        struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
        unsigned short bank = offset / PINS_PER_BANK;
-       struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank];
-       struct regulator *reg;
+       unsigned short bank_offset = bank - pctl->desc->pin_base /
+                                           PINS_PER_BANK;
+       struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank_offset];
+       struct regulator *reg = s_reg->regulator;
+       char supply[16];
        int ret;
 
-       reg = s_reg->regulator;
-       if (!reg) {
-               char supply[16];
-
-               snprintf(supply, sizeof(supply), "vcc-p%c", 'a' + bank);
-               reg = regulator_get(pctl->dev, supply);
-               if (IS_ERR(reg)) {
-                       dev_err(pctl->dev, "Couldn't get bank P%c regulator\n",
-                               'A' + bank);
-                       return PTR_ERR(reg);
-               }
-
-               s_reg->regulator = reg;
-               refcount_set(&s_reg->refcount, 1);
-       } else {
+       if (reg) {
                refcount_inc(&s_reg->refcount);
+               return 0;
+       }
+
+       snprintf(supply, sizeof(supply), "vcc-p%c", 'a' + bank);
+       reg = regulator_get(pctl->dev, supply);
+       if (IS_ERR(reg)) {
+               dev_err(pctl->dev, "Couldn't get bank P%c regulator\n",
+                       'A' + bank);
+               return PTR_ERR(reg);
        }
 
        ret = regulator_enable(reg);
@@ -727,13 +725,13 @@ static int sunxi_pmx_request(struct pinctrl_dev *pctldev, unsigned offset)
                goto out;
        }
 
+       s_reg->regulator = reg;
+       refcount_set(&s_reg->refcount, 1);
+
        return 0;
 
 out:
-       if (refcount_dec_and_test(&s_reg->refcount)) {
-               regulator_put(s_reg->regulator);
-               s_reg->regulator = NULL;
-       }
+       regulator_put(s_reg->regulator);
 
        return ret;
 }
@@ -742,7 +740,9 @@ static int sunxi_pmx_free(struct pinctrl_dev *pctldev, unsigned offset)
 {
        struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
        unsigned short bank = offset / PINS_PER_BANK;
-       struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank];
+       unsigned short bank_offset = bank - pctl->desc->pin_base /
+                                           PINS_PER_BANK;
+       struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank_offset];
 
        if (!refcount_dec_and_test(&s_reg->refcount))
                return 0;
index e340d2a..034c031 100644 (file)
@@ -136,7 +136,7 @@ struct sunxi_pinctrl {
        struct gpio_chip                *chip;
        const struct sunxi_pinctrl_desc *desc;
        struct device                   *dev;
-       struct sunxi_pinctrl_regulator  regulators[12];
+       struct sunxi_pinctrl_regulator  regulators[9];
        struct irq_domain               *domain;
        struct sunxi_pinctrl_function   *functions;
        unsigned                        nfunctions;
index e3b62c2..b5e9db8 100644 (file)
@@ -905,6 +905,7 @@ config TOSHIBA_WMI
 config ACPI_CMPC
        tristate "CMPC Laptop Extras"
        depends on ACPI && INPUT
+       depends on BACKLIGHT_LCD_SUPPORT
        depends on RFKILL || RFKILL=n
        select BACKLIGHT_CLASS_DEVICE
        help
@@ -1009,7 +1010,7 @@ config INTEL_MFLD_THERMAL
 
 config INTEL_IPS
        tristate "Intel Intelligent Power Sharing"
-       depends on ACPI
+       depends on ACPI && PCI
        ---help---
          Intel Calpella platforms support dynamic power sharing between the
          CPU and GPU, maximizing performance in a given TDP.  This driver,
@@ -1128,6 +1129,7 @@ config INTEL_OAKTRAIL
 config SAMSUNG_Q10
        tristate "Samsung Q10 Extras"
        depends on ACPI
+       depends on BACKLIGHT_LCD_SUPPORT
        select BACKLIGHT_CLASS_DEVICE
        ---help---
          This driver provides support for backlight control on Samsung Q10
@@ -1135,7 +1137,7 @@ config SAMSUNG_Q10
 
 config APPLE_GMUX
        tristate "Apple Gmux Driver"
-       depends on ACPI
+       depends on ACPI && PCI
        depends on PNP
        depends on BACKLIGHT_CLASS_DEVICE
        depends on BACKLIGHT_APPLE=n || BACKLIGHT_APPLE
@@ -1174,7 +1176,7 @@ config INTEL_SMARTCONNECT
 
 config INTEL_PMC_IPC
        tristate "Intel PMC IPC Driver"
-       depends on ACPI
+       depends on ACPI && PCI
        ---help---
        This driver provides support for PMC control on some Intel platforms.
        The PMC is an ARC processor which defines IPC commands for communication
index 797fab3..7cbea79 100644 (file)
@@ -224,7 +224,8 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
                        extoff = NULL;
                        break;
                }
-               if (extoff->n_samples > PTP_MAX_SAMPLES) {
+               if (extoff->n_samples > PTP_MAX_SAMPLES
+                   || extoff->rsv[0] || extoff->rsv[1] || extoff->rsv[2]) {
                        err = -EINVAL;
                        break;
                }
index bb65585..b64c56c 100644 (file)
@@ -1382,9 +1382,9 @@ static int tsi721_doorbell_init(struct tsi721_device *priv)
        INIT_WORK(&priv->idb_work, tsi721_db_dpc);
 
        /* Allocate buffer for inbound doorbells queue */
-       priv->idb_base = dma_zalloc_coherent(&priv->pdev->dev,
-                               IDB_QSIZE * TSI721_IDB_ENTRY_SIZE,
-                               &priv->idb_dma, GFP_KERNEL);
+       priv->idb_base = dma_alloc_coherent(&priv->pdev->dev,
+                                           IDB_QSIZE * TSI721_IDB_ENTRY_SIZE,
+                                           &priv->idb_dma, GFP_KERNEL);
        if (!priv->idb_base)
                return -ENOMEM;
 
@@ -1447,9 +1447,9 @@ static int tsi721_bdma_maint_init(struct tsi721_device *priv)
        regs = priv->regs + TSI721_DMAC_BASE(TSI721_DMACH_MAINT);
 
        /* Allocate space for DMA descriptors */
-       bd_ptr = dma_zalloc_coherent(&priv->pdev->dev,
-                                       bd_num * sizeof(struct tsi721_dma_desc),
-                                       &bd_phys, GFP_KERNEL);
+       bd_ptr = dma_alloc_coherent(&priv->pdev->dev,
+                                   bd_num * sizeof(struct tsi721_dma_desc),
+                                   &bd_phys, GFP_KERNEL);
        if (!bd_ptr)
                return -ENOMEM;
 
@@ -1464,7 +1464,7 @@ static int tsi721_bdma_maint_init(struct tsi721_device *priv)
        sts_size = (bd_num >= TSI721_DMA_MINSTSSZ) ?
                                        bd_num : TSI721_DMA_MINSTSSZ;
        sts_size = roundup_pow_of_two(sts_size);
-       sts_ptr = dma_zalloc_coherent(&priv->pdev->dev,
+       sts_ptr = dma_alloc_coherent(&priv->pdev->dev,
                                     sts_size * sizeof(struct tsi721_dma_sts),
                                     &sts_phys, GFP_KERNEL);
        if (!sts_ptr) {
@@ -1939,10 +1939,10 @@ static int tsi721_open_outb_mbox(struct rio_mport *mport, void *dev_id,
 
        /* Outbound message descriptor status FIFO allocation */
        priv->omsg_ring[mbox].sts_size = roundup_pow_of_two(entries + 1);
-       priv->omsg_ring[mbox].sts_base = dma_zalloc_coherent(&priv->pdev->dev,
-                       priv->omsg_ring[mbox].sts_size *
-                                               sizeof(struct tsi721_dma_sts),
-                       &priv->omsg_ring[mbox].sts_phys, GFP_KERNEL);
+       priv->omsg_ring[mbox].sts_base = dma_alloc_coherent(&priv->pdev->dev,
+                                                           priv->omsg_ring[mbox].sts_size * sizeof(struct tsi721_dma_sts),
+                                                           &priv->omsg_ring[mbox].sts_phys,
+                                                           GFP_KERNEL);
        if (priv->omsg_ring[mbox].sts_base == NULL) {
                tsi_debug(OMSG, &priv->pdev->dev,
                        "ENOMEM for OB_MSG_%d status FIFO", mbox);
index 006ea5a..7f5d443 100644 (file)
@@ -90,9 +90,9 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan, int bd_num)
         * Allocate space for DMA descriptors
         * (add an extra element for link descriptor)
         */
-       bd_ptr = dma_zalloc_coherent(dev,
-                               (bd_num + 1) * sizeof(struct tsi721_dma_desc),
-                               &bd_phys, GFP_ATOMIC);
+       bd_ptr = dma_alloc_coherent(dev,
+                                   (bd_num + 1) * sizeof(struct tsi721_dma_desc),
+                                   &bd_phys, GFP_ATOMIC);
        if (!bd_ptr)
                return -ENOMEM;
 
@@ -108,7 +108,7 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan, int bd_num)
        sts_size = ((bd_num + 1) >= TSI721_DMA_MINSTSSZ) ?
                                        (bd_num + 1) : TSI721_DMA_MINSTSSZ;
        sts_size = roundup_pow_of_two(sts_size);
-       sts_ptr = dma_zalloc_coherent(dev,
+       sts_ptr = dma_alloc_coherent(dev,
                                     sts_size * sizeof(struct tsi721_dma_sts),
                                     &sts_phys, GFP_ATOMIC);
        if (!sts_ptr) {
index 183fc42..2d7cd34 100644 (file)
@@ -153,10 +153,15 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
                                 const bool * ctx,
                                 struct irq_affinity *desc)
 {
-       int i, ret;
+       int i, ret, queue_idx = 0;
 
        for (i = 0; i < nvqs; ++i) {
-               vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i],
+               if (!names[i]) {
+                       vqs[i] = NULL;
+                       continue;
+               }
+
+               vqs[i] = rp_find_vq(vdev, queue_idx++, callbacks[i], names[i],
                                    ctx ? ctx[i] : false);
                if (IS_ERR(vqs[i])) {
                        ret = PTR_ERR(vqs[i]);
index c21da9f..2e01bd8 100644 (file)
@@ -109,7 +109,7 @@ config RESET_QCOM_PDC
 
 config RESET_SIMPLE
        bool "Simple Reset Controller Driver" if COMPILE_TEST
-       default ARCH_SOCFPGA || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED
+       default ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED
        help
          This enables a simple reset controller driver for reset lines that
          that can be asserted and deasserted by toggling bits in a contiguous,
@@ -128,6 +128,14 @@ config RESET_STM32MP157
        help
          This enables the RCC reset controller driver for STM32 MPUs.
 
+config RESET_SOCFPGA
+       bool "SoCFPGA Reset Driver" if COMPILE_TEST && !ARCH_SOCFPGA
+       default ARCH_SOCFPGA
+       select RESET_SIMPLE
+       help
+         This enables the reset driver for the SoCFPGA ARMv7 platforms. This
+         driver gets initialized early during platform init calls.
+
 config RESET_SUNXI
        bool "Allwinner SoCs Reset Driver" if COMPILE_TEST && !ARCH_SUNXI
        default ARCH_SUNXI
@@ -163,15 +171,15 @@ config RESET_UNIPHIER
          Say Y if you want to control reset signals provided by System Control
          block, Media I/O block, Peripheral Block.
 
-config RESET_UNIPHIER_USB3
-       tristate "USB3 reset driver for UniPhier SoCs"
+config RESET_UNIPHIER_GLUE
+       tristate "Reset driver in glue layer for UniPhier SoCs"
        depends on (ARCH_UNIPHIER || COMPILE_TEST) && OF
        default ARCH_UNIPHIER
        select RESET_SIMPLE
        help
-         Support for the USB3 core reset on UniPhier SoCs.
-         Say Y if you want to control reset signals provided by
-         USB3 glue layer.
+         Support for peripheral core reset included in its own glue layer
+         on UniPhier SoCs. Say Y if you want to control reset signals
+         provided by the glue layer.
 
 config RESET_ZYNQ
        bool "ZYNQ Reset Driver" if COMPILE_TEST
index d08e8b9..dc7874d 100644 (file)
@@ -19,10 +19,11 @@ obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o
 obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o
 obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
 obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o
+obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
 obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
 obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
 obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o
 obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
-obj-$(CONFIG_RESET_UNIPHIER_USB3) += reset-uniphier-usb3.o
+obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o
 obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
 
index d1887c0..9582efb 100644 (file)
@@ -795,3 +795,45 @@ devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
        return rstc;
 }
 EXPORT_SYMBOL_GPL(devm_reset_control_array_get);
+
+static int reset_control_get_count_from_lookup(struct device *dev)
+{
+       const struct reset_control_lookup *lookup;
+       const char *dev_id;
+       int count = 0;
+
+       if (!dev)
+               return -EINVAL;
+
+       dev_id = dev_name(dev);
+       mutex_lock(&reset_lookup_mutex);
+
+       list_for_each_entry(lookup, &reset_lookup_list, list) {
+               if (!strcmp(lookup->dev_id, dev_id))
+                       count++;
+       }
+
+       mutex_unlock(&reset_lookup_mutex);
+
+       if (count == 0)
+               count = -ENOENT;
+
+       return count;
+}
+
+/**
+ * reset_control_get_count - Count number of resets available with a device
+ *
+ * @dev: device for which to return the number of resets
+ *
+ * Returns positive reset count on success, or error number on failure and
+ * on count being zero.
+ */
+int reset_control_get_count(struct device *dev)
+{
+       if (dev->of_node)
+               return of_reset_control_get_count(dev->of_node);
+
+       return reset_control_get_count_from_lookup(dev);
+}
+EXPORT_SYMBOL_GPL(reset_control_get_count);
index 8bce391..4c7b864 100644 (file)
@@ -86,6 +86,7 @@ static int hsdk_reset_reset(struct reset_controller_dev *rcdev,
 
 static const struct reset_control_ops hsdk_reset_ops = {
        .reset  = hsdk_reset_reset,
+       .deassert = hsdk_reset_reset,
 };
 
 static int hsdk_reset_probe(struct platform_device *pdev)
index a91107f..77fbba3 100644 (file)
@@ -109,7 +109,7 @@ struct reset_simple_devdata {
 #define SOCFPGA_NR_BANKS       8
 
 static const struct reset_simple_devdata reset_simple_socfpga = {
-       .reg_offset = 0x10,
+       .reg_offset = 0x20,
        .nr_resets = SOCFPGA_NR_BANKS * 32,
        .status_active_low = true,
 };
@@ -120,7 +120,8 @@ static const struct reset_simple_devdata reset_simple_active_low = {
 };
 
 static const struct of_device_id reset_simple_dt_ids[] = {
-       { .compatible = "altr,rst-mgr", .data = &reset_simple_socfpga },
+       { .compatible = "altr,stratix10-rst-mgr",
+               .data = &reset_simple_socfpga },
        { .compatible = "st,stm32-rcc", },
        { .compatible = "allwinner,sun6i-a31-clock-reset",
                .data = &reset_simple_active_low },
@@ -166,14 +167,6 @@ static int reset_simple_probe(struct platform_device *pdev)
                data->status_active_low = devdata->status_active_low;
        }
 
-       if (of_device_is_compatible(dev->of_node, "altr,rst-mgr") &&
-           of_property_read_u32(dev->of_node, "altr,modrst-offset",
-                                &reg_offset)) {
-               dev_warn(dev,
-                        "missing altr,modrst-offset property, assuming 0x%x!\n",
-                        reg_offset);
-       }
-
        data->membase += reg_offset;
 
        return devm_reset_controller_register(dev, &data->rcdev);
diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c
new file mode 100644 (file)
index 0000000..318cfc5
--- /dev/null
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018, Intel Corporation
+ * Copied from reset-sunxi.c
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include "reset-simple.h"
+
+#define SOCFPGA_NR_BANKS       8
+void __init socfpga_reset_init(void);
+
+static int a10_reset_init(struct device_node *np)
+{
+       struct reset_simple_data *data;
+       struct resource res;
+       resource_size_t size;
+       int ret;
+       u32 reg_offset = 0x10;
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       ret = of_address_to_resource(np, 0, &res);
+       if (ret)
+               goto err_alloc;
+
+       size = resource_size(&res);
+       if (!request_mem_region(res.start, size, np->name)) {
+               ret = -EBUSY;
+               goto err_alloc;
+       }
+
+       data->membase = ioremap(res.start, size);
+       if (!data->membase) {
+               ret = -ENOMEM;
+               goto err_alloc;
+       }
+
+       if (of_property_read_u32(np, "altr,modrst-offset", &reg_offset))
+               pr_warn("missing altr,modrst-offset property, assuming 0x10\n");
+       data->membase += reg_offset;
+
+       spin_lock_init(&data->lock);
+
+       data->rcdev.owner = THIS_MODULE;
+       data->rcdev.nr_resets = SOCFPGA_NR_BANKS * 32;
+       data->rcdev.ops = &reset_simple_ops;
+       data->rcdev.of_node = np;
+       data->status_active_low = true;
+
+       return reset_controller_register(&data->rcdev);
+
+err_alloc:
+       kfree(data);
+       return ret;
+};
+
+/*
+ * These are the reset controller we need to initialize early on in
+ * our system, before we can even think of using a regular device
+ * driver for it.
+ * The controllers that we can register through the regular device
+ * model are handled by the simple reset driver directly.
+ */
+static const struct of_device_id socfpga_early_reset_dt_ids[] __initconst = {
+       { .compatible = "altr,rst-mgr", },
+       { /* sentinel */ },
+};
+
+void __init socfpga_reset_init(void)
+{
+       struct device_node *np;
+
+       for_each_matching_node(np, socfpga_early_reset_dt_ids)
+               a10_reset_init(np);
+}
similarity index 73%
rename from drivers/reset/reset-uniphier-usb3.c
rename to drivers/reset/reset-uniphier-glue.c
index ffa1b19..a45923f 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 //
-// reset-uniphier-usb3.c - USB3 reset driver for UniPhier
+// reset-uniphier-glue.c - Glue layer reset driver for UniPhier
 // Copyright 2018 Socionext Inc.
 // Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
 
 #define MAX_CLKS       2
 #define MAX_RSTS       2
 
-struct uniphier_usb3_reset_soc_data {
+struct uniphier_glue_reset_soc_data {
        int nclks;
        const char * const *clock_names;
        int nrsts;
        const char * const *reset_names;
 };
 
-struct uniphier_usb3_reset_priv {
+struct uniphier_glue_reset_priv {
        struct clk_bulk_data clk[MAX_CLKS];
        struct reset_control *rst[MAX_RSTS];
        struct reset_simple_data rdata;
-       const struct uniphier_usb3_reset_soc_data *data;
+       const struct uniphier_glue_reset_soc_data *data;
 };
 
-static int uniphier_usb3_reset_probe(struct platform_device *pdev)
+static int uniphier_glue_reset_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       struct uniphier_usb3_reset_priv *priv;
+       struct uniphier_glue_reset_priv *priv;
        struct resource *res;
        resource_size_t size;
        const char *name;
@@ -100,9 +100,9 @@ out_rst_assert:
        return ret;
 }
 
-static int uniphier_usb3_reset_remove(struct platform_device *pdev)
+static int uniphier_glue_reset_remove(struct platform_device *pdev)
 {
-       struct uniphier_usb3_reset_priv *priv = platform_get_drvdata(pdev);
+       struct uniphier_glue_reset_priv *priv = platform_get_drvdata(pdev);
        int i;
 
        for (i = 0; i < priv->data->nrsts; i++)
@@ -117,7 +117,7 @@ static const char * const uniphier_pro4_clock_reset_names[] = {
        "gio", "link",
 };
 
-static const struct uniphier_usb3_reset_soc_data uniphier_pro4_data = {
+static const struct uniphier_glue_reset_soc_data uniphier_pro4_data = {
        .nclks = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
        .clock_names = uniphier_pro4_clock_reset_names,
        .nrsts = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
@@ -128,14 +128,14 @@ static const char * const uniphier_pxs2_clock_reset_names[] = {
        "link",
 };
 
-static const struct uniphier_usb3_reset_soc_data uniphier_pxs2_data = {
+static const struct uniphier_glue_reset_soc_data uniphier_pxs2_data = {
        .nclks = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
        .clock_names = uniphier_pxs2_clock_reset_names,
        .nrsts = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
        .reset_names = uniphier_pxs2_clock_reset_names,
 };
 
-static const struct of_device_id uniphier_usb3_reset_match[] = {
+static const struct of_device_id uniphier_glue_reset_match[] = {
        {
                .compatible = "socionext,uniphier-pro4-usb3-reset",
                .data = &uniphier_pro4_data,
@@ -152,20 +152,32 @@ static const struct of_device_id uniphier_usb3_reset_match[] = {
                .compatible = "socionext,uniphier-pxs3-usb3-reset",
                .data = &uniphier_pxs2_data,
        },
+       {
+               .compatible = "socionext,uniphier-pro4-ahci-reset",
+               .data = &uniphier_pro4_data,
+       },
+       {
+               .compatible = "socionext,uniphier-pxs2-ahci-reset",
+               .data = &uniphier_pxs2_data,
+       },
+       {
+               .compatible = "socionext,uniphier-pxs3-ahci-reset",
+               .data = &uniphier_pxs2_data,
+       },
        { /* Sentinel */ }
 };
-MODULE_DEVICE_TABLE(of, uniphier_usb3_reset_match);
+MODULE_DEVICE_TABLE(of, uniphier_glue_reset_match);
 
-static struct platform_driver uniphier_usb3_reset_driver = {
-       .probe = uniphier_usb3_reset_probe,
-       .remove = uniphier_usb3_reset_remove,
+static struct platform_driver uniphier_glue_reset_driver = {
+       .probe = uniphier_glue_reset_probe,
+       .remove = uniphier_glue_reset_remove,
        .driver = {
-               .name = "uniphier-usb3-reset",
-               .of_match_table = uniphier_usb3_reset_match,
+               .name = "uniphier-glue-reset",
+               .of_match_table = uniphier_glue_reset_match,
        },
 };
-module_platform_driver(uniphier_usb3_reset_driver);
+module_platform_driver(uniphier_glue_reset_driver);
 
 MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
-MODULE_DESCRIPTION("UniPhier USB3 Reset Driver");
+MODULE_DESCRIPTION("UniPhier Glue layer reset driver");
 MODULE_LICENSE("GPL");
index 4e7b55a..6e294b4 100644 (file)
@@ -4469,6 +4469,14 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp)
                usrparm.psf_data &= 0x7fffffffULL;
                usrparm.rssd_result &= 0x7fffffffULL;
        }
+       /* at least 2 bytes are accessed and should be allocated */
+       if (usrparm.psf_data_len < 2) {
+               DBF_DEV_EVENT(DBF_WARNING, device,
+                             "Symmetrix ioctl invalid data length %d",
+                             usrparm.psf_data_len);
+               rc = -EINVAL;
+               goto out;
+       }
        /* alloc I/O data area */
        psf_data = kzalloc(usrparm.psf_data_len, GFP_KERNEL | GFP_DMA);
        rssd_result = kzalloc(usrparm.rssd_result_len, GFP_KERNEL | GFP_DMA);
index 194ffd5..039b207 100644 (file)
@@ -60,7 +60,9 @@ static void sclp_cpu_capability_notify(struct work_struct *work)
 
 static void __ref sclp_cpu_change_notify(struct work_struct *work)
 {
+       lock_device_hotplug();
        smp_rescan_cpus();
+       unlock_device_hotplug();
 }
 
 static void sclp_conf_receiver_fn(struct evbuf_header *evbuf)
index 48ea000..5a69974 100644 (file)
@@ -248,7 +248,8 @@ static inline int ap_test_config(unsigned int *field, unsigned int nr)
 static inline int ap_test_config_card_id(unsigned int id)
 {
        if (!ap_configuration)  /* QCI not supported */
-               return 1;
+               /* only ids 0...3F may be probed */
+               return id < 0x40 ? 1 : 0;
        return ap_test_config(ap_configuration->apm, id);
 }
 
index dcbf5c8..ed8e58f 100644 (file)
@@ -89,8 +89,8 @@ static int register_sba(struct ism_dev *ism)
        dma_addr_t dma_handle;
        struct ism_sba *sba;
 
-       sba = dma_zalloc_coherent(&ism->pdev->dev, PAGE_SIZE,
-                                 &dma_handle, GFP_KERNEL);
+       sba = dma_alloc_coherent(&ism->pdev->dev, PAGE_SIZE, &dma_handle,
+                                GFP_KERNEL);
        if (!sba)
                return -ENOMEM;
 
@@ -116,8 +116,8 @@ static int register_ieq(struct ism_dev *ism)
        dma_addr_t dma_handle;
        struct ism_eq *ieq;
 
-       ieq = dma_zalloc_coherent(&ism->pdev->dev, PAGE_SIZE,
-                                 &dma_handle, GFP_KERNEL);
+       ieq = dma_alloc_coherent(&ism->pdev->dev, PAGE_SIZE, &dma_handle,
+                                GFP_KERNEL);
        if (!ieq)
                return -ENOMEM;
 
@@ -234,10 +234,9 @@ static int ism_alloc_dmb(struct ism_dev *ism, struct smcd_dmb *dmb)
            test_and_set_bit(dmb->sba_idx, ism->sba_bitmap))
                return -EINVAL;
 
-       dmb->cpu_addr = dma_zalloc_coherent(&ism->pdev->dev, dmb->dmb_len,
-                                           &dmb->dma_addr, GFP_KERNEL |
-                                           __GFP_NOWARN | __GFP_NOMEMALLOC |
-                                           __GFP_COMP | __GFP_NORETRY);
+       dmb->cpu_addr = dma_alloc_coherent(&ism->pdev->dev, dmb->dmb_len,
+                                          &dmb->dma_addr,
+                                          GFP_KERNEL | __GFP_NOWARN | __GFP_NOMEMALLOC | __GFP_COMP | __GFP_NORETRY);
        if (!dmb->cpu_addr)
                clear_bit(dmb->sba_idx, ism->sba_bitmap);
 
index 0ee0269..122059e 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/hashtable.h>
 #include <linux/ip.h>
 #include <linux/refcount.h>
+#include <linux/workqueue.h>
 
 #include <net/ipv6.h>
 #include <net/if_inet6.h>
@@ -789,6 +790,7 @@ struct qeth_card {
        struct qeth_seqno seqno;
        struct qeth_card_options options;
 
+       struct workqueue_struct *event_wq;
        wait_queue_head_t wait_q;
        spinlock_t mclock;
        unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
@@ -962,7 +964,6 @@ extern const struct attribute_group *qeth_osn_attr_groups[];
 extern const struct attribute_group qeth_device_attr_group;
 extern const struct attribute_group qeth_device_blkt_group;
 extern const struct device_type qeth_generic_devtype;
-extern struct workqueue_struct *qeth_wq;
 
 int qeth_card_hw_is_reachable(struct qeth_card *);
 const char *qeth_get_cardname_short(struct qeth_card *);
index e63e031..89f9122 100644 (file)
@@ -74,8 +74,7 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *queue,
 static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf);
 static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int);
 
-struct workqueue_struct *qeth_wq;
-EXPORT_SYMBOL_GPL(qeth_wq);
+static struct workqueue_struct *qeth_wq;
 
 int qeth_card_hw_is_reachable(struct qeth_card *card)
 {
@@ -566,6 +565,7 @@ static int __qeth_issue_next_read(struct qeth_card *card)
                QETH_DBF_MESSAGE(2, "error %i on device %x when starting next read ccw!\n",
                                 rc, CARD_DEVID(card));
                atomic_set(&channel->irq_pending, 0);
+               qeth_release_buffer(channel, iob);
                card->read_or_write_problem = 1;
                qeth_schedule_recovery(card);
                wake_up(&card->wait_q);
@@ -1127,6 +1127,8 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
                rc = qeth_get_problem(card, cdev, irb);
                if (rc) {
                        card->read_or_write_problem = 1;
+                       if (iob)
+                               qeth_release_buffer(iob->channel, iob);
                        qeth_clear_ipacmd_list(card);
                        qeth_schedule_recovery(card);
                        goto out;
@@ -1466,6 +1468,10 @@ static struct qeth_card *qeth_alloc_card(struct ccwgroup_device *gdev)
        CARD_RDEV(card) = gdev->cdev[0];
        CARD_WDEV(card) = gdev->cdev[1];
        CARD_DDEV(card) = gdev->cdev[2];
+
+       card->event_wq = alloc_ordered_workqueue("%s", 0, dev_name(&gdev->dev));
+       if (!card->event_wq)
+               goto out_wq;
        if (qeth_setup_channel(&card->read, true))
                goto out_ip;
        if (qeth_setup_channel(&card->write, true))
@@ -1481,6 +1487,8 @@ out_data:
 out_channel:
        qeth_clean_channel(&card->read);
 out_ip:
+       destroy_workqueue(card->event_wq);
+out_wq:
        dev_set_drvdata(&gdev->dev, NULL);
        kfree(card);
 out:
@@ -1809,6 +1817,7 @@ static int qeth_idx_activate_get_answer(struct qeth_card *card,
                QETH_DBF_MESSAGE(2, "Error2 in activating channel rc=%d\n", rc);
                QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
                atomic_set(&channel->irq_pending, 0);
+               qeth_release_buffer(channel, iob);
                wake_up(&card->wait_q);
                return rc;
        }
@@ -1878,6 +1887,7 @@ static int qeth_idx_activate_channel(struct qeth_card *card,
                        rc);
                QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
                atomic_set(&channel->irq_pending, 0);
+               qeth_release_buffer(channel, iob);
                wake_up(&card->wait_q);
                return rc;
        }
@@ -2058,6 +2068,7 @@ int qeth_send_control_data(struct qeth_card *card, int len,
        }
        reply = qeth_alloc_reply(card);
        if (!reply) {
+               qeth_release_buffer(channel, iob);
                return -ENOMEM;
        }
        reply->callback = reply_cb;
@@ -2389,11 +2400,12 @@ static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *q, int bidx)
        return 0;
 }
 
-static void qeth_free_qdio_out_buf(struct qeth_qdio_out_q *q)
+static void qeth_free_output_queue(struct qeth_qdio_out_q *q)
 {
        if (!q)
                return;
 
+       qeth_clear_outq_buffers(q, 1);
        qdio_free_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q);
        kfree(q);
 }
@@ -2467,10 +2479,8 @@ out_freeoutqbufs:
                card->qdio.out_qs[i]->bufs[j] = NULL;
        }
 out_freeoutq:
-       while (i > 0) {
-               qeth_free_qdio_out_buf(card->qdio.out_qs[--i]);
-               qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
-       }
+       while (i > 0)
+               qeth_free_output_queue(card->qdio.out_qs[--i]);
        kfree(card->qdio.out_qs);
        card->qdio.out_qs = NULL;
 out_freepool:
@@ -2503,10 +2513,8 @@ static void qeth_free_qdio_buffers(struct qeth_card *card)
        qeth_free_buffer_pool(card);
        /* free outbound qdio_qs */
        if (card->qdio.out_qs) {
-               for (i = 0; i < card->qdio.no_out_queues; ++i) {
-                       qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
-                       qeth_free_qdio_out_buf(card->qdio.out_qs[i]);
-               }
+               for (i = 0; i < card->qdio.no_out_queues; i++)
+                       qeth_free_output_queue(card->qdio.out_qs[i]);
                kfree(card->qdio.out_qs);
                card->qdio.out_qs = NULL;
        }
@@ -5028,6 +5036,7 @@ static void qeth_core_free_card(struct qeth_card *card)
        qeth_clean_channel(&card->read);
        qeth_clean_channel(&card->write);
        qeth_clean_channel(&card->data);
+       destroy_workqueue(card->event_wq);
        qeth_free_qdio_buffers(card);
        unregister_service_level(&card->qeth_service_level);
        dev_set_drvdata(&card->gdev->dev, NULL);
index f108d4b..a43de2f 100644 (file)
@@ -369,6 +369,8 @@ static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
                qeth_clear_cmd_buffers(&card->read);
                qeth_clear_cmd_buffers(&card->write);
        }
+
+       flush_workqueue(card->event_wq);
 }
 
 static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
@@ -801,6 +803,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
 
        if (cgdev->state == CCWGROUP_ONLINE)
                qeth_l2_set_offline(cgdev);
+
+       cancel_work_sync(&card->close_dev_work);
        if (qeth_netdev_is_registered(card->dev))
                unregister_netdev(card->dev);
 }
@@ -1434,7 +1438,7 @@ static void qeth_bridge_state_change(struct qeth_card *card,
        data->card = card;
        memcpy(&data->qports, qports,
                        sizeof(struct qeth_sbp_state_change) + extrasize);
-       queue_work(qeth_wq, &data->worker);
+       queue_work(card->event_wq, &data->worker);
 }
 
 struct qeth_bridge_host_data {
@@ -1506,7 +1510,7 @@ static void qeth_bridge_host_event(struct qeth_card *card,
        data->card = card;
        memcpy(&data->hostevs, hostevs,
                        sizeof(struct qeth_ipacmd_addr_change) + extrasize);
-       queue_work(qeth_wq, &data->worker);
+       queue_work(card->event_wq, &data->worker);
 }
 
 /* SETBRIDGEPORT support; sending commands */
index 42a7cdc..df34bff 100644 (file)
@@ -1433,6 +1433,8 @@ static void qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
                qeth_clear_cmd_buffers(&card->read);
                qeth_clear_cmd_buffers(&card->write);
        }
+
+       flush_workqueue(card->event_wq);
 }
 
 /*
@@ -2338,6 +2340,7 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev)
        if (cgdev->state == CCWGROUP_ONLINE)
                qeth_l3_set_offline(cgdev);
 
+       cancel_work_sync(&card->close_dev_work);
        if (qeth_netdev_is_registered(card->dev))
                unregister_netdev(card->dev);
        qeth_l3_clear_ip_htable(card, 0);
index 9cf30d1..e390f8c 100644 (file)
@@ -403,7 +403,6 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
                goto failed;
 
        /* report size limit per scatter-gather segment */
-       adapter->dma_parms.max_segment_size = ZFCP_QDIO_SBALE_LEN;
        adapter->ccw_device->dev.dma_parms = &adapter->dma_parms;
 
        adapter->stat_read_buf_num = FSF_STATUS_READS_RECOM;
index 00acc71..f4f6a07 100644 (file)
@@ -428,6 +428,8 @@ static struct scsi_host_template zfcp_scsi_host_template = {
        .max_sectors             = (((QDIO_MAX_ELEMENTS_PER_BUFFER - 1)
                                     * ZFCP_QDIO_MAX_SBALS_PER_REQ) - 2) * 8,
                                   /* GCD, adjusted later */
+       /* report size limit per scatter-gather segment */
+       .max_segment_size        = ZFCP_QDIO_SBALE_LEN,
        .dma_boundary            = ZFCP_QDIO_SBALE_LEN - 1,
        .shost_attrs             = zfcp_sysfs_shost_attrs,
        .sdev_attrs              = zfcp_sysfs_sdev_attrs,
index fc9dbad..ae1d56d 100644 (file)
@@ -635,7 +635,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 {
        struct virtio_ccw_device *vcdev = to_vc_device(vdev);
        unsigned long *indicatorp = NULL;
-       int ret, i;
+       int ret, i, queue_idx = 0;
        struct ccw1 *ccw;
 
        ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL);
@@ -643,8 +643,14 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
                return -ENOMEM;
 
        for (i = 0; i < nvqs; ++i) {
-               vqs[i] = virtio_ccw_setup_vq(vdev, i, callbacks[i], names[i],
-                                            ctx ? ctx[i] : false, ccw);
+               if (!names[i]) {
+                       vqs[i] = NULL;
+                       continue;
+               }
+
+               vqs[i] = virtio_ccw_setup_vq(vdev, queue_idx++, callbacks[i],
+                                            names[i], ctx ? ctx[i] : false,
+                                            ccw);
                if (IS_ERR(vqs[i])) {
                        ret = PTR_ERR(vqs[i]);
                        vqs[i] = NULL;
index e8f5f7c..cd09610 100644 (file)
@@ -646,8 +646,9 @@ static int twl_allocate_memory(TW_Device_Extension *tw_dev, int size, int which)
        unsigned long *cpu_addr;
        int retval = 1;
 
-       cpu_addr = dma_zalloc_coherent(&tw_dev->tw_pci_dev->dev,
-                       size * TW_Q_LENGTH, &dma_handle, GFP_KERNEL);
+       cpu_addr = dma_alloc_coherent(&tw_dev->tw_pci_dev->dev,
+                                     size * TW_Q_LENGTH, &dma_handle,
+                                     GFP_KERNEL);
        if (!cpu_addr) {
                TW_PRINTK(tw_dev->host, TW_DRIVER, 0x5, "Memory allocation failed");
                goto out;
index 128d658..16957d7 100644 (file)
@@ -295,7 +295,7 @@ NCR_700_detect(struct scsi_host_template *tpnt,
        if(tpnt->sdev_attrs == NULL)
                tpnt->sdev_attrs = NCR_700_dev_attrs;
 
-       memory = dma_alloc_attrs(hostdata->dev, TOTAL_MEM_SIZE, &pScript,
+       memory = dma_alloc_attrs(dev, TOTAL_MEM_SIZE, &pScript,
                                 GFP_KERNEL, DMA_ATTR_NON_CONSISTENT);
        if(memory == NULL) {
                printk(KERN_ERR "53c700: Failed to allocate memory for driver, detaching\n");
index ff53fd0..66c5143 100644 (file)
@@ -1123,8 +1123,8 @@ static int inia100_probe_one(struct pci_dev *pdev,
 
        /* Get total memory needed for SCB */
        sz = ORC_MAXQUEUE * sizeof(struct orc_scb);
-       host->scb_virt = dma_zalloc_coherent(&pdev->dev, sz, &host->scb_phys,
-                                            GFP_KERNEL);
+       host->scb_virt = dma_alloc_coherent(&pdev->dev, sz, &host->scb_phys,
+                                           GFP_KERNEL);
        if (!host->scb_virt) {
                printk("inia100: SCB memory allocation error\n");
                goto out_host_put;
@@ -1132,8 +1132,8 @@ static int inia100_probe_one(struct pci_dev *pdev,
 
        /* Get total memory needed for ESCB */
        sz = ORC_MAXQUEUE * sizeof(struct orc_extended_scb);
-       host->escb_virt = dma_zalloc_coherent(&pdev->dev, sz, &host->escb_phys,
-                                             GFP_KERNEL);
+       host->escb_virt = dma_alloc_coherent(&pdev->dev, sz, &host->escb_phys,
+                                            GFP_KERNEL);
        if (!host->escb_virt) {
                printk("inia100: ESCB memory allocation error\n");
                goto out_free_scb_array;
index 634ddb9..7e56a11 100644 (file)
@@ -1747,11 +1747,10 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
                shost->max_sectors = (shost->sg_tablesize * 8) + 112;
        }
 
-       error = dma_set_max_seg_size(&pdev->dev,
-               (aac->adapter_info.options & AAC_OPT_NEW_COMM) ?
-                       (shost->max_sectors << 9) : 65536);
-       if (error)
-               goto out_deinit;
+       if (aac->adapter_info.options & AAC_OPT_NEW_COMM)
+               shost->max_segment_size = shost->max_sectors << 9;
+       else
+               shost->max_segment_size = 65536;
 
        /*
         * Firmware printf works only with older firmware.
index f83f79b..07efcb9 100644 (file)
@@ -280,7 +280,7 @@ static ssize_t asd_show_dev_rev(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%s\n",
                        asd_dev_rev[asd_ha->revision_id]);
 }
-static DEVICE_ATTR(revision, S_IRUGO, asd_show_dev_rev, NULL);
+static DEVICE_ATTR(aic_revision, S_IRUGO, asd_show_dev_rev, NULL);
 
 static ssize_t asd_show_dev_bios_build(struct device *dev,
                                       struct device_attribute *attr,char *buf)
@@ -477,7 +477,7 @@ static int asd_create_dev_attrs(struct asd_ha_struct *asd_ha)
 {
        int err;
 
-       err = device_create_file(&asd_ha->pcidev->dev, &dev_attr_revision);
+       err = device_create_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision);
        if (err)
                return err;
 
@@ -499,13 +499,13 @@ err_update_bios:
 err_biosb:
        device_remove_file(&asd_ha->pcidev->dev, &dev_attr_bios_build);
 err_rev:
-       device_remove_file(&asd_ha->pcidev->dev, &dev_attr_revision);
+       device_remove_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision);
        return err;
 }
 
 static void asd_remove_dev_attrs(struct asd_ha_struct *asd_ha)
 {
-       device_remove_file(&asd_ha->pcidev->dev, &dev_attr_revision);
+       device_remove_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision);
        device_remove_file(&asd_ha->pcidev->dev, &dev_attr_bios_build);
        device_remove_file(&asd_ha->pcidev->dev, &dev_attr_pcba_sn);
        device_remove_file(&asd_ha->pcidev->dev, &dev_attr_update_bios);
index 0f6751b..57c6fa3 100644 (file)
@@ -587,8 +587,10 @@ static bool arcmsr_alloc_io_queue(struct AdapterControlBlock *acb)
        case ACB_ADAPTER_TYPE_B: {
                struct MessageUnit_B *reg;
                acb->roundup_ccbsize = roundup(sizeof(struct MessageUnit_B), 32);
-               dma_coherent = dma_zalloc_coherent(&pdev->dev, acb->roundup_ccbsize,
-                       &dma_coherent_handle, GFP_KERNEL);
+               dma_coherent = dma_alloc_coherent(&pdev->dev,
+                                                 acb->roundup_ccbsize,
+                                                 &dma_coherent_handle,
+                                                 GFP_KERNEL);
                if (!dma_coherent) {
                        pr_notice("arcmsr%d: DMA allocation failed\n", acb->host->host_no);
                        return false;
@@ -617,8 +619,10 @@ static bool arcmsr_alloc_io_queue(struct AdapterControlBlock *acb)
                struct MessageUnit_D *reg;
 
                acb->roundup_ccbsize = roundup(sizeof(struct MessageUnit_D), 32);
-               dma_coherent = dma_zalloc_coherent(&pdev->dev, acb->roundup_ccbsize,
-                       &dma_coherent_handle, GFP_KERNEL);
+               dma_coherent = dma_alloc_coherent(&pdev->dev,
+                                                 acb->roundup_ccbsize,
+                                                 &dma_coherent_handle,
+                                                 GFP_KERNEL);
                if (!dma_coherent) {
                        pr_notice("arcmsr%d: DMA allocation failed\n", acb->host->host_no);
                        return false;
@@ -659,8 +663,10 @@ static bool arcmsr_alloc_io_queue(struct AdapterControlBlock *acb)
                uint32_t completeQ_size;
                completeQ_size = sizeof(struct deliver_completeQ) * ARCMSR_MAX_HBE_DONEQUEUE + 128;
                acb->roundup_ccbsize = roundup(completeQ_size, 32);
-               dma_coherent = dma_zalloc_coherent(&pdev->dev, acb->roundup_ccbsize,
-                       &dma_coherent_handle, GFP_KERNEL);
+               dma_coherent = dma_alloc_coherent(&pdev->dev,
+                                                 acb->roundup_ccbsize,
+                                                 &dma_coherent_handle,
+                                                 GFP_KERNEL);
                if (!dma_coherent){
                        pr_notice("arcmsr%d: DMA allocation failed\n", acb->host->host_no);
                        return false;
index 39f3820..74e2600 100644 (file)
@@ -3321,8 +3321,8 @@ static int be_queue_alloc(struct beiscsi_hba *phba, struct be_queue_info *q,
        q->len = len;
        q->entry_size = entry_size;
        mem->size = len * entry_size;
-       mem->va = dma_zalloc_coherent(&phba->pcidev->dev, mem->size, &mem->dma,
-                       GFP_KERNEL);
+       mem->va = dma_alloc_coherent(&phba->pcidev->dev, mem->size, &mem->dma,
+                                    GFP_KERNEL);
        if (!mem->va)
                return -ENOMEM;
        return 0;
index ca7b7bb..d4febaa 100644 (file)
@@ -293,8 +293,8 @@ static int beiscsi_prep_nemb_cmd(struct beiscsi_hba *phba,
                                 struct be_dma_mem *cmd,
                                 u8 subsystem, u8 opcode, u32 size)
 {
-       cmd->va = dma_zalloc_coherent(&phba->ctrl.pdev->dev, size, &cmd->dma,
-                       GFP_KERNEL);
+       cmd->va = dma_alloc_coherent(&phba->ctrl.pdev->dev, size, &cmd->dma,
+                                    GFP_KERNEL);
        if (!cmd->va) {
                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
                            "BG_%d : Failed to allocate memory for if info\n");
@@ -1510,10 +1510,9 @@ int beiscsi_mgmt_invalidate_icds(struct beiscsi_hba *phba,
                return -EINVAL;
 
        nonemb_cmd.size = sizeof(union be_invldt_cmds_params);
-       nonemb_cmd.va = dma_zalloc_coherent(&phba->ctrl.pdev->dev,
-                                             nonemb_cmd.size,
-                                             &nonemb_cmd.dma,
-                                             GFP_KERNEL);
+       nonemb_cmd.va = dma_alloc_coherent(&phba->ctrl.pdev->dev,
+                                          nonemb_cmd.size, &nonemb_cmd.dma,
+                                          GFP_KERNEL);
        if (!nonemb_cmd.va) {
                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH,
                            "BM_%d : invldt_cmds_params alloc failed\n");
index 5d163ca..d8e6d74 100644 (file)
@@ -3264,9 +3264,9 @@ bfad_fcxp_map_sg(struct bfad_s *bfad, void *payload_kbuf,
        /* Allocate dma coherent memory */
        buf_info = buf_base;
        buf_info->size = payload_len;
-       buf_info->virt = dma_zalloc_coherent(&bfad->pcidev->dev,
-                                            buf_info->size, &buf_info->phys,
-                                            GFP_KERNEL);
+       buf_info->virt = dma_alloc_coherent(&bfad->pcidev->dev,
+                                           buf_info->size, &buf_info->phys,
+                                           GFP_KERNEL);
        if (!buf_info->virt)
                goto out_free_mem;
 
index e8ae4d6..039328d 100644 (file)
@@ -1857,10 +1857,10 @@ int bnx2fc_setup_task_ctx(struct bnx2fc_hba *hba)
         * entries. Hence the limit with one page is 8192 task context
         * entries.
         */
-       hba->task_ctx_bd_tbl = dma_zalloc_coherent(&hba->pcidev->dev,
-                                                  PAGE_SIZE,
-                                                  &hba->task_ctx_bd_dma,
-                                                  GFP_KERNEL);
+       hba->task_ctx_bd_tbl = dma_alloc_coherent(&hba->pcidev->dev,
+                                                 PAGE_SIZE,
+                                                 &hba->task_ctx_bd_dma,
+                                                 GFP_KERNEL);
        if (!hba->task_ctx_bd_tbl) {
                printk(KERN_ERR PFX "unable to allocate task context BDT\n");
                rc = -1;
@@ -1894,10 +1894,10 @@ int bnx2fc_setup_task_ctx(struct bnx2fc_hba *hba)
        task_ctx_bdt = (struct regpair *)hba->task_ctx_bd_tbl;
        for (i = 0; i < task_ctx_arr_sz; i++) {
 
-               hba->task_ctx[i] = dma_zalloc_coherent(&hba->pcidev->dev,
-                                                      PAGE_SIZE,
-                                                      &hba->task_ctx_dma[i],
-                                                      GFP_KERNEL);
+               hba->task_ctx[i] = dma_alloc_coherent(&hba->pcidev->dev,
+                                                     PAGE_SIZE,
+                                                     &hba->task_ctx_dma[i],
+                                                     GFP_KERNEL);
                if (!hba->task_ctx[i]) {
                        printk(KERN_ERR PFX "unable to alloc task context\n");
                        rc = -1;
@@ -2031,19 +2031,19 @@ static int bnx2fc_allocate_hash_table(struct bnx2fc_hba *hba)
        }
 
        for (i = 0; i < segment_count; ++i) {
-               hba->hash_tbl_segments[i] = dma_zalloc_coherent(&hba->pcidev->dev,
-                                                               BNX2FC_HASH_TBL_CHUNK_SIZE,
-                                                               &dma_segment_array[i],
-                                                               GFP_KERNEL);
+               hba->hash_tbl_segments[i] = dma_alloc_coherent(&hba->pcidev->dev,
+                                                              BNX2FC_HASH_TBL_CHUNK_SIZE,
+                                                              &dma_segment_array[i],
+                                                              GFP_KERNEL);
                if (!hba->hash_tbl_segments[i]) {
                        printk(KERN_ERR PFX "hash segment alloc failed\n");
                        goto cleanup_dma;
                }
        }
 
-       hba->hash_tbl_pbl = dma_zalloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
-                                               &hba->hash_tbl_pbl_dma,
-                                               GFP_KERNEL);
+       hba->hash_tbl_pbl = dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
+                                              &hba->hash_tbl_pbl_dma,
+                                              GFP_KERNEL);
        if (!hba->hash_tbl_pbl) {
                printk(KERN_ERR PFX "hash table pbl alloc failed\n");
                goto cleanup_dma;
@@ -2104,10 +2104,9 @@ int bnx2fc_setup_fw_resc(struct bnx2fc_hba *hba)
                return -ENOMEM;
 
        mem_size = BNX2FC_NUM_MAX_SESS * sizeof(struct regpair);
-       hba->t2_hash_tbl_ptr = dma_zalloc_coherent(&hba->pcidev->dev,
-                                                  mem_size,
-                                                  &hba->t2_hash_tbl_ptr_dma,
-                                                  GFP_KERNEL);
+       hba->t2_hash_tbl_ptr = dma_alloc_coherent(&hba->pcidev->dev, mem_size,
+                                                 &hba->t2_hash_tbl_ptr_dma,
+                                                 GFP_KERNEL);
        if (!hba->t2_hash_tbl_ptr) {
                printk(KERN_ERR PFX "unable to allocate t2 hash table ptr\n");
                bnx2fc_free_fw_resc(hba);
@@ -2116,9 +2115,9 @@ int bnx2fc_setup_fw_resc(struct bnx2fc_hba *hba)
 
        mem_size = BNX2FC_NUM_MAX_SESS *
                                sizeof(struct fcoe_t2_hash_table_entry);
-       hba->t2_hash_tbl = dma_zalloc_coherent(&hba->pcidev->dev, mem_size,
-                                              &hba->t2_hash_tbl_dma,
-                                              GFP_KERNEL);
+       hba->t2_hash_tbl = dma_alloc_coherent(&hba->pcidev->dev, mem_size,
+                                             &hba->t2_hash_tbl_dma,
+                                             GFP_KERNEL);
        if (!hba->t2_hash_tbl) {
                printk(KERN_ERR PFX "unable to allocate t2 hash table\n");
                bnx2fc_free_fw_resc(hba);
@@ -2140,9 +2139,9 @@ int bnx2fc_setup_fw_resc(struct bnx2fc_hba *hba)
                return -ENOMEM;
        }
 
-       hba->stats_buffer = dma_zalloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
-                                               &hba->stats_buf_dma,
-                                               GFP_KERNEL);
+       hba->stats_buffer = dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
+                                              &hba->stats_buf_dma,
+                                              GFP_KERNEL);
        if (!hba->stats_buffer) {
                printk(KERN_ERR PFX "unable to alloc Stats Buffer\n");
                bnx2fc_free_fw_resc(hba);
index 350257c..bc9f2a2 100644 (file)
@@ -240,6 +240,7 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba)
                return NULL;
        }
 
+       cmgr->hba = hba;
        cmgr->free_list = kcalloc(arr_sz, sizeof(*cmgr->free_list),
                                  GFP_KERNEL);
        if (!cmgr->free_list) {
@@ -256,7 +257,6 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba)
                goto mem_err;
        }
 
-       cmgr->hba = hba;
        cmgr->cmds = (struct bnx2fc_cmd **)(cmgr + 1);
 
        for (i = 0; i < arr_sz; i++)  {
@@ -295,7 +295,7 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba)
 
        /* Allocate pool of io_bdts - one for each bnx2fc_cmd */
        mem_size = num_ios * sizeof(struct io_bdt *);
-       cmgr->io_bdt_pool = kmalloc(mem_size, GFP_KERNEL);
+       cmgr->io_bdt_pool = kzalloc(mem_size, GFP_KERNEL);
        if (!cmgr->io_bdt_pool) {
                printk(KERN_ERR PFX "failed to alloc io_bdt_pool\n");
                goto mem_err;
index e3d1c7c..d735e87 100644 (file)
@@ -672,8 +672,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->sq_mem_size = (tgt->sq_mem_size + (CNIC_PAGE_SIZE - 1)) &
                           CNIC_PAGE_MASK;
 
-       tgt->sq = dma_zalloc_coherent(&hba->pcidev->dev, tgt->sq_mem_size,
-                                     &tgt->sq_dma, GFP_KERNEL);
+       tgt->sq = dma_alloc_coherent(&hba->pcidev->dev, tgt->sq_mem_size,
+                                    &tgt->sq_dma, GFP_KERNEL);
        if (!tgt->sq) {
                printk(KERN_ERR PFX "unable to allocate SQ memory %d\n",
                        tgt->sq_mem_size);
@@ -685,8 +685,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->cq_mem_size = (tgt->cq_mem_size + (CNIC_PAGE_SIZE - 1)) &
                           CNIC_PAGE_MASK;
 
-       tgt->cq = dma_zalloc_coherent(&hba->pcidev->dev, tgt->cq_mem_size,
-                                     &tgt->cq_dma, GFP_KERNEL);
+       tgt->cq = dma_alloc_coherent(&hba->pcidev->dev, tgt->cq_mem_size,
+                                    &tgt->cq_dma, GFP_KERNEL);
        if (!tgt->cq) {
                printk(KERN_ERR PFX "unable to allocate CQ memory %d\n",
                        tgt->cq_mem_size);
@@ -698,8 +698,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->rq_mem_size = (tgt->rq_mem_size + (CNIC_PAGE_SIZE - 1)) &
                           CNIC_PAGE_MASK;
 
-       tgt->rq = dma_zalloc_coherent(&hba->pcidev->dev, tgt->rq_mem_size,
-                                     &tgt->rq_dma, GFP_KERNEL);
+       tgt->rq = dma_alloc_coherent(&hba->pcidev->dev, tgt->rq_mem_size,
+                                    &tgt->rq_dma, GFP_KERNEL);
        if (!tgt->rq) {
                printk(KERN_ERR PFX "unable to allocate RQ memory %d\n",
                        tgt->rq_mem_size);
@@ -710,8 +710,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->rq_pbl_size = (tgt->rq_pbl_size + (CNIC_PAGE_SIZE - 1)) &
                           CNIC_PAGE_MASK;
 
-       tgt->rq_pbl = dma_zalloc_coherent(&hba->pcidev->dev, tgt->rq_pbl_size,
-                                         &tgt->rq_pbl_dma, GFP_KERNEL);
+       tgt->rq_pbl = dma_alloc_coherent(&hba->pcidev->dev, tgt->rq_pbl_size,
+                                        &tgt->rq_pbl_dma, GFP_KERNEL);
        if (!tgt->rq_pbl) {
                printk(KERN_ERR PFX "unable to allocate RQ PBL %d\n",
                        tgt->rq_pbl_size);
@@ -735,9 +735,9 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->xferq_mem_size = (tgt->xferq_mem_size + (CNIC_PAGE_SIZE - 1)) &
                               CNIC_PAGE_MASK;
 
-       tgt->xferq = dma_zalloc_coherent(&hba->pcidev->dev,
-                                        tgt->xferq_mem_size, &tgt->xferq_dma,
-                                        GFP_KERNEL);
+       tgt->xferq = dma_alloc_coherent(&hba->pcidev->dev,
+                                       tgt->xferq_mem_size, &tgt->xferq_dma,
+                                       GFP_KERNEL);
        if (!tgt->xferq) {
                printk(KERN_ERR PFX "unable to allocate XFERQ %d\n",
                        tgt->xferq_mem_size);
@@ -749,9 +749,9 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->confq_mem_size = (tgt->confq_mem_size + (CNIC_PAGE_SIZE - 1)) &
                               CNIC_PAGE_MASK;
 
-       tgt->confq = dma_zalloc_coherent(&hba->pcidev->dev,
-                                        tgt->confq_mem_size, &tgt->confq_dma,
-                                        GFP_KERNEL);
+       tgt->confq = dma_alloc_coherent(&hba->pcidev->dev,
+                                       tgt->confq_mem_size, &tgt->confq_dma,
+                                       GFP_KERNEL);
        if (!tgt->confq) {
                printk(KERN_ERR PFX "unable to allocate CONFQ %d\n",
                        tgt->confq_mem_size);
@@ -763,9 +763,9 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->confq_pbl_size =
                (tgt->confq_pbl_size + (CNIC_PAGE_SIZE - 1)) & CNIC_PAGE_MASK;
 
-       tgt->confq_pbl = dma_zalloc_coherent(&hba->pcidev->dev,
-                                            tgt->confq_pbl_size,
-                                            &tgt->confq_pbl_dma, GFP_KERNEL);
+       tgt->confq_pbl = dma_alloc_coherent(&hba->pcidev->dev,
+                                           tgt->confq_pbl_size,
+                                           &tgt->confq_pbl_dma, GFP_KERNEL);
        if (!tgt->confq_pbl) {
                printk(KERN_ERR PFX "unable to allocate CONFQ PBL %d\n",
                        tgt->confq_pbl_size);
@@ -787,9 +787,9 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        /* Allocate and map ConnDB */
        tgt->conn_db_mem_size = sizeof(struct fcoe_conn_db);
 
-       tgt->conn_db = dma_zalloc_coherent(&hba->pcidev->dev,
-                                          tgt->conn_db_mem_size,
-                                          &tgt->conn_db_dma, GFP_KERNEL);
+       tgt->conn_db = dma_alloc_coherent(&hba->pcidev->dev,
+                                         tgt->conn_db_mem_size,
+                                         &tgt->conn_db_dma, GFP_KERNEL);
        if (!tgt->conn_db) {
                printk(KERN_ERR PFX "unable to allocate conn_db %d\n",
                                                tgt->conn_db_mem_size);
@@ -802,8 +802,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->lcq_mem_size = (tgt->lcq_mem_size + (CNIC_PAGE_SIZE - 1)) &
                             CNIC_PAGE_MASK;
 
-       tgt->lcq = dma_zalloc_coherent(&hba->pcidev->dev, tgt->lcq_mem_size,
-                                      &tgt->lcq_dma, GFP_KERNEL);
+       tgt->lcq = dma_alloc_coherent(&hba->pcidev->dev, tgt->lcq_mem_size,
+                                     &tgt->lcq_dma, GFP_KERNEL);
 
        if (!tgt->lcq) {
                printk(KERN_ERR PFX "unable to allocate lcq %d\n",
index 91f5316..fae6f71 100644 (file)
@@ -1070,8 +1070,8 @@ int bnx2i_alloc_qp_resc(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep)
 
        /* Allocate memory area for actual SQ element */
        ep->qp.sq_virt =
-               dma_zalloc_coherent(&hba->pcidev->dev, ep->qp.sq_mem_size,
-                                       &ep->qp.sq_phys, GFP_KERNEL);
+               dma_alloc_coherent(&hba->pcidev->dev, ep->qp.sq_mem_size,
+                                  &ep->qp.sq_phys, GFP_KERNEL);
        if (!ep->qp.sq_virt) {
                printk(KERN_ALERT "bnx2i: unable to alloc SQ BD memory %d\n",
                                  ep->qp.sq_mem_size);
@@ -1106,8 +1106,8 @@ int bnx2i_alloc_qp_resc(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep)
 
        /* Allocate memory area for actual CQ element */
        ep->qp.cq_virt =
-               dma_zalloc_coherent(&hba->pcidev->dev, ep->qp.cq_mem_size,
-                                       &ep->qp.cq_phys, GFP_KERNEL);
+               dma_alloc_coherent(&hba->pcidev->dev, ep->qp.cq_mem_size,
+                                  &ep->qp.cq_phys, GFP_KERNEL);
        if (!ep->qp.cq_virt) {
                printk(KERN_ALERT "bnx2i: unable to alloc CQ BD memory %d\n",
                                  ep->qp.cq_mem_size);
index 8a00403..9bd2bd8 100644 (file)
@@ -594,12 +594,12 @@ csio_vport_create(struct fc_vport *fc_vport, bool disable)
        }
 
        fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);
+       ln->fc_vport = fc_vport;
 
        if (csio_fcoe_alloc_vnp(hw, ln))
                goto error;
 
        *(struct csio_lnode **)fc_vport->dd_data = ln;
-       ln->fc_vport = fc_vport;
        if (!fc_vport->node_name)
                fc_vport->node_name = wwn_to_u64(csio_ln_wwnn(ln));
        if (!fc_vport->port_name)
index dc12933..66bbd21 100644 (file)
@@ -233,8 +233,8 @@ csio_wr_alloc_q(struct csio_hw *hw, uint32_t qsize, uint32_t wrsize,
 
        q = wrm->q_arr[free_idx];
 
-       q->vstart = dma_zalloc_coherent(&hw->pdev->dev, qsz, &q->pstart,
-                       GFP_KERNEL);
+       q->vstart = dma_alloc_coherent(&hw->pdev->dev, qsz, &q->pstart,
+                                      GFP_KERNEL);
        if (!q->vstart) {
                csio_err(hw,
                         "Failed to allocate DMA memory for "
index 8a20411..75e1273 100644 (file)
@@ -1144,7 +1144,7 @@ static void ddp_clear_map(struct cxgbi_device *cdev, struct cxgbi_ppm *ppm,
 }
 
 static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
-                                      unsigned int tid, int pg_idx, bool reply)
+                               unsigned int tid, int pg_idx)
 {
        struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0,
                                        GFP_KERNEL);
@@ -1160,7 +1160,7 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
        req = (struct cpl_set_tcb_field *)skb->head;
        req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
        OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
-       req->reply = V_NO_REPLY(reply ? 0 : 1);
+       req->reply = V_NO_REPLY(1);
        req->cpu_idx = 0;
        req->word = htons(31);
        req->mask = cpu_to_be64(0xF0000000);
@@ -1177,11 +1177,10 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
  * @tid: connection id
  * @hcrc: header digest enabled
  * @dcrc: data digest enabled
- * @reply: request reply from h/w
  * set up the iscsi digest settings for a connection identified by tid
  */
 static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
-                            int hcrc, int dcrc, int reply)
+                                int hcrc, int dcrc)
 {
        struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0,
                                        GFP_KERNEL);
@@ -1197,7 +1196,7 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
        req = (struct cpl_set_tcb_field *)skb->head;
        req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
        OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
-       req->reply = V_NO_REPLY(reply ? 0 : 1);
+       req->reply = V_NO_REPLY(1);
        req->cpu_idx = 0;
        req->word = htons(31);
        req->mask = cpu_to_be64(0x0F000000);
index 49f8028..d26f50a 100644 (file)
@@ -1548,16 +1548,22 @@ static void do_set_tcb_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
        struct cxgbi_sock *csk;
 
        csk = lookup_tid(t, tid);
-       if (!csk)
+       if (!csk) {
                pr_err("can't find conn. for tid %u.\n", tid);
+               return;
+       }
 
        log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
                "csk 0x%p,%u,%lx,%u, status 0x%x.\n",
                csk, csk->state, csk->flags, csk->tid, rpl->status);
 
-       if (rpl->status != CPL_ERR_NONE)
+       if (rpl->status != CPL_ERR_NONE) {
                pr_err("csk 0x%p,%u, SET_TCB_RPL status %u.\n",
                        csk, tid, rpl->status);
+               csk->err = -EINVAL;
+       }
+
+       complete(&csk->cmpl);
 
        __kfree_skb(skb);
 }
@@ -1983,7 +1989,7 @@ static int ddp_set_map(struct cxgbi_ppm *ppm, struct cxgbi_sock *csk,
 }
 
 static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
-                               int pg_idx, bool reply)
+                               int pg_idx)
 {
        struct sk_buff *skb;
        struct cpl_set_tcb_field *req;
@@ -1999,7 +2005,7 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
        req = (struct cpl_set_tcb_field *)skb->head;
        INIT_TP_WR(req, csk->tid);
        OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, csk->tid));
-       req->reply_ctrl = htons(NO_REPLY_V(reply) | QUEUENO_V(csk->rss_qid));
+       req->reply_ctrl = htons(NO_REPLY_V(0) | QUEUENO_V(csk->rss_qid));
        req->word_cookie = htons(0);
        req->mask = cpu_to_be64(0x3 << 8);
        req->val = cpu_to_be64(pg_idx << 8);
@@ -2008,12 +2014,15 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
        log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
                "csk 0x%p, tid 0x%x, pg_idx %u.\n", csk, csk->tid, pg_idx);
 
+       reinit_completion(&csk->cmpl);
        cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
-       return 0;
+       wait_for_completion(&csk->cmpl);
+
+       return csk->err;
 }
 
 static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
-                                int hcrc, int dcrc, int reply)
+                                int hcrc, int dcrc)
 {
        struct sk_buff *skb;
        struct cpl_set_tcb_field *req;
@@ -2031,7 +2040,7 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
        req = (struct cpl_set_tcb_field *)skb->head;
        INIT_TP_WR(req, tid);
        OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
-       req->reply_ctrl = htons(NO_REPLY_V(reply) | QUEUENO_V(csk->rss_qid));
+       req->reply_ctrl = htons(NO_REPLY_V(0) | QUEUENO_V(csk->rss_qid));
        req->word_cookie = htons(0);
        req->mask = cpu_to_be64(0x3 << 4);
        req->val = cpu_to_be64(((hcrc ? ULP_CRC_HEADER : 0) |
@@ -2041,8 +2050,11 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
        log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
                "csk 0x%p, tid 0x%x, crc %d,%d.\n", csk, csk->tid, hcrc, dcrc);
 
+       reinit_completion(&csk->cmpl);
        cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
-       return 0;
+       wait_for_completion(&csk->cmpl);
+
+       return csk->err;
 }
 
 static struct cxgbi_ppm *cdev2ppm(struct cxgbi_device *cdev)
index 75f8764..2457425 100644 (file)
@@ -573,6 +573,7 @@ static struct cxgbi_sock *cxgbi_sock_create(struct cxgbi_device *cdev)
        skb_queue_head_init(&csk->receive_queue);
        skb_queue_head_init(&csk->write_queue);
        timer_setup(&csk->retry_timer, NULL, 0);
+       init_completion(&csk->cmpl);
        rwlock_init(&csk->callback_lock);
        csk->cdev = cdev;
        csk->flags = 0;
@@ -2251,14 +2252,14 @@ int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn,
                if (!err && conn->hdrdgst_en)
                        err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid,
                                                        conn->hdrdgst_en,
-                                                       conn->datadgst_en, 0);
+                                                       conn->datadgst_en);
                break;
        case ISCSI_PARAM_DATADGST_EN:
                err = iscsi_set_param(cls_conn, param, buf, buflen);
                if (!err && conn->datadgst_en)
                        err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid,
                                                        conn->hdrdgst_en,
-                                                       conn->datadgst_en, 0);
+                                                       conn->datadgst_en);
                break;
        case ISCSI_PARAM_MAX_R2T:
                return iscsi_tcp_set_max_r2t(conn, buf);
@@ -2384,7 +2385,7 @@ int cxgbi_bind_conn(struct iscsi_cls_session *cls_session,
 
        ppm = csk->cdev->cdev2ppm(csk->cdev);
        err = csk->cdev->csk_ddp_setup_pgidx(csk, csk->tid,
-                                            ppm->tformat.pgsz_idx_dflt, 0);
+                                            ppm->tformat.pgsz_idx_dflt);
        if (err < 0)
                return err;
 
index 5d5d8b5..1917ff5 100644 (file)
@@ -149,6 +149,7 @@ struct cxgbi_sock {
        struct sk_buff_head receive_queue;
        struct sk_buff_head write_queue;
        struct timer_list retry_timer;
+       struct completion cmpl;
        int err;
        rwlock_t callback_lock;
        void *user_data;
@@ -490,9 +491,9 @@ struct cxgbi_device {
                                  struct cxgbi_ppm *,
                                  struct cxgbi_task_tag_info *);
        int (*csk_ddp_setup_digest)(struct cxgbi_sock *,
-                               unsigned int, int, int, int);
+                                   unsigned int, int, int);
        int (*csk_ddp_setup_pgidx)(struct cxgbi_sock *,
-                               unsigned int, int, bool);
+                                  unsigned int, int);
 
        void (*csk_release_offload_resources)(struct cxgbi_sock *);
        int (*csk_rx_pdu_ready)(struct cxgbi_sock *, struct sk_buff *);
index bfa13e3..c8bad2c 100644 (file)
@@ -3687,6 +3687,7 @@ static int cxlflash_probe(struct pci_dev *pdev,
        host->max_cmd_len = CXLFLASH_MAX_CDB_LEN;
 
        cfg = shost_priv(host);
+       cfg->state = STATE_PROBING;
        cfg->host = host;
        rc = alloc_mem(cfg);
        if (rc) {
@@ -3775,6 +3776,7 @@ out:
        return rc;
 
 out_remove:
+       cfg->state = STATE_PROBED;
        cxlflash_remove(pdev);
        goto out;
 }
index e2420a8..c92b382 100644 (file)
@@ -2507,6 +2507,12 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                sha->sas_port[i] = &hisi_hba->port[i].sas_port;
        }
 
+       if (hisi_hba->prot_mask) {
+               dev_info(dev, "Registering for DIF/DIX prot_mask=0x%x\n",
+                        prot_mask);
+               scsi_host_set_prot(hisi_hba->shost, prot_mask);
+       }
+
        rc = scsi_add_host(shost, dev);
        if (rc)
                goto err_out_ha;
@@ -2519,12 +2525,6 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (rc)
                goto err_out_register_ha;
 
-       if (hisi_hba->prot_mask) {
-               dev_info(dev, "Registering for DIF/DIX prot_mask=0x%x\n",
-                        prot_mask);
-               scsi_host_set_prot(hisi_hba->shost, prot_mask);
-       }
-
        scsi_scan_host(shost);
 
        return 0;
index 68b90c4..1727d0c 100644 (file)
@@ -576,6 +576,13 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
        shost->max_lun = ~0;
        shost->max_cmd_len = MAX_COMMAND_SIZE;
 
+       /* turn on DIF support */
+       scsi_host_set_prot(shost,
+                          SHOST_DIF_TYPE1_PROTECTION |
+                          SHOST_DIF_TYPE2_PROTECTION |
+                          SHOST_DIF_TYPE3_PROTECTION);
+       scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
+
        err = scsi_add_host(shost, &pdev->dev);
        if (err)
                goto err_shost;
@@ -663,13 +670,6 @@ static int isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                        goto err_host_alloc;
                }
                pci_info->hosts[i] = h;
-
-               /* turn on DIF support */
-               scsi_host_set_prot(to_shost(h),
-                                  SHOST_DIF_TYPE1_PROTECTION |
-                                  SHOST_DIF_TYPE2_PROTECTION |
-                                  SHOST_DIF_TYPE3_PROTECTION);
-               scsi_host_set_guard(to_shost(h), SHOST_DIX_GUARD_CRC);
        }
 
        err = isci_setup_interrupts(pdev);
index be83590..ff943f4 100644 (file)
@@ -1726,14 +1726,14 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
            fc_frame_payload_op(fp) != ELS_LS_ACC) {
                FC_LPORT_DBG(lport, "FLOGI not accepted or bad response\n");
                fc_lport_error(lport, fp);
-               goto err;
+               goto out;
        }
 
        flp = fc_frame_payload_get(fp, sizeof(*flp));
        if (!flp) {
                FC_LPORT_DBG(lport, "FLOGI bad response\n");
                fc_lport_error(lport, fp);
-               goto err;
+               goto out;
        }
 
        mfs = ntohs(flp->fl_csp.sp_bb_data) &
@@ -1743,7 +1743,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
                FC_LPORT_DBG(lport, "FLOGI bad mfs:%hu response, "
                             "lport->mfs:%hu\n", mfs, lport->mfs);
                fc_lport_error(lport, fp);
-               goto err;
+               goto out;
        }
 
        if (mfs <= lport->mfs) {
index 9192a1d..dfba492 100644 (file)
@@ -184,7 +184,6 @@ void fc_rport_destroy(struct kref *kref)
        struct fc_rport_priv *rdata;
 
        rdata = container_of(kref, struct fc_rport_priv, kref);
-       WARN_ON(!list_empty(&rdata->peers));
        kfree_rcu(rdata, rcu);
 }
 EXPORT_SYMBOL(fc_rport_destroy);
index 8698af8..2dc564e 100644 (file)
@@ -2730,8 +2730,8 @@ lpfc_bsg_dma_page_alloc(struct lpfc_hba *phba)
        INIT_LIST_HEAD(&dmabuf->list);
 
        /* now, allocate dma buffer */
-       dmabuf->virt = dma_zalloc_coherent(&pcidev->dev, BSG_MBOX_SIZE,
-                                          &(dmabuf->phys), GFP_KERNEL);
+       dmabuf->virt = dma_alloc_coherent(&pcidev->dev, BSG_MBOX_SIZE,
+                                         &(dmabuf->phys), GFP_KERNEL);
 
        if (!dmabuf->virt) {
                kfree(dmabuf);
index c1c3681..bede11e 100644 (file)
@@ -6973,9 +6973,9 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba)
        if (!dmabuf)
                return NULL;
 
-       dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev,
-                                          LPFC_HDR_TEMPLATE_SIZE,
-                                          &dmabuf->phys, GFP_KERNEL);
+       dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev,
+                                         LPFC_HDR_TEMPLATE_SIZE,
+                                         &dmabuf->phys, GFP_KERNEL);
        if (!dmabuf->virt) {
                rpi_hdr = NULL;
                goto err_free_dmabuf;
@@ -7397,8 +7397,8 @@ lpfc_sli_pci_mem_setup(struct lpfc_hba *phba)
        }
 
        /* Allocate memory for SLI-2 structures */
-       phba->slim2p.virt = dma_zalloc_coherent(&pdev->dev, SLI2_SLIM_SIZE,
-                                               &phba->slim2p.phys, GFP_KERNEL);
+       phba->slim2p.virt = dma_alloc_coherent(&pdev->dev, SLI2_SLIM_SIZE,
+                                              &phba->slim2p.phys, GFP_KERNEL);
        if (!phba->slim2p.virt)
                goto out_iounmap;
 
@@ -7816,8 +7816,8 @@ lpfc_create_bootstrap_mbox(struct lpfc_hba *phba)
         * plus an alignment restriction of 16 bytes.
         */
        bmbx_size = sizeof(struct lpfc_bmbx_create) + (LPFC_ALIGN_16_BYTE - 1);
-       dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev, bmbx_size,
-                                          &dmabuf->phys, GFP_KERNEL);
+       dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev, bmbx_size,
+                                         &dmabuf->phys, GFP_KERNEL);
        if (!dmabuf->virt) {
                kfree(dmabuf);
                return -ENOMEM;
index f6a5083..4d3b943 100644 (file)
@@ -1827,9 +1827,9 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox,
                 * page, this is used as a priori size of SLI4_PAGE_SIZE for
                 * the later DMA memory free.
                 */
-               viraddr = dma_zalloc_coherent(&phba->pcidev->dev,
-                                             SLI4_PAGE_SIZE, &phyaddr,
-                                             GFP_KERNEL);
+               viraddr = dma_alloc_coherent(&phba->pcidev->dev,
+                                            SLI4_PAGE_SIZE, &phyaddr,
+                                            GFP_KERNEL);
                /* In case of malloc fails, proceed with whatever we have */
                if (!viraddr)
                        break;
index 4c66b19..8c9f790 100644 (file)
@@ -297,7 +297,8 @@ lpfc_nvme_localport_delete(struct nvme_fc_local_port *localport)
                         lport);
 
        /* release any threads waiting for the unreg to complete */
-       complete(&lport->lport_unreg_done);
+       if (lport->vport->localport)
+               complete(lport->lport_unreg_cmp);
 }
 
 /* lpfc_nvme_remoteport_delete
@@ -2545,7 +2546,8 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport)
  */
 void
 lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport,
-                          struct lpfc_nvme_lport *lport)
+                          struct lpfc_nvme_lport *lport,
+                          struct completion *lport_unreg_cmp)
 {
 #if (IS_ENABLED(CONFIG_NVME_FC))
        u32 wait_tmo;
@@ -2557,8 +2559,7 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport,
         */
        wait_tmo = msecs_to_jiffies(LPFC_NVME_WAIT_TMO * 1000);
        while (true) {
-               ret = wait_for_completion_timeout(&lport->lport_unreg_done,
-                                                 wait_tmo);
+               ret = wait_for_completion_timeout(lport_unreg_cmp, wait_tmo);
                if (unlikely(!ret)) {
                        lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_IOERR,
                                         "6176 Lport %p Localport %p wait "
@@ -2592,12 +2593,12 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport)
        struct lpfc_nvme_lport *lport;
        struct lpfc_nvme_ctrl_stat *cstat;
        int ret;
+       DECLARE_COMPLETION_ONSTACK(lport_unreg_cmp);
 
        if (vport->nvmei_support == 0)
                return;
 
        localport = vport->localport;
-       vport->localport = NULL;
        lport = (struct lpfc_nvme_lport *)localport->private;
        cstat = lport->cstat;
 
@@ -2608,13 +2609,14 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport)
        /* lport's rport list is clear.  Unregister
         * lport and release resources.
         */
-       init_completion(&lport->lport_unreg_done);
+       lport->lport_unreg_cmp = &lport_unreg_cmp;
        ret = nvme_fc_unregister_localport(localport);
 
        /* Wait for completion.  This either blocks
         * indefinitely or succeeds
         */
-       lpfc_nvme_lport_unreg_wait(vport, lport);
+       lpfc_nvme_lport_unreg_wait(vport, lport, &lport_unreg_cmp);
+       vport->localport = NULL;
        kfree(cstat);
 
        /* Regardless of the unregister upcall response, clear
index cfd4719..b234d02 100644 (file)
@@ -50,7 +50,7 @@ struct lpfc_nvme_ctrl_stat {
 /* Declare nvme-based local and remote port definitions. */
 struct lpfc_nvme_lport {
        struct lpfc_vport *vport;
-       struct completion lport_unreg_done;
+       struct completion *lport_unreg_cmp;
        /* Add stats counters here */
        struct lpfc_nvme_ctrl_stat *cstat;
        atomic_t fc4NvmeLsRequests;
index 6245f44..95fee83 100644 (file)
@@ -1003,7 +1003,8 @@ lpfc_nvmet_targetport_delete(struct nvmet_fc_target_port *targetport)
        struct lpfc_nvmet_tgtport *tport = targetport->private;
 
        /* release any threads waiting for the unreg to complete */
-       complete(&tport->tport_unreg_done);
+       if (tport->phba->targetport)
+               complete(tport->tport_unreg_cmp);
 }
 
 static void
@@ -1692,6 +1693,7 @@ lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba)
        struct lpfc_nvmet_tgtport *tgtp;
        struct lpfc_queue *wq;
        uint32_t qidx;
+       DECLARE_COMPLETION_ONSTACK(tport_unreg_cmp);
 
        if (phba->nvmet_support == 0)
                return;
@@ -1701,9 +1703,9 @@ lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba)
                        wq = phba->sli4_hba.nvme_wq[qidx];
                        lpfc_nvmet_wqfull_flush(phba, wq, NULL);
                }
-               init_completion(&tgtp->tport_unreg_done);
+               tgtp->tport_unreg_cmp = &tport_unreg_cmp;
                nvmet_fc_unregister_targetport(phba->targetport);
-               wait_for_completion_timeout(&tgtp->tport_unreg_done, 5);
+               wait_for_completion_timeout(&tport_unreg_cmp, 5);
                lpfc_nvmet_cleanup_io_context(phba);
        }
        phba->targetport = NULL;
index 1aaff63..0ec1082 100644 (file)
@@ -34,7 +34,7 @@
 /* Used for NVME Target */
 struct lpfc_nvmet_tgtport {
        struct lpfc_hba *phba;
-       struct completion tport_unreg_done;
+       struct completion *tport_unreg_cmp;
 
        /* Stats counters - lpfc_nvmet_unsol_ls_buffer */
        atomic_t rcv_ls_req_in;
index 30734ca..2242e9b 100644 (file)
@@ -5362,8 +5362,8 @@ lpfc_sli4_read_rev(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
         * mailbox command.
         */
        dma_size = *vpd_size;
-       dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev, dma_size,
-                                          &dmabuf->phys, GFP_KERNEL);
+       dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev, dma_size,
+                                         &dmabuf->phys, GFP_KERNEL);
        if (!dmabuf->virt) {
                kfree(dmabuf);
                return -ENOMEM;
@@ -6300,10 +6300,9 @@ lpfc_sli4_ras_dma_alloc(struct lpfc_hba *phba,
                        goto free_mem;
                }
 
-               dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev,
+               dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev,
                                                  LPFC_RAS_MAX_ENTRY_SIZE,
-                                                 &dmabuf->phys,
-                                                 GFP_KERNEL);
+                                                 &dmabuf->phys, GFP_KERNEL);
                if (!dmabuf->virt) {
                        kfree(dmabuf);
                        rc = -ENOMEM;
@@ -9408,6 +9407,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                cmnd = CMD_XMIT_SEQUENCE64_CR;
                if (phba->link_flag & LS_LOOPBACK_MODE)
                        bf_set(wqe_xo, &wqe->xmit_sequence.wge_ctl, 1);
+               /* fall through */
        case CMD_XMIT_SEQUENCE64_CR:
                /* word3 iocb=io_tag32 wqe=reserved */
                wqe->xmit_sequence.rsvd3 = 0;
@@ -13529,6 +13529,7 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe)
        case FC_STATUS_RQ_BUF_LEN_EXCEEDED:
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                "2537 Receive Frame Truncated!!\n");
+               /* fall through */
        case FC_STATUS_RQ_SUCCESS:
                spin_lock_irqsave(&phba->hbalock, iflags);
                lpfc_sli4_rq_release(hrq, drq);
@@ -13938,7 +13939,7 @@ lpfc_sli4_nvmet_handle_rcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
        case FC_STATUS_RQ_BUF_LEN_EXCEEDED:
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                "6126 Receive Frame Truncated!!\n");
-               /* Drop thru */
+               /* fall through */
        case FC_STATUS_RQ_SUCCESS:
                spin_lock_irqsave(&phba->hbalock, iflags);
                lpfc_sli4_rq_release(hrq, drq);
@@ -14613,9 +14614,9 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t page_size,
                dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
                if (!dmabuf)
                        goto out_fail;
-               dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev,
-                                                  hw_page_size, &dmabuf->phys,
-                                                  GFP_KERNEL);
+               dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev,
+                                                 hw_page_size, &dmabuf->phys,
+                                                 GFP_KERNEL);
                if (!dmabuf->virt) {
                        kfree(dmabuf);
                        goto out_fail;
@@ -14850,7 +14851,7 @@ lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint32_t imax)
                                eq->entry_count);
                if (eq->entry_count < 256)
                        return -EINVAL;
-               /* otherwise default to smallest count (drop through) */
+               /* fall through - otherwise default to smallest count */
        case 256:
                bf_set(lpfc_eq_context_count, &eq_create->u.request.context,
                       LPFC_EQ_CNT_256);
@@ -14981,7 +14982,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
                               LPFC_CQ_CNT_WORD7);
                        break;
                }
-               /* Fall Thru */
+               /* fall through */
        default:
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                "0361 Unsupported CQ count: "
@@ -14992,7 +14993,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
                        status = -EINVAL;
                        goto out;
                }
-               /* otherwise default to smallest count (drop through) */
+               /* fall through - otherwise default to smallest count */
        case 256:
                bf_set(lpfc_cq_context_count, &cq_create->u.request.context,
                       LPFC_CQ_CNT_256);
@@ -15152,7 +15153,7 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp,
                                               LPFC_CQ_CNT_WORD7);
                                        break;
                                }
-                               /* Fall Thru */
+                               /* fall through */
                        default:
                                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                                "3118 Bad CQ count. (%d)\n",
@@ -15161,7 +15162,7 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp,
                                        status = -EINVAL;
                                        goto out;
                                }
-                               /* otherwise default to smallest (drop thru) */
+                               /* fall through - otherwise default to smallest */
                        case 256:
                                bf_set(lpfc_mbx_cq_create_set_cqe_cnt,
                                       &cq_set->u.request, LPFC_CQ_CNT_256);
@@ -15433,7 +15434,7 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
                        status = -EINVAL;
                        goto out;
                }
-               /* otherwise default to smallest count (drop through) */
+               /* fall through - otherwise default to smallest count */
        case 16:
                bf_set(lpfc_mq_context_ring_size,
                       &mq_create_ext->u.request.context,
@@ -15852,7 +15853,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
                                status = -EINVAL;
                                goto out;
                        }
-                       /* otherwise default to smallest count (drop through) */
+                       /* fall through - otherwise default to smallest count */
                case 512:
                        bf_set(lpfc_rq_context_rqe_count,
                               &rq_create->u.request.context,
@@ -15989,7 +15990,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
                                status = -EINVAL;
                                goto out;
                        }
-                       /* otherwise default to smallest count (drop through) */
+                       /* fall through - otherwise default to smallest count */
                case 512:
                        bf_set(lpfc_rq_context_rqe_count,
                               &rq_create->u.request.context,
index e836392..f112458 100644 (file)
@@ -967,9 +967,10 @@ megaraid_alloc_cmd_packets(adapter_t *adapter)
         * Allocate the common 16-byte aligned memory for the handshake
         * mailbox.
         */
-       raid_dev->una_mbox64 = dma_zalloc_coherent(&adapter->pdev->dev,
-                       sizeof(mbox64_t), &raid_dev->una_mbox64_dma,
-                       GFP_KERNEL);
+       raid_dev->una_mbox64 = dma_alloc_coherent(&adapter->pdev->dev,
+                                                 sizeof(mbox64_t),
+                                                 &raid_dev->una_mbox64_dma,
+                                                 GFP_KERNEL);
 
        if (!raid_dev->una_mbox64) {
                con_log(CL_ANN, (KERN_WARNING
@@ -995,8 +996,8 @@ megaraid_alloc_cmd_packets(adapter_t *adapter)
                        align;
 
        // Allocate memory for commands issued internally
-       adapter->ibuf = dma_zalloc_coherent(&pdev->dev, MBOX_IBUF_SIZE,
-                       &adapter->ibuf_dma_h, GFP_KERNEL);
+       adapter->ibuf = dma_alloc_coherent(&pdev->dev, MBOX_IBUF_SIZE,
+                                          &adapter->ibuf_dma_h, GFP_KERNEL);
        if (!adapter->ibuf) {
 
                con_log(CL_ANN, (KERN_WARNING
@@ -2897,8 +2898,8 @@ megaraid_mbox_product_info(adapter_t *adapter)
         * Issue an ENQUIRY3 command to find out certain adapter parameters,
         * e.g., max channels, max commands etc.
         */
-       pinfo = dma_zalloc_coherent(&adapter->pdev->dev, sizeof(mraid_pinfo_t),
-                       &pinfo_dma_h, GFP_KERNEL);
+       pinfo = dma_alloc_coherent(&adapter->pdev->dev, sizeof(mraid_pinfo_t),
+                                  &pinfo_dma_h, GFP_KERNEL);
        if (pinfo == NULL) {
                con_log(CL_ANN, (KERN_WARNING
                        "megaraid: out of memory, %s %d\n", __func__,
index f7bdd78..fcbff83 100644 (file)
@@ -2273,9 +2273,9 @@ static int megasas_get_ld_vf_affiliation_111(struct megasas_instance *instance,
                               sizeof(struct MR_LD_VF_AFFILIATION_111));
        else {
                new_affiliation_111 =
-                       dma_zalloc_coherent(&instance->pdev->dev,
-                                             sizeof(struct MR_LD_VF_AFFILIATION_111),
-                                             &new_affiliation_111_h, GFP_KERNEL);
+                       dma_alloc_coherent(&instance->pdev->dev,
+                                          sizeof(struct MR_LD_VF_AFFILIATION_111),
+                                          &new_affiliation_111_h, GFP_KERNEL);
                if (!new_affiliation_111) {
                        dev_printk(KERN_DEBUG, &instance->pdev->dev, "SR-IOV: Couldn't allocate "
                               "memory for new affiliation for scsi%d\n",
@@ -2380,10 +2380,9 @@ static int megasas_get_ld_vf_affiliation_12(struct megasas_instance *instance,
                       sizeof(struct MR_LD_VF_AFFILIATION));
        else {
                new_affiliation =
-                       dma_zalloc_coherent(&instance->pdev->dev,
-                                             (MAX_LOGICAL_DRIVES + 1) *
-                                             sizeof(struct MR_LD_VF_AFFILIATION),
-                                             &new_affiliation_h, GFP_KERNEL);
+                       dma_alloc_coherent(&instance->pdev->dev,
+                                          (MAX_LOGICAL_DRIVES + 1) * sizeof(struct MR_LD_VF_AFFILIATION),
+                                          &new_affiliation_h, GFP_KERNEL);
                if (!new_affiliation) {
                        dev_printk(KERN_DEBUG, &instance->pdev->dev, "SR-IOV: Couldn't allocate "
                               "memory for new affiliation for scsi%d\n",
@@ -2546,9 +2545,10 @@ int megasas_sriov_start_heartbeat(struct megasas_instance *instance,
 
        if (initial) {
                instance->hb_host_mem =
-                       dma_zalloc_coherent(&instance->pdev->dev,
-                                             sizeof(struct MR_CTRL_HB_HOST_MEM),
-                                             &instance->hb_host_mem_h, GFP_KERNEL);
+                       dma_alloc_coherent(&instance->pdev->dev,
+                                          sizeof(struct MR_CTRL_HB_HOST_MEM),
+                                          &instance->hb_host_mem_h,
+                                          GFP_KERNEL);
                if (!instance->hb_host_mem) {
                        dev_printk(KERN_DEBUG, &instance->pdev->dev, "SR-IOV: Couldn't allocate"
                               " memory for heartbeat host memory for scsi%d\n",
@@ -5816,9 +5816,9 @@ megasas_get_seq_num(struct megasas_instance *instance,
        }
 
        dcmd = &cmd->frame->dcmd;
-       el_info = dma_zalloc_coherent(&instance->pdev->dev,
-                       sizeof(struct megasas_evt_log_info), &el_info_h,
-                       GFP_KERNEL);
+       el_info = dma_alloc_coherent(&instance->pdev->dev,
+                                    sizeof(struct megasas_evt_log_info),
+                                    &el_info_h, GFP_KERNEL);
        if (!el_info) {
                megasas_return_cmd(instance, cmd);
                return -ENOMEM;
@@ -6236,7 +6236,7 @@ megasas_set_dma_mask(struct megasas_instance *instance)
                instance->consistent_mask_64bit = true;
 
        dev_info(&pdev->dev, "%s bit DMA mask and %s bit consistent mask\n",
-                ((*pdev->dev.dma_mask == DMA_BIT_MASK(64)) ? "63" : "32"),
+                ((*pdev->dev.dma_mask == DMA_BIT_MASK(63)) ? "63" : "32"),
                 (instance->consistent_mask_64bit ? "63" : "32"));
 
        return 0;
index 211c17c..647f48a 100644 (file)
@@ -175,7 +175,8 @@ megasas_clear_intr_fusion(struct megasas_instance *instance)
        /*
         * Check if it is our interrupt
         */
-       status = readl(&regs->outbound_intr_status);
+       status = megasas_readl(instance,
+                              &regs->outbound_intr_status);
 
        if (status & 1) {
                writel(status, &regs->outbound_intr_status);
@@ -689,8 +690,9 @@ megasas_alloc_rdpq_fusion(struct megasas_instance *instance)
        array_size = sizeof(struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY) *
                     MAX_MSIX_QUEUES_FUSION;
 
-       fusion->rdpq_virt = dma_zalloc_coherent(&instance->pdev->dev,
-                       array_size, &fusion->rdpq_phys, GFP_KERNEL);
+       fusion->rdpq_virt = dma_alloc_coherent(&instance->pdev->dev,
+                                              array_size, &fusion->rdpq_phys,
+                                              GFP_KERNEL);
        if (!fusion->rdpq_virt) {
                dev_err(&instance->pdev->dev,
                        "Failed from %s %d\n",  __func__, __LINE__);
index f3e182e..c9dc774 100644 (file)
@@ -1915,8 +1915,9 @@ static int mesh_probe(struct macio_dev *mdev, const struct of_device_id *match)
        /* We use the PCI APIs for now until the generic one gets fixed
         * enough or until we get some macio-specific versions
         */
-       dma_cmd_space = dma_zalloc_coherent(&macio_get_pci_dev(mdev)->dev,
-                       ms->dma_cmd_size, &dma_cmd_bus, GFP_KERNEL);
+       dma_cmd_space = dma_alloc_coherent(&macio_get_pci_dev(mdev)->dev,
+                                          ms->dma_cmd_size, &dma_cmd_bus,
+                                          GFP_KERNEL);
        if (dma_cmd_space == NULL) {
                printk(KERN_ERR "mesh: can't allocate DMA table\n");
                goto out_unmap;
index dbe753f..36f6420 100644 (file)
@@ -143,8 +143,9 @@ static struct mvumi_res *mvumi_alloc_mem_resource(struct mvumi_hba *mhba,
 
        case RESOURCE_UNCACHED_MEMORY:
                size = round_up(size, 8);
-               res->virt_addr = dma_zalloc_coherent(&mhba->pdev->dev, size,
-                               &res->bus_addr, GFP_KERNEL);
+               res->virt_addr = dma_alloc_coherent(&mhba->pdev->dev, size,
+                                                   &res->bus_addr,
+                                                   GFP_KERNEL);
                if (!res->virt_addr) {
                        dev_err(&mhba->pdev->dev,
                                        "unable to allocate consistent mem,"
@@ -246,8 +247,8 @@ static int mvumi_internal_cmd_sgl(struct mvumi_hba *mhba, struct mvumi_cmd *cmd,
        if (size == 0)
                return 0;
 
-       virt_addr = dma_zalloc_coherent(&mhba->pdev->dev, size, &phy_addr,
-                       GFP_KERNEL);
+       virt_addr = dma_alloc_coherent(&mhba->pdev->dev, size, &phy_addr,
+                                      GFP_KERNEL);
        if (!virt_addr)
                return -1;
 
index b3be49d..084f2fc 100644 (file)
@@ -116,8 +116,8 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr,
        u64 align_offset = 0;
        if (align)
                align_offset = (dma_addr_t)align - 1;
-       mem_virt_alloc = dma_zalloc_coherent(&pdev->dev, mem_size + align,
-                       &mem_dma_handle, GFP_KERNEL);
+       mem_virt_alloc = dma_alloc_coherent(&pdev->dev, mem_size + align,
+                                           &mem_dma_handle, GFP_KERNEL);
        if (!mem_virt_alloc) {
                pm8001_printk("memory allocation error\n");
                return -1;
@@ -657,7 +657,7 @@ static int pm8001_dev_found_notify(struct domain_device *dev)
                if (dev->dev_type == SAS_SATA_DEV) {
                        pm8001_device->attached_phy =
                                dev->rphy->identify.phy_identifier;
-                               flag = 1; /* directly sata*/
+                       flag = 1; /* directly sata */
                }
        } /*register this device to HBA*/
        PM8001_DISC_DBG(pm8001_ha, pm8001_printk("Found device\n"));
index edcaf4b..9bbc19f 100644 (file)
@@ -1050,16 +1050,17 @@ static int qedf_alloc_sq(struct qedf_ctx *qedf, struct qedf_rport *fcport)
            sizeof(void *);
        fcport->sq_pbl_size = fcport->sq_pbl_size + QEDF_PAGE_SIZE;
 
-       fcport->sq = dma_zalloc_coherent(&qedf->pdev->dev,
-           fcport->sq_mem_size, &fcport->sq_dma, GFP_KERNEL);
+       fcport->sq = dma_alloc_coherent(&qedf->pdev->dev, fcport->sq_mem_size,
+                                       &fcport->sq_dma, GFP_KERNEL);
        if (!fcport->sq) {
                QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate send queue.\n");
                rval = 1;
                goto out;
        }
 
-       fcport->sq_pbl = dma_zalloc_coherent(&qedf->pdev->dev,
-           fcport->sq_pbl_size, &fcport->sq_pbl_dma, GFP_KERNEL);
+       fcport->sq_pbl = dma_alloc_coherent(&qedf->pdev->dev,
+                                           fcport->sq_pbl_size,
+                                           &fcport->sq_pbl_dma, GFP_KERNEL);
        if (!fcport->sq_pbl) {
                QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate send queue PBL.\n");
                rval = 1;
@@ -2680,8 +2681,10 @@ static int qedf_alloc_bdq(struct qedf_ctx *qedf)
        }
 
        /* Allocate list of PBL pages */
-       qedf->bdq_pbl_list = dma_zalloc_coherent(&qedf->pdev->dev,
-           QEDF_PAGE_SIZE, &qedf->bdq_pbl_list_dma, GFP_KERNEL);
+       qedf->bdq_pbl_list = dma_alloc_coherent(&qedf->pdev->dev,
+                                               QEDF_PAGE_SIZE,
+                                               &qedf->bdq_pbl_list_dma,
+                                               GFP_KERNEL);
        if (!qedf->bdq_pbl_list) {
                QEDF_ERR(&(qedf->dbg_ctx), "Could not allocate list of PBL pages.\n");
                return -ENOMEM;
@@ -2770,9 +2773,10 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf)
                    ALIGN(qedf->global_queues[i]->cq_pbl_size, QEDF_PAGE_SIZE);
 
                qedf->global_queues[i]->cq =
-                   dma_zalloc_coherent(&qedf->pdev->dev,
-                       qedf->global_queues[i]->cq_mem_size,
-                       &qedf->global_queues[i]->cq_dma, GFP_KERNEL);
+                   dma_alloc_coherent(&qedf->pdev->dev,
+                                      qedf->global_queues[i]->cq_mem_size,
+                                      &qedf->global_queues[i]->cq_dma,
+                                      GFP_KERNEL);
 
                if (!qedf->global_queues[i]->cq) {
                        QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate cq.\n");
@@ -2781,9 +2785,10 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf)
                }
 
                qedf->global_queues[i]->cq_pbl =
-                   dma_zalloc_coherent(&qedf->pdev->dev,
-                       qedf->global_queues[i]->cq_pbl_size,
-                       &qedf->global_queues[i]->cq_pbl_dma, GFP_KERNEL);
+                   dma_alloc_coherent(&qedf->pdev->dev,
+                                      qedf->global_queues[i]->cq_pbl_size,
+                                      &qedf->global_queues[i]->cq_pbl_dma,
+                                      GFP_KERNEL);
 
                if (!qedf->global_queues[i]->cq_pbl) {
                        QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate cq PBL.\n");
index 4da660c..6d6d601 100644 (file)
@@ -953,6 +953,7 @@ static int qedi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
 
        qedi_ep = ep->dd_data;
        if (qedi_ep->state == EP_STATE_IDLE ||
+           qedi_ep->state == EP_STATE_OFLDCONN_NONE ||
            qedi_ep->state == EP_STATE_OFLDCONN_FAILED)
                return -1;
 
@@ -1035,6 +1036,7 @@ static void qedi_ep_disconnect(struct iscsi_endpoint *ep)
 
        switch (qedi_ep->state) {
        case EP_STATE_OFLDCONN_START:
+       case EP_STATE_OFLDCONN_NONE:
                goto ep_release_conn;
        case EP_STATE_OFLDCONN_FAILED:
                        break;
@@ -1225,6 +1227,7 @@ static int qedi_set_path(struct Scsi_Host *shost, struct iscsi_path *path_data)
 
        if (!is_valid_ether_addr(&path_data->mac_addr[0])) {
                QEDI_NOTICE(&qedi->dbg_ctx, "dst mac NOT VALID\n");
+               qedi_ep->state = EP_STATE_OFLDCONN_NONE;
                ret = -EIO;
                goto set_path_exit;
        }
index 1126077..892d70d 100644 (file)
@@ -59,6 +59,7 @@ enum {
        EP_STATE_OFLDCONN_FAILED        = 0x2000,
        EP_STATE_CONNECT_FAILED         = 0x4000,
        EP_STATE_DISCONN_TIMEDOUT       = 0x8000,
+       EP_STATE_OFLDCONN_NONE          = 0x10000,
 };
 
 struct qedi_conn;
index 5c53409..e74a624 100644 (file)
@@ -1394,10 +1394,9 @@ static int qedi_alloc_nvm_iscsi_cfg(struct qedi_ctx *qedi)
 {
        struct qedi_nvm_iscsi_image nvm_image;
 
-       qedi->iscsi_image = dma_zalloc_coherent(&qedi->pdev->dev,
-                                               sizeof(nvm_image),
-                                               &qedi->nvm_buf_dma,
-                                               GFP_KERNEL);
+       qedi->iscsi_image = dma_alloc_coherent(&qedi->pdev->dev,
+                                              sizeof(nvm_image),
+                                              &qedi->nvm_buf_dma, GFP_KERNEL);
        if (!qedi->iscsi_image) {
                QEDI_ERR(&qedi->dbg_ctx, "Could not allocate NVM BUF.\n");
                return -ENOMEM;
@@ -1510,10 +1509,10 @@ static int qedi_alloc_bdq(struct qedi_ctx *qedi)
        }
 
        /* Allocate list of PBL pages */
-       qedi->bdq_pbl_list = dma_zalloc_coherent(&qedi->pdev->dev,
-                                                QEDI_PAGE_SIZE,
-                                                &qedi->bdq_pbl_list_dma,
-                                                GFP_KERNEL);
+       qedi->bdq_pbl_list = dma_alloc_coherent(&qedi->pdev->dev,
+                                               QEDI_PAGE_SIZE,
+                                               &qedi->bdq_pbl_list_dma,
+                                               GFP_KERNEL);
        if (!qedi->bdq_pbl_list) {
                QEDI_ERR(&qedi->dbg_ctx,
                         "Could not allocate list of PBL pages.\n");
@@ -1609,10 +1608,10 @@ static int qedi_alloc_global_queues(struct qedi_ctx *qedi)
                    (qedi->global_queues[i]->cq_pbl_size +
                    (QEDI_PAGE_SIZE - 1));
 
-               qedi->global_queues[i]->cq = dma_zalloc_coherent(&qedi->pdev->dev,
-                                                                qedi->global_queues[i]->cq_mem_size,
-                                                                &qedi->global_queues[i]->cq_dma,
-                                                                GFP_KERNEL);
+               qedi->global_queues[i]->cq = dma_alloc_coherent(&qedi->pdev->dev,
+                                                               qedi->global_queues[i]->cq_mem_size,
+                                                               &qedi->global_queues[i]->cq_dma,
+                                                               GFP_KERNEL);
 
                if (!qedi->global_queues[i]->cq) {
                        QEDI_WARN(&qedi->dbg_ctx,
@@ -1620,10 +1619,10 @@ static int qedi_alloc_global_queues(struct qedi_ctx *qedi)
                        status = -ENOMEM;
                        goto mem_alloc_failure;
                }
-               qedi->global_queues[i]->cq_pbl = dma_zalloc_coherent(&qedi->pdev->dev,
-                                                                    qedi->global_queues[i]->cq_pbl_size,
-                                                                    &qedi->global_queues[i]->cq_pbl_dma,
-                                                                    GFP_KERNEL);
+               qedi->global_queues[i]->cq_pbl = dma_alloc_coherent(&qedi->pdev->dev,
+                                                                   qedi->global_queues[i]->cq_pbl_size,
+                                                                   &qedi->global_queues[i]->cq_pbl_dma,
+                                                                   GFP_KERNEL);
 
                if (!qedi->global_queues[i]->cq_pbl) {
                        QEDI_WARN(&qedi->dbg_ctx,
@@ -1691,16 +1690,16 @@ int qedi_alloc_sq(struct qedi_ctx *qedi, struct qedi_endpoint *ep)
        ep->sq_pbl_size = (ep->sq_mem_size / QEDI_PAGE_SIZE) * sizeof(void *);
        ep->sq_pbl_size = ep->sq_pbl_size + QEDI_PAGE_SIZE;
 
-       ep->sq = dma_zalloc_coherent(&qedi->pdev->dev, ep->sq_mem_size,
-                                    &ep->sq_dma, GFP_KERNEL);
+       ep->sq = dma_alloc_coherent(&qedi->pdev->dev, ep->sq_mem_size,
+                                   &ep->sq_dma, GFP_KERNEL);
        if (!ep->sq) {
                QEDI_WARN(&qedi->dbg_ctx,
                          "Could not allocate send queue.\n");
                rval = -ENOMEM;
                goto out;
        }
-       ep->sq_pbl = dma_zalloc_coherent(&qedi->pdev->dev, ep->sq_pbl_size,
-                                        &ep->sq_pbl_dma, GFP_KERNEL);
+       ep->sq_pbl = dma_alloc_coherent(&qedi->pdev->dev, ep->sq_pbl_size,
+                                       &ep->sq_pbl_dma, GFP_KERNEL);
        if (!ep->sq_pbl) {
                QEDI_WARN(&qedi->dbg_ctx,
                          "Could not allocate send queue PBL.\n");
index a414f51..6856dfd 100644 (file)
@@ -4248,7 +4248,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        ha->devnum = devnum;    /* specifies microcode load address */
 
 #ifdef QLA_64BIT_PTR
-       if (dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(64))) {
+       if (dma_set_mask_and_coherent(&ha->pdev->dev, DMA_BIT_MASK(64))) {
                if (dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(32))) {
                        printk(KERN_WARNING "scsi(%li): Unable to set a "
                               "suitable DMA mask - aborting\n", ha->host_no);
index 00444dc..ac504a1 100644 (file)
@@ -2415,8 +2415,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
        if (qla2x00_chip_is_down(vha))
                goto done;
 
-       stats = dma_zalloc_coherent(&ha->pdev->dev, sizeof(*stats),
-                                   &stats_dma, GFP_KERNEL);
+       stats = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stats), &stats_dma,
+                                  GFP_KERNEL);
        if (!stats) {
                ql_log(ql_log_warn, vha, 0x707d,
                    "Failed to allocate memory for stats.\n");
index 4a9fd8d..17d4265 100644 (file)
@@ -2312,8 +2312,8 @@ qla2x00_get_priv_stats(struct bsg_job *bsg_job)
        if (!IS_FWI2_CAPABLE(ha))
                return -EPERM;
 
-       stats = dma_zalloc_coherent(&ha->pdev->dev, sizeof(*stats),
-                                   &stats_dma, GFP_KERNEL);
+       stats = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stats), &stats_dma,
+                                  GFP_KERNEL);
        if (!stats) {
                ql_log(ql_log_warn, vha, 0x70e2,
                    "Failed to allocate memory for stats.\n");
index 26b93c5..d1fc495 100644 (file)
@@ -4394,6 +4394,8 @@ typedef struct scsi_qla_host {
        uint16_t        n2n_id;
        struct list_head gpnid_list;
        struct fab_scan scan;
+
+       unsigned int irq_offset;
 } scsi_qla_host_t;
 
 struct qla27xx_image_status {
index 90cfa39..cbc3bc4 100644 (file)
@@ -4147,9 +4147,10 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
                        return rval;
                }
 
-               sp->u.iocb_cmd.u.ctarg.req = dma_zalloc_coherent(
-                       &vha->hw->pdev->dev, sizeof(struct ct_sns_pkt),
-                       &sp->u.iocb_cmd.u.ctarg.req_dma, GFP_KERNEL);
+               sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
+                                                               sizeof(struct ct_sns_pkt),
+                                                               &sp->u.iocb_cmd.u.ctarg.req_dma,
+                                                               GFP_KERNEL);
                sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt);
                if (!sp->u.iocb_cmd.u.ctarg.req) {
                        ql_log(ql_log_warn, vha, 0xffff,
@@ -4165,9 +4166,10 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
                        ((vha->hw->max_fibre_devices - 1) *
                            sizeof(struct ct_sns_gpn_ft_data));
 
-               sp->u.iocb_cmd.u.ctarg.rsp = dma_zalloc_coherent(
-                       &vha->hw->pdev->dev, rspsz,
-                       &sp->u.iocb_cmd.u.ctarg.rsp_dma, GFP_KERNEL);
+               sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
+                                                               rspsz,
+                                                               &sp->u.iocb_cmd.u.ctarg.rsp_dma,
+                                                               GFP_KERNEL);
                sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = sizeof(struct ct_sns_pkt);
                if (!sp->u.iocb_cmd.u.ctarg.rsp) {
                        ql_log(ql_log_warn, vha, 0xffff,
index 364bb52..8d1acc8 100644 (file)
@@ -1785,13 +1785,13 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
 
                /* Issue Marker IOCB */
                qla2x00_marker(vha, vha->hw->req_q_map[0],
-                   vha->hw->rsp_q_map[0], sp->fcport->loop_id, lun,
+                   vha->hw->rsp_q_map[0], fcport->loop_id, lun,
                    flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
        }
 
 done_free_sp:
        sp->free(sp);
-       sp->fcport->flags &= ~FCF_ASYNC_SENT;
+       fcport->flags &= ~FCF_ASYNC_SENT;
 done:
        return rval;
 }
@@ -3099,8 +3099,8 @@ qla2x00_alloc_offload_mem(scsi_qla_host_t *vha)
                            FCE_SIZE, ha->fce, ha->fce_dma);
 
                /* Allocate memory for Fibre Channel Event Buffer. */
-               tc = dma_zalloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
-                                        GFP_KERNEL);
+               tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
+                                       GFP_KERNEL);
                if (!tc) {
                        ql_log(ql_log_warn, vha, 0x00be,
                            "Unable to allocate (%d KB) for FCE.\n",
@@ -3131,8 +3131,8 @@ try_eft:
                            EFT_SIZE, ha->eft, ha->eft_dma);
 
                /* Allocate memory for Extended Trace Buffer. */
-               tc = dma_zalloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
-                                        GFP_KERNEL);
+               tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
+                                       GFP_KERNEL);
                if (!tc) {
                        ql_log(ql_log_warn, vha, 0x00c1,
                            "Unable to allocate (%d KB) for EFT.\n",
index 30d3090..8507c43 100644 (file)
@@ -3446,6 +3446,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
                            "Adjusted Max no of queues pairs: %d.\n", ha->max_qpairs);
                }
        }
+       vha->irq_offset = desc.pre_vectors;
        ha->msix_entries = kcalloc(ha->msix_count,
                                   sizeof(struct qla_msix_entry),
                                   GFP_KERNEL);
index ea69daf..c6ef83d 100644 (file)
@@ -6939,7 +6939,7 @@ static int qla2xxx_map_queues(struct Scsi_Host *shost)
        if (USER_CTRL_IRQ(vha->hw))
                rc = blk_mq_map_queues(qmap);
        else
-               rc = blk_mq_pci_map_queues(qmap, vha->hw->pdev, 0);
+               rc = blk_mq_pci_map_queues(qmap, vha->hw->pdev, vha->irq_offset);
        return rc;
 }
 
index 1ef74aa..2bf5e3e 100644 (file)
@@ -153,8 +153,8 @@ int qla4xxx_get_sys_info(struct scsi_qla_host *ha)
        dma_addr_t sys_info_dma;
        int status = QLA_ERROR;
 
-       sys_info = dma_zalloc_coherent(&ha->pdev->dev, sizeof(*sys_info),
-                                      &sys_info_dma, GFP_KERNEL);
+       sys_info = dma_alloc_coherent(&ha->pdev->dev, sizeof(*sys_info),
+                                     &sys_info_dma, GFP_KERNEL);
        if (sys_info == NULL) {
                DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
                              ha->host_no, __func__));
index 5d56904..dac9a70 100644 (file)
@@ -625,9 +625,9 @@ int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha)
        uint32_t mbox_sts[MBOX_REG_COUNT];
        int status = QLA_ERROR;
 
-       init_fw_cb = dma_zalloc_coherent(&ha->pdev->dev,
-                                        sizeof(struct addr_ctrl_blk),
-                                        &init_fw_cb_dma, GFP_KERNEL);
+       init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
+                                       sizeof(struct addr_ctrl_blk),
+                                       &init_fw_cb_dma, GFP_KERNEL);
        if (init_fw_cb == NULL) {
                DEBUG2(printk("scsi%ld: %s: Unable to alloc init_cb\n",
                              ha->host_no, __func__));
@@ -709,9 +709,9 @@ int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha)
        uint32_t mbox_cmd[MBOX_REG_COUNT];
        uint32_t mbox_sts[MBOX_REG_COUNT];
 
-       init_fw_cb = dma_zalloc_coherent(&ha->pdev->dev,
-                                        sizeof(struct addr_ctrl_blk),
-                                        &init_fw_cb_dma, GFP_KERNEL);
+       init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
+                                       sizeof(struct addr_ctrl_blk),
+                                       &init_fw_cb_dma, GFP_KERNEL);
        if (init_fw_cb == NULL) {
                printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no,
                       __func__);
@@ -1340,9 +1340,9 @@ int qla4xxx_about_firmware(struct scsi_qla_host *ha)
        uint32_t mbox_sts[MBOX_REG_COUNT];
        int status = QLA_ERROR;
 
-       about_fw = dma_zalloc_coherent(&ha->pdev->dev,
-                                      sizeof(struct about_fw_info),
-                                      &about_fw_dma, GFP_KERNEL);
+       about_fw = dma_alloc_coherent(&ha->pdev->dev,
+                                     sizeof(struct about_fw_info),
+                                     &about_fw_dma, GFP_KERNEL);
        if (!about_fw) {
                DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Unable to alloc memory "
                                  "for about_fw\n", __func__));
index d2b333d..5a31877 100644 (file)
@@ -4052,8 +4052,8 @@ int qla4_8xxx_get_sys_info(struct scsi_qla_host *ha)
        dma_addr_t sys_info_dma;
        int status = QLA_ERROR;
 
-       sys_info = dma_zalloc_coherent(&ha->pdev->dev, sizeof(*sys_info),
-                                      &sys_info_dma, GFP_KERNEL);
+       sys_info = dma_alloc_coherent(&ha->pdev->dev, sizeof(*sys_info),
+                                     &sys_info_dma, GFP_KERNEL);
        if (sys_info == NULL) {
                DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
                    ha->host_no, __func__));
index 949e186..a77bfb2 100644 (file)
@@ -2704,9 +2704,9 @@ qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data, uint32_t len)
        uint32_t rem = len;
        struct nlattr *attr;
 
-       init_fw_cb = dma_zalloc_coherent(&ha->pdev->dev,
-                                        sizeof(struct addr_ctrl_blk),
-                                        &init_fw_cb_dma, GFP_KERNEL);
+       init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
+                                       sizeof(struct addr_ctrl_blk),
+                                       &init_fw_cb_dma, GFP_KERNEL);
        if (!init_fw_cb) {
                ql4_printk(KERN_ERR, ha, "%s: Unable to alloc init_cb\n",
                           __func__);
@@ -4206,8 +4206,8 @@ static int qla4xxx_mem_alloc(struct scsi_qla_host *ha)
                          sizeof(struct shadow_regs) +
                          MEM_ALIGN_VALUE +
                          (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
-       ha->queues = dma_zalloc_coherent(&ha->pdev->dev, ha->queues_len,
-                                        &ha->queues_dma, GFP_KERNEL);
+       ha->queues = dma_alloc_coherent(&ha->pdev->dev, ha->queues_len,
+                                       &ha->queues_dma, GFP_KERNEL);
        if (ha->queues == NULL) {
                ql4_printk(KERN_WARNING, ha,
                    "Memory Allocation failed - queues.\n");
@@ -7232,6 +7232,8 @@ static int qla4xxx_sysfs_ddb_tgt_create(struct scsi_qla_host *ha,
 
        rc = qla4xxx_copy_from_fwddb_param(fnode_sess, fnode_conn,
                                           fw_ddb_entry);
+       if (rc)
+               goto free_sess;
 
        ql4_printk(KERN_INFO, ha, "%s: sysfs entry %s created\n",
                   __func__, fnode_sess->dev.kobj.name);
index 661512b..e27f4df 100644 (file)
@@ -62,7 +62,7 @@
 
 /* make sure inq_product_rev string corresponds to this version */
 #define SDEBUG_VERSION "0188"  /* format to fit INQUIRY revision field */
-static const char *sdebug_version_date = "20180128";
+static const char *sdebug_version_date = "20190125";
 
 #define MY_NAME "scsi_debug"
 
@@ -735,7 +735,7 @@ static inline bool scsi_debug_lbp(void)
                (sdebug_lbpu || sdebug_lbpws || sdebug_lbpws10);
 }
 
-static void *fake_store(unsigned long long lba)
+static void *lba2fake_store(unsigned long long lba)
 {
        lba = do_div(lba, sdebug_store_sectors);
 
@@ -2514,8 +2514,8 @@ static int do_device_access(struct scsi_cmnd *scmd, u32 sg_skip, u64 lba,
        return ret;
 }
 
-/* If fake_store(lba,num) compares equal to arr(num), then copy top half of
- * arr into fake_store(lba,num) and return true. If comparison fails then
+/* If lba2fake_store(lba,num) compares equal to arr(num), then copy top half of
+ * arr into lba2fake_store(lba,num) and return true. If comparison fails then
  * return false. */
 static bool comp_write_worker(u64 lba, u32 num, const u8 *arr)
 {
@@ -2643,7 +2643,7 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
                if (sdt->app_tag == cpu_to_be16(0xffff))
                        continue;
 
-               ret = dif_verify(sdt, fake_store(sector), sector, ei_lba);
+               ret = dif_verify(sdt, lba2fake_store(sector), sector, ei_lba);
                if (ret) {
                        dif_errors++;
                        return ret;
@@ -3261,10 +3261,12 @@ err_out:
 static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num,
                           u32 ei_lba, bool unmap, bool ndob)
 {
+       int ret;
        unsigned long iflags;
        unsigned long long i;
-       int ret;
-       u64 lba_off;
+       u32 lb_size = sdebug_sector_size;
+       u64 block, lbaa;
+       u8 *fs1p;
 
        ret = check_device_access_params(scp, lba, num);
        if (ret)
@@ -3276,31 +3278,30 @@ static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num,
                unmap_region(lba, num);
                goto out;
        }
-
-       lba_off = lba * sdebug_sector_size;
+       lbaa = lba;
+       block = do_div(lbaa, sdebug_store_sectors);
        /* if ndob then zero 1 logical block, else fetch 1 logical block */
+       fs1p = fake_storep + (block * lb_size);
        if (ndob) {
-               memset(fake_storep + lba_off, 0, sdebug_sector_size);
+               memset(fs1p, 0, lb_size);
                ret = 0;
        } else
-               ret = fetch_to_dev_buffer(scp, fake_storep + lba_off,
-                                         sdebug_sector_size);
+               ret = fetch_to_dev_buffer(scp, fs1p, lb_size);
 
        if (-1 == ret) {
                write_unlock_irqrestore(&atomic_rw, iflags);
                return DID_ERROR << 16;
-       } else if (sdebug_verbose && !ndob && (ret < sdebug_sector_size))
+       } else if (sdebug_verbose && !ndob && (ret < lb_size))
                sdev_printk(KERN_INFO, scp->device,
                            "%s: %s: lb size=%u, IO sent=%d bytes\n",
-                           my_name, "write same",
-                           sdebug_sector_size, ret);
+                           my_name, "write same", lb_size, ret);
 
        /* Copy first sector to remaining blocks */
-       for (i = 1 ; i < num ; i++)
-               memcpy(fake_storep + ((lba + i) * sdebug_sector_size),
-                      fake_storep + lba_off,
-                      sdebug_sector_size);
-
+       for (i = 1 ; i < num ; i++) {
+               lbaa = lba + i;
+               block = do_div(lbaa, sdebug_store_sectors);
+               memmove(fake_storep + (block * lb_size), fs1p, lb_size);
+       }
        if (scsi_debug_lbp())
                map_region(lba, num);
 out:
index b13cc92..6d65ac5 100644 (file)
@@ -1842,8 +1842,8 @@ void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q)
        blk_queue_segment_boundary(q, shost->dma_boundary);
        dma_set_seg_boundary(dev, shost->dma_boundary);
 
-       blk_queue_max_segment_size(q,
-               min(shost->max_segment_size, dma_get_max_seg_size(dev)));
+       blk_queue_max_segment_size(q, shost->max_segment_size);
+       dma_set_max_seg_size(dev, shost->max_segment_size);
 
        /*
         * Set a reasonable default alignment:  The larger of 32-byte (dword),
index a2b4179..7639df9 100644 (file)
@@ -80,8 +80,22 @@ static int scsi_dev_type_resume(struct device *dev,
 
        if (err == 0) {
                pm_runtime_disable(dev);
-               pm_runtime_set_active(dev);
+               err = pm_runtime_set_active(dev);
                pm_runtime_enable(dev);
+
+               /*
+                * Forcibly set runtime PM status of request queue to "active"
+                * to make sure we can again get requests from the queue
+                * (see also blk_pm_peek_request()).
+                *
+                * The resume hook will correct runtime PM status of the disk.
+                */
+               if (!err && scsi_is_sdev_device(dev)) {
+                       struct scsi_device *sdev = to_scsi_device(dev);
+
+                       if (sdev->request_queue->dev)
+                               blk_set_runtime_active(sdev->request_queue);
+               }
        }
 
        return err;
@@ -140,16 +154,6 @@ static int scsi_bus_resume_common(struct device *dev,
        else
                fn = NULL;
 
-       /*
-        * Forcibly set runtime PM status of request queue to "active" to
-        * make sure we can again get requests from the queue (see also
-        * blk_pm_peek_request()).
-        *
-        * The resume hook will correct runtime PM status of the disk.
-        */
-       if (scsi_is_sdev_device(dev) && pm_runtime_suspended(dev))
-               blk_set_runtime_active(to_scsi_device(dev)->request_queue);
-
        if (fn) {
                async_schedule_domain(fn, dev, &scsi_sd_pm_domain);
 
index a1a44f5..5464d46 100644 (file)
@@ -206,6 +206,12 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
        sp = buffer_data[0] & 0x80 ? 1 : 0;
        buffer_data[0] &= ~0x80;
 
+       /*
+        * Ensure WP, DPOFUA, and RESERVED fields are cleared in
+        * received mode parameter buffer before doing MODE SELECT.
+        */
+       data.device_specific = 0;
+
        if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT,
                             SD_MAX_RETRIES, &data, &sshdr)) {
                if (scsi_sense_valid(&sshdr))
@@ -2945,9 +2951,6 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
        if (rot == 1) {
                blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
                blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q);
-       } else {
-               blk_queue_flag_clear(QUEUE_FLAG_NONROT, q);
-               blk_queue_flag_set(QUEUE_FLAG_ADD_RANDOM, q);
        }
 
        if (sdkp->device->type == TYPE_ZBC) {
@@ -3084,6 +3087,15 @@ static int sd_revalidate_disk(struct gendisk *disk)
        if (sdkp->media_present) {
                sd_read_capacity(sdkp, buffer);
 
+               /*
+                * set the default to rotational.  All non-rotational devices
+                * support the block characteristics VPD page, which will
+                * cause this to be updated correctly and any device which
+                * doesn't support it should be treated as rotational.
+                */
+               blk_queue_flag_clear(QUEUE_FLAG_NONROT, q);
+               blk_queue_flag_set(QUEUE_FLAG_ADD_RANDOM, q);
+
                if (scsi_device_supports_vpd(sdp)) {
                        sd_read_block_provisioning(sdkp);
                        sd_read_block_limits(sdkp);
index 83365b2..fff8694 100644 (file)
@@ -462,12 +462,16 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buf)
        sdkp->device->use_10_for_rw = 0;
 
        /*
-        * If something changed, revalidate the disk zone bitmaps once we have
-        * the capacity, that is on the second revalidate execution during disk
-        * scan and always during normal revalidate.
+        * Revalidate the disk zone bitmaps once the block device capacity is
+        * set on the second revalidate execution during disk scan and if
+        * something changed when executing a normal revalidate.
         */
-       if (sdkp->first_scan)
+       if (sdkp->first_scan) {
+               sdkp->zone_blocks = zone_blocks;
+               sdkp->nr_zones = nr_zones;
                return 0;
+       }
+
        if (sdkp->zone_blocks != zone_blocks ||
            sdkp->nr_zones != nr_zones ||
            disk->queue->nr_zones != nr_zones) {
index e2fa3f4..f564af8 100644 (file)
@@ -323,7 +323,7 @@ static inline void pqi_device_remove_start(struct pqi_scsi_dev *device)
 static inline bool pqi_device_in_remove(struct pqi_ctrl_info *ctrl_info,
                                        struct pqi_scsi_dev *device)
 {
-       return device->in_remove & !ctrl_info->in_shutdown;
+       return device->in_remove && !ctrl_info->in_shutdown;
 }
 
 static inline void pqi_schedule_rescan_worker_with_delay(
@@ -3576,9 +3576,9 @@ static int pqi_alloc_operational_queues(struct pqi_ctrl_info *ctrl_info)
        alloc_length += PQI_EXTRA_SGL_MEMORY;
 
        ctrl_info->queue_memory_base =
-               dma_zalloc_coherent(&ctrl_info->pci_dev->dev,
-                       alloc_length,
-                       &ctrl_info->queue_memory_base_dma_handle, GFP_KERNEL);
+               dma_alloc_coherent(&ctrl_info->pci_dev->dev, alloc_length,
+                                  &ctrl_info->queue_memory_base_dma_handle,
+                                  GFP_KERNEL);
 
        if (!ctrl_info->queue_memory_base)
                return -ENOMEM;
@@ -3715,10 +3715,9 @@ static int pqi_alloc_admin_queues(struct pqi_ctrl_info *ctrl_info)
                PQI_QUEUE_ELEMENT_ARRAY_ALIGNMENT;
 
        ctrl_info->admin_queue_memory_base =
-               dma_zalloc_coherent(&ctrl_info->pci_dev->dev,
-                       alloc_length,
-                       &ctrl_info->admin_queue_memory_base_dma_handle,
-                       GFP_KERNEL);
+               dma_alloc_coherent(&ctrl_info->pci_dev->dev, alloc_length,
+                                  &ctrl_info->admin_queue_memory_base_dma_handle,
+                                  GFP_KERNEL);
 
        if (!ctrl_info->admin_queue_memory_base)
                return -ENOMEM;
@@ -4602,9 +4601,10 @@ static void pqi_free_all_io_requests(struct pqi_ctrl_info *ctrl_info)
 
 static inline int pqi_alloc_error_buffer(struct pqi_ctrl_info *ctrl_info)
 {
-       ctrl_info->error_buffer = dma_zalloc_coherent(&ctrl_info->pci_dev->dev,
-               ctrl_info->error_buffer_length,
-               &ctrl_info->error_buffer_dma_handle, GFP_KERNEL);
+       ctrl_info->error_buffer = dma_alloc_coherent(&ctrl_info->pci_dev->dev,
+                                                    ctrl_info->error_buffer_length,
+                                                    &ctrl_info->error_buffer_dma_handle,
+                                                    GFP_KERNEL);
 
        if (!ctrl_info->error_buffer)
                return -ENOMEM;
@@ -7487,8 +7487,8 @@ static int pqi_ofa_alloc_mem(struct pqi_ctrl_info *ctrl_info,
                dma_addr_t dma_handle;
 
                ctrl_info->pqi_ofa_chunk_virt_addr[i] =
-                       dma_zalloc_coherent(dev, chunk_size, &dma_handle,
-                                               GFP_KERNEL);
+                       dma_alloc_coherent(dev, chunk_size, &dma_handle,
+                                          GFP_KERNEL);
 
                if (!ctrl_info->pqi_ofa_chunk_virt_addr[i])
                        break;
@@ -7545,10 +7545,10 @@ static void pqi_ofa_setup_host_buffer(struct pqi_ctrl_info *ctrl_info,
        struct device *dev;
 
        dev = &ctrl_info->pci_dev->dev;
-       pqi_ofa_memory = dma_zalloc_coherent(dev,
-                               PQI_OFA_MEMORY_DESCRIPTOR_LENGTH,
-                               &ctrl_info->pqi_ofa_mem_dma_handle,
-                               GFP_KERNEL);
+       pqi_ofa_memory = dma_alloc_coherent(dev,
+                                           PQI_OFA_MEMORY_DESCRIPTOR_LENGTH,
+                                           &ctrl_info->pqi_ofa_mem_dma_handle,
+                                           GFP_KERNEL);
 
        if (!pqi_ofa_memory)
                return;
index dd65fea..6d17681 100644 (file)
@@ -195,7 +195,7 @@ enum ufs_desc_def_size {
        QUERY_DESC_CONFIGURATION_DEF_SIZE       = 0x90,
        QUERY_DESC_UNIT_DEF_SIZE                = 0x23,
        QUERY_DESC_INTERCONNECT_DEF_SIZE        = 0x06,
-       QUERY_DESC_GEOMETRY_DEF_SIZE            = 0x44,
+       QUERY_DESC_GEOMETRY_DEF_SIZE            = 0x48,
        QUERY_DESC_POWER_DEF_SIZE               = 0x62,
        QUERY_DESC_HEALTH_DEF_SIZE              = 0x25,
 };
index 9ba7671..2ddf244 100644 (file)
 int ufshcd_dump_regs(struct ufs_hba *hba, size_t offset, size_t len,
                     const char *prefix)
 {
-       u8 *regs;
+       u32 *regs;
+       size_t pos;
+
+       if (offset % 4 != 0 || len % 4 != 0) /* keep readl happy */
+               return -EINVAL;
 
        regs = kzalloc(len, GFP_KERNEL);
        if (!regs)
                return -ENOMEM;
 
-       memcpy_fromio(regs, hba->mmio_base + offset, len);
+       for (pos = 0; pos < len; pos += 4)
+               regs[pos / 4] = ufshcd_readl(hba, offset + pos);
+
        ufshcd_hex_dump(prefix, regs, len);
        kfree(regs);
 
@@ -8001,6 +8007,8 @@ out:
        trace_ufshcd_system_resume(dev_name(hba->dev), ret,
                ktime_to_us(ktime_sub(ktime_get(), start)),
                hba->curr_dev_pwr_mode, hba->uic_link_state);
+       if (!ret)
+               hba->is_sys_suspended = false;
        return ret;
 }
 EXPORT_SYMBOL(ufshcd_system_resume);
index 9436aa8..e6d48dc 100644 (file)
@@ -62,7 +62,7 @@ int qbman_init_private_mem(struct device *dev, int idx, dma_addr_t *addr,
                return -ENODEV;
        }
 
-       if (!dma_zalloc_coherent(dev, *size, addr, 0)) {
+       if (!dma_alloc_coherent(dev, *size, addr, 0)) {
                dev_err(dev, "DMA Alloc memory failed\n");
                return -ENODEV;
        }
index 52c153c..636f83f 100644 (file)
@@ -1143,18 +1143,19 @@ static void qm_mr_process_task(struct work_struct *work);
 static irqreturn_t portal_isr(int irq, void *ptr)
 {
        struct qman_portal *p = ptr;
-
-       u32 clear = QM_DQAVAIL_MASK | p->irq_sources;
        u32 is = qm_in(&p->p, QM_REG_ISR) & p->irq_sources;
+       u32 clear = 0;
 
        if (unlikely(!is))
                return IRQ_NONE;
 
        /* DQRR-handling if it's interrupt-driven */
-       if (is & QM_PIRQ_DQRI)
+       if (is & QM_PIRQ_DQRI) {
                __poll_portal_fast(p, QMAN_POLL_LIMIT);
+               clear = QM_DQAVAIL_MASK | QM_PIRQ_DQRI;
+       }
        /* Handling of anything else that's interrupt-driven */
-       clear |= __poll_portal_slow(p, is);
+       clear |= __poll_portal_slow(p, is) & QM_PIRQ_SLOW;
        qm_out(&p->p, QM_REG_ISR, clear);
        return IRQ_HANDLED;
 }
index f78c346..76480df 100644 (file)
@@ -44,10 +44,6 @@ int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm,
        const char *sprop;
        int ret = 0;
        u32 val;
-       struct resource *res;
-       struct device_node *np2;
-       static int siram_init_flag;
-       struct platform_device *pdev;
 
        sprop = of_get_property(np, "fsl,rx-sync-clock", NULL);
        if (sprop) {
@@ -124,57 +120,6 @@ int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm,
        utdm->siram_entry_id = val;
 
        set_si_param(utdm, ut_info);
-
-       np2 = of_find_compatible_node(NULL, NULL, "fsl,t1040-qe-si");
-       if (!np2)
-               return -EINVAL;
-
-       pdev = of_find_device_by_node(np2);
-       if (!pdev) {
-               pr_err("%pOFn: failed to lookup pdev\n", np2);
-               of_node_put(np2);
-               return -EINVAL;
-       }
-
-       of_node_put(np2);
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       utdm->si_regs = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(utdm->si_regs)) {
-               ret = PTR_ERR(utdm->si_regs);
-               goto err_miss_siram_property;
-       }
-
-       np2 = of_find_compatible_node(NULL, NULL, "fsl,t1040-qe-siram");
-       if (!np2) {
-               ret = -EINVAL;
-               goto err_miss_siram_property;
-       }
-
-       pdev = of_find_device_by_node(np2);
-       if (!pdev) {
-               ret = -EINVAL;
-               pr_err("%pOFn: failed to lookup pdev\n", np2);
-               of_node_put(np2);
-               goto err_miss_siram_property;
-       }
-
-       of_node_put(np2);
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       utdm->siram = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(utdm->siram)) {
-               ret = PTR_ERR(utdm->siram);
-               goto err_miss_siram_property;
-       }
-
-       if (siram_init_flag == 0) {
-               memset_io(utdm->siram, 0,  resource_size(res));
-               siram_init_flag = 1;
-       }
-
-       return ret;
-
-err_miss_siram_property:
-       devm_iounmap(&pdev->dev, utdm->si_regs);
        return ret;
 }
 EXPORT_SYMBOL(ucc_of_parse_tdm);
index 4d8012e..68bfca6 100644 (file)
@@ -44,7 +44,7 @@ config ARCH_RZN1
        bool
        select ARM_AMBA
 
-if ARM
+if ARM && ARCH_RENESAS
 
 #comment "Renesas ARM SoCs System Type"
 
index e1ac4c0..11050e1 100644 (file)
@@ -28,19 +28,6 @@ static struct rcar_sysc_area r8a774c0_areas[] __initdata = {
        { "3dg-b",      0x100, 1, R8A774C0_PD_3DG_B,    R8A774C0_PD_3DG_A },
 };
 
-static void __init rcar_sysc_fix_parent(struct rcar_sysc_area *areas,
-                                       unsigned int num_areas, u8 id,
-                                       int new_parent)
-{
-       unsigned int i;
-
-       for (i = 0; i < num_areas; i++)
-               if (areas[i].isr_bit == id) {
-                       areas[i].parent = new_parent;
-                       return;
-               }
-}
-
 /* Fixups for RZ/G2E ES1.0 revision */
 static const struct soc_device_attribute r8a774c0[] __initconst = {
        { .soc_id = "r8a774c0", .revision = "ES1.0" },
@@ -50,12 +37,10 @@ static const struct soc_device_attribute r8a774c0[] __initconst = {
 static int __init r8a774c0_sysc_init(void)
 {
        if (soc_device_match(r8a774c0)) {
-               rcar_sysc_fix_parent(r8a774c0_areas,
-                                    ARRAY_SIZE(r8a774c0_areas),
-                                    R8A774C0_PD_3DG_A, R8A774C0_PD_3DG_B);
-               rcar_sysc_fix_parent(r8a774c0_areas,
-                                    ARRAY_SIZE(r8a774c0_areas),
-                                    R8A774C0_PD_3DG_B, R8A774C0_PD_ALWAYS_ON);
+               /* Fix incorrect 3DG hierarchy */
+               swap(r8a774c0_areas[6], r8a774c0_areas[7]);
+               r8a774c0_areas[6].parent = R8A774C0_PD_ALWAYS_ON;
+               r8a774c0_areas[7].parent = R8A774C0_PD_3DG_B;
        }
 
        return 0;
index d7e4e18..1ae9af5 100644 (file)
@@ -466,9 +466,9 @@ static int ring_desc_ring_alloc(struct pic32_sqi *sqi)
        int i;
 
        /* allocate coherent DMAable memory for hardware buffer descriptors. */
-       sqi->bd = dma_zalloc_coherent(&sqi->master->dev,
-                                     sizeof(*bd) * PESQI_BD_COUNT,
-                                     &sqi->bd_dma, GFP_KERNEL);
+       sqi->bd = dma_alloc_coherent(&sqi->master->dev,
+                                    sizeof(*bd) * PESQI_BD_COUNT,
+                                    &sqi->bd_dma, GFP_KERNEL);
        if (!sqi->bd) {
                dev_err(&sqi->master->dev, "failed allocating dma buffer\n");
                return -ENOMEM;
index a0802de..6f5afab 100644 (file)
@@ -248,10 +248,10 @@ static void ion_dma_buf_detatch(struct dma_buf *dmabuf,
        struct ion_dma_buf_attachment *a = attachment->priv;
        struct ion_buffer *buffer = dmabuf->priv;
 
-       free_duped_table(a->table);
        mutex_lock(&buffer->lock);
        list_del(&a->list);
        mutex_unlock(&buffer->lock);
+       free_duped_table(a->table);
 
        kfree(a);
 }
index 21a76a8..6027b19 100644 (file)
@@ -1396,8 +1396,7 @@ static int mtk_qdma_tx_alloc_tx(struct mtk_eth *eth)
        if (!ring->tx_buf)
                goto no_tx_mem;
 
-       ring->tx_dma = dma_zalloc_coherent(eth->dev,
-                                         ring->tx_ring_size * sz,
+       ring->tx_dma = dma_alloc_coherent(eth->dev, ring->tx_ring_size * sz,
                                          &ring->tx_phys,
                                          GFP_ATOMIC | __GFP_ZERO);
        if (!ring->tx_dma)
index 2848fa7..d6248ee 100644 (file)
@@ -170,7 +170,7 @@ int cvm_oct_phy_setup_device(struct net_device *dev)
                return -ENODEV;
 
        priv->last_link = 0;
-       phy_start_aneg(phydev);
+       phy_start(phydev);
 
        return 0;
 no_phy:
index 364d6ea..2f90f60 100644 (file)
@@ -154,7 +154,7 @@ void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe)
 
        pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset;
 
-       crypto_ops = try_then_request_module(lib80211_get_crypto_ops("WEP"), "lib80211_crypt_wep");
+       crypto_ops = lib80211_get_crypto_ops("WEP");
 
        if (!crypto_ops)
                return;
@@ -210,7 +210,7 @@ int rtw_wep_decrypt(struct adapter  *padapter, u8 *precvframe)
                void *crypto_private = NULL;
                int status = _SUCCESS;
                const int keyindex = prxattrib->key_index;
-               struct lib80211_crypto_ops *crypto_ops = try_then_request_module(lib80211_get_crypto_ops("WEP"), "lib80211_crypt_wep");
+               struct lib80211_crypto_ops *crypto_ops = lib80211_get_crypto_ops("WEP");
                char iv[4], icv[4];
 
                if (!crypto_ops) {
@@ -1291,7 +1291,7 @@ u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe)
                        struct sk_buff *skb = ((struct recv_frame *)precvframe)->pkt;
                        void *crypto_private = NULL;
                        u8 *key, *pframe = skb->data;
-                       struct lib80211_crypto_ops *crypto_ops = try_then_request_module(lib80211_get_crypto_ops("CCMP"), "lib80211_crypt_ccmp");
+                       struct lib80211_crypto_ops *crypto_ops = lib80211_get_crypto_ops("CCMP");
                        struct security_priv *psecuritypriv = &padapter->securitypriv;
                        char iv[8], icv[8];
 
index 28cbd6b..dfee698 100644 (file)
@@ -35,6 +35,7 @@ static const struct usb_device_id rtw_usb_id_tbl[] = {
        {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
        {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */
        {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */
+       {USB_DEVICE(0x2001, 0x331B)}, /* D-Link DWA-121 rev B1 */
        {USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */
        {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */
        {USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */
index bcc8dfa..9efb4dc 100644 (file)
@@ -850,18 +850,18 @@ enum ieee80211_state {
 #define IP_FMT "%pI4"
 #define IP_ARG(x) (x)
 
-extern __inline int is_multicast_mac_addr(const u8 *addr)
+static inline int is_multicast_mac_addr(const u8 *addr)
 {
         return ((addr[0] != 0xff) && (0x01 & addr[0]));
 }
 
-extern __inline int is_broadcast_mac_addr(const u8 *addr)
+static inline int is_broadcast_mac_addr(const u8 *addr)
 {
        return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&   \
                (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
 }
 
-extern __inline int is_zero_mac_addr(const u8 *addr)
+static inline int is_zero_mac_addr(const u8 *addr)
 {
        return ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) &&   \
                (addr[3] == 0x00) && (addr[4] == 0x00) && (addr[5] == 0x00));
index 7c03b69..6d02904 100644 (file)
@@ -22,7 +22,7 @@ static const struct sdio_device_id sdio_ids[] =
        { SDIO_DEVICE(0x024c, 0xb723), },
        { /* end: all zeroes */                         },
 };
-static const struct acpi_device_id acpi_ids[] __used = {
+static const struct acpi_device_id acpi_ids[] = {
        {"OBDA8723", 0x0000},
        {}
 };
index c92bbd0..005de00 100644 (file)
@@ -265,7 +265,8 @@ static void spk_ttyio_send_xchar(char ch)
                return;
        }
 
-       speakup_tty->ops->send_xchar(speakup_tty, ch);
+       if (speakup_tty->ops->send_xchar)
+               speakup_tty->ops->send_xchar(speakup_tty, ch);
        mutex_unlock(&speakup_tty_mutex);
 }
 
@@ -277,7 +278,8 @@ static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear)
                return;
        }
 
-       speakup_tty->ops->tiocmset(speakup_tty, set, clear);
+       if (speakup_tty->ops->tiocmset)
+               speakup_tty->ops->tiocmset(speakup_tty, set, clear);
        mutex_unlock(&speakup_tty_mutex);
 }
 
index 338b6e9..dd48988 100644 (file)
@@ -407,10 +407,8 @@ create_pagelist(char __user *buf, size_t count, unsigned short type)
        /* Allocate enough storage to hold the page pointers and the page
         * list
         */
-       pagelist = dma_zalloc_coherent(g_dev,
-                                      pagelist_size,
-                                      &dma_addr,
-                                      GFP_KERNEL);
+       pagelist = dma_alloc_coherent(g_dev, pagelist_size, &dma_addr,
+                                     GFP_KERNEL);
 
        vchiq_log_trace(vchiq_arm_log_level, "%s - %pK", __func__, pagelist);
 
index 9e17ec6..53f5a1c 100644 (file)
@@ -446,6 +446,7 @@ remote_event_wait(wait_queue_head_t *wq, struct remote_event *event)
 static inline void
 remote_event_signal_local(wait_queue_head_t *wq, struct remote_event *event)
 {
+       event->fired = 1;
        event->armed = 0;
        wake_up_all(wq);
 }
index 1ab0e85..c9097e7 100644 (file)
@@ -440,12 +440,9 @@ static bool device_init_rings(struct vnt_private *priv)
        void *vir_pool;
 
        /*allocate all RD/TD rings a single pool*/
-       vir_pool = dma_zalloc_coherent(&priv->pcid->dev,
-                                      priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) +
-                                      priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) +
-                                      priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) +
-                                      priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc),
-                                      &priv->pool_dma, GFP_ATOMIC);
+       vir_pool = dma_alloc_coherent(&priv->pcid->dev,
+                                     priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) + priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) + priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc),
+                                     &priv->pool_dma, GFP_ATOMIC);
        if (!vir_pool) {
                dev_err(&priv->pcid->dev, "allocate desc dma memory failed\n");
                return false;
@@ -459,13 +456,9 @@ static bool device_init_rings(struct vnt_private *priv)
        priv->rd1_pool_dma = priv->rd0_pool_dma +
                priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc);
 
-       priv->tx0_bufs = dma_zalloc_coherent(&priv->pcid->dev,
-                                            priv->opts.tx_descs[0] * PKT_BUF_SZ +
-                                            priv->opts.tx_descs[1] * PKT_BUF_SZ +
-                                            CB_BEACON_BUF_SIZE +
-                                            CB_MAX_BUF_SIZE,
-                                            &priv->tx_bufs_dma0,
-                                            GFP_ATOMIC);
+       priv->tx0_bufs = dma_alloc_coherent(&priv->pcid->dev,
+                                           priv->opts.tx_descs[0] * PKT_BUF_SZ + priv->opts.tx_descs[1] * PKT_BUF_SZ + CB_BEACON_BUF_SIZE + CB_MAX_BUF_SIZE,
+                                           &priv->tx_bufs_dma0, GFP_ATOMIC);
        if (!priv->tx0_bufs) {
                dev_err(&priv->pcid->dev, "allocate buf dma memory failed\n");
 
index 70c854d..3d0badc 100644 (file)
@@ -36,7 +36,7 @@ struct wilc_op_mode {
 struct wilc_reg_frame {
        bool reg;
        u8 reg_id;
-       __le32 frame_type;
+       __le16 frame_type;
 } __packed;
 
 struct wilc_drv_handler {
@@ -1744,7 +1744,6 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
                result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
                                              ARRAY_SIZE(wid_list),
                                              wilc_get_vif_idx(vif));
-               kfree(gtk_key);
        } else if (mode == WILC_STATION_MODE) {
                struct wid wid;
 
@@ -1754,9 +1753,9 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
                wid.val = (u8 *)gtk_key;
                result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
                                              wilc_get_vif_idx(vif));
-               kfree(gtk_key);
        }
 
+       kfree(gtk_key);
        return result;
 }
 
index 3c5e9e0..489e5a5 100644 (file)
@@ -1252,21 +1252,22 @@ static u32 init_chip(struct net_device *dev)
                ret = wilc->hif_func->hif_read_reg(wilc, 0x1118, &reg);
                if (!ret) {
                        netdev_err(dev, "fail read reg 0x1118\n");
-                       return ret;
+                       goto release;
                }
                reg |= BIT(0);
                ret = wilc->hif_func->hif_write_reg(wilc, 0x1118, reg);
                if (!ret) {
                        netdev_err(dev, "fail write reg 0x1118\n");
-                       return ret;
+                       goto release;
                }
                ret = wilc->hif_func->hif_write_reg(wilc, 0xc0000, 0x71);
                if (!ret) {
                        netdev_err(dev, "fail write reg 0xc0000\n");
-                       return ret;
+                       goto release;
                }
        }
 
+release:
        release_bus(wilc, WILC_BUS_RELEASE_ONLY);
 
        return ret;
index 984941e..bd15a56 100644 (file)
@@ -714,7 +714,7 @@ static int __init iscsi_target_init_module(void)
                        sizeof(struct iscsi_queue_req),
                        __alignof__(struct iscsi_queue_req), 0, NULL);
        if (!lio_qr_cache) {
-               pr_err("nable to kmem_cache_create() for"
+               pr_err("Unable to kmem_cache_create() for"
                                " lio_qr_cache\n");
                goto bitmap_out;
        }
index 72016d0..8e7fffb 100644 (file)
@@ -852,6 +852,12 @@ static ssize_t pi_prot_type_store(struct config_item *item,
        return count;
 }
 
+/* always zero, but attr needs to remain RW to avoid userspace breakage */
+static ssize_t pi_prot_format_show(struct config_item *item, char *page)
+{
+       return snprintf(page, PAGE_SIZE, "0\n");
+}
+
 static ssize_t pi_prot_format_store(struct config_item *item,
                const char *page, size_t count)
 {
@@ -1132,7 +1138,7 @@ CONFIGFS_ATTR(, emulate_3pc);
 CONFIGFS_ATTR(, emulate_pr);
 CONFIGFS_ATTR(, pi_prot_type);
 CONFIGFS_ATTR_RO(, hw_pi_prot_type);
-CONFIGFS_ATTR_WO(, pi_prot_format);
+CONFIGFS_ATTR(, pi_prot_format);
 CONFIGFS_ATTR(, pi_prot_verify);
 CONFIGFS_ATTR(, enforce_pr_isids);
 CONFIGFS_ATTR(, is_nonrot);
index 1e6d249..5831e0e 100644 (file)
@@ -148,7 +148,7 @@ struct tcmu_dev {
        size_t ring_size;
 
        struct mutex cmdr_lock;
-       struct list_head cmdr_queue;
+       struct list_head qfull_queue;
 
        uint32_t dbi_max;
        uint32_t dbi_thresh;
@@ -159,6 +159,7 @@ struct tcmu_dev {
 
        struct timer_list cmd_timer;
        unsigned int cmd_time_out;
+       struct list_head inflight_queue;
 
        struct timer_list qfull_timer;
        int qfull_time_out;
@@ -179,7 +180,7 @@ struct tcmu_dev {
 struct tcmu_cmd {
        struct se_cmd *se_cmd;
        struct tcmu_dev *tcmu_dev;
-       struct list_head cmdr_queue_entry;
+       struct list_head queue_entry;
 
        uint16_t cmd_id;
 
@@ -192,6 +193,7 @@ struct tcmu_cmd {
        unsigned long deadline;
 
 #define TCMU_CMD_BIT_EXPIRED 0
+#define TCMU_CMD_BIT_INFLIGHT 1
        unsigned long flags;
 };
 /*
@@ -586,7 +588,7 @@ static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd)
        if (!tcmu_cmd)
                return NULL;
 
-       INIT_LIST_HEAD(&tcmu_cmd->cmdr_queue_entry);
+       INIT_LIST_HEAD(&tcmu_cmd->queue_entry);
        tcmu_cmd->se_cmd = se_cmd;
        tcmu_cmd->tcmu_dev = udev;
 
@@ -915,11 +917,13 @@ setup_timer:
                return 0;
 
        tcmu_cmd->deadline = round_jiffies_up(jiffies + msecs_to_jiffies(tmo));
-       mod_timer(timer, tcmu_cmd->deadline);
+       if (!timer_pending(timer))
+               mod_timer(timer, tcmu_cmd->deadline);
+
        return 0;
 }
 
-static int add_to_cmdr_queue(struct tcmu_cmd *tcmu_cmd)
+static int add_to_qfull_queue(struct tcmu_cmd *tcmu_cmd)
 {
        struct tcmu_dev *udev = tcmu_cmd->tcmu_dev;
        unsigned int tmo;
@@ -942,7 +946,7 @@ static int add_to_cmdr_queue(struct tcmu_cmd *tcmu_cmd)
        if (ret)
                return ret;
 
-       list_add_tail(&tcmu_cmd->cmdr_queue_entry, &udev->cmdr_queue);
+       list_add_tail(&tcmu_cmd->queue_entry, &udev->qfull_queue);
        pr_debug("adding cmd %u on dev %s to ring space wait queue\n",
                 tcmu_cmd->cmd_id, udev->name);
        return 0;
@@ -999,7 +1003,7 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err)
        base_command_size = tcmu_cmd_get_base_cmd_size(tcmu_cmd->dbi_cnt);
        command_size = tcmu_cmd_get_cmd_size(tcmu_cmd, base_command_size);
 
-       if (!list_empty(&udev->cmdr_queue))
+       if (!list_empty(&udev->qfull_queue))
                goto queue;
 
        mb = udev->mb_addr;
@@ -1096,13 +1100,16 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err)
        UPDATE_HEAD(mb->cmd_head, command_size, udev->cmdr_size);
        tcmu_flush_dcache_range(mb, sizeof(*mb));
 
+       list_add_tail(&tcmu_cmd->queue_entry, &udev->inflight_queue);
+       set_bit(TCMU_CMD_BIT_INFLIGHT, &tcmu_cmd->flags);
+
        /* TODO: only if FLUSH and FUA? */
        uio_event_notify(&udev->uio_info);
 
        return 0;
 
 queue:
-       if (add_to_cmdr_queue(tcmu_cmd)) {
+       if (add_to_qfull_queue(tcmu_cmd)) {
                *scsi_err = TCM_OUT_OF_RESOURCES;
                return -1;
        }
@@ -1145,6 +1152,8 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
        if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags))
                goto out;
 
+       list_del_init(&cmd->queue_entry);
+
        tcmu_cmd_reset_dbi_cur(cmd);
 
        if (entry->hdr.uflags & TCMU_UFLAG_UNKNOWN_OP) {
@@ -1194,9 +1203,29 @@ out:
        tcmu_free_cmd(cmd);
 }
 
+static void tcmu_set_next_deadline(struct list_head *queue,
+                                  struct timer_list *timer)
+{
+       struct tcmu_cmd *tcmu_cmd, *tmp_cmd;
+       unsigned long deadline = 0;
+
+       list_for_each_entry_safe(tcmu_cmd, tmp_cmd, queue, queue_entry) {
+               if (!time_after(jiffies, tcmu_cmd->deadline)) {
+                       deadline = tcmu_cmd->deadline;
+                       break;
+               }
+       }
+
+       if (deadline)
+               mod_timer(timer, deadline);
+       else
+               del_timer(timer);
+}
+
 static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
 {
        struct tcmu_mailbox *mb;
+       struct tcmu_cmd *cmd;
        int handled = 0;
 
        if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags)) {
@@ -1210,7 +1239,6 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
        while (udev->cmdr_last_cleaned != READ_ONCE(mb->cmd_tail)) {
 
                struct tcmu_cmd_entry *entry = (void *) mb + CMDR_OFF + udev->cmdr_last_cleaned;
-               struct tcmu_cmd *cmd;
 
                tcmu_flush_dcache_range(entry, sizeof(*entry));
 
@@ -1243,7 +1271,7 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
                /* no more pending commands */
                del_timer(&udev->cmd_timer);
 
-               if (list_empty(&udev->cmdr_queue)) {
+               if (list_empty(&udev->qfull_queue)) {
                        /*
                         * no more pending or waiting commands so try to
                         * reclaim blocks if needed.
@@ -1252,6 +1280,8 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
                            tcmu_global_max_blocks)
                                schedule_delayed_work(&tcmu_unmap_work, 0);
                }
+       } else if (udev->cmd_time_out) {
+               tcmu_set_next_deadline(&udev->inflight_queue, &udev->cmd_timer);
        }
 
        return handled;
@@ -1271,7 +1301,7 @@ static int tcmu_check_expired_cmd(int id, void *p, void *data)
        if (!time_after(jiffies, cmd->deadline))
                return 0;
 
-       is_running = list_empty(&cmd->cmdr_queue_entry);
+       is_running = test_bit(TCMU_CMD_BIT_INFLIGHT, &cmd->flags);
        se_cmd = cmd->se_cmd;
 
        if (is_running) {
@@ -1287,9 +1317,9 @@ static int tcmu_check_expired_cmd(int id, void *p, void *data)
                 * target_complete_cmd will translate this to LUN COMM FAILURE
                 */
                scsi_status = SAM_STAT_CHECK_CONDITION;
+               list_del_init(&cmd->queue_entry);
        } else {
-               list_del_init(&cmd->cmdr_queue_entry);
-
+               list_del_init(&cmd->queue_entry);
                idr_remove(&udev->commands, id);
                tcmu_free_cmd(cmd);
                scsi_status = SAM_STAT_TASK_SET_FULL;
@@ -1372,7 +1402,8 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name)
 
        INIT_LIST_HEAD(&udev->node);
        INIT_LIST_HEAD(&udev->timedout_entry);
-       INIT_LIST_HEAD(&udev->cmdr_queue);
+       INIT_LIST_HEAD(&udev->qfull_queue);
+       INIT_LIST_HEAD(&udev->inflight_queue);
        idr_init(&udev->commands);
 
        timer_setup(&udev->qfull_timer, tcmu_qfull_timedout, 0);
@@ -1383,7 +1414,7 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name)
        return &udev->se_dev;
 }
 
-static bool run_cmdr_queue(struct tcmu_dev *udev, bool fail)
+static bool run_qfull_queue(struct tcmu_dev *udev, bool fail)
 {
        struct tcmu_cmd *tcmu_cmd, *tmp_cmd;
        LIST_HEAD(cmds);
@@ -1391,15 +1422,15 @@ static bool run_cmdr_queue(struct tcmu_dev *udev, bool fail)
        sense_reason_t scsi_ret;
        int ret;
 
-       if (list_empty(&udev->cmdr_queue))
+       if (list_empty(&udev->qfull_queue))
                return true;
 
        pr_debug("running %s's cmdr queue forcefail %d\n", udev->name, fail);
 
-       list_splice_init(&udev->cmdr_queue, &cmds);
+       list_splice_init(&udev->qfull_queue, &cmds);
 
-       list_for_each_entry_safe(tcmu_cmd, tmp_cmd, &cmds, cmdr_queue_entry) {
-               list_del_init(&tcmu_cmd->cmdr_queue_entry);
+       list_for_each_entry_safe(tcmu_cmd, tmp_cmd, &cmds, queue_entry) {
+               list_del_init(&tcmu_cmd->queue_entry);
 
                pr_debug("removing cmd %u on dev %s from queue\n",
                         tcmu_cmd->cmd_id, udev->name);
@@ -1437,14 +1468,13 @@ static bool run_cmdr_queue(struct tcmu_dev *udev, bool fail)
                         * cmd was requeued, so just put all cmds back in
                         * the queue
                         */
-                       list_splice_tail(&cmds, &udev->cmdr_queue);
+                       list_splice_tail(&cmds, &udev->qfull_queue);
                        drained = false;
-                       goto done;
+                       break;
                }
        }
-       if (list_empty(&udev->cmdr_queue))
-               del_timer(&udev->qfull_timer);
-done:
+
+       tcmu_set_next_deadline(&udev->qfull_queue, &udev->qfull_timer);
        return drained;
 }
 
@@ -1454,7 +1484,7 @@ static int tcmu_irqcontrol(struct uio_info *info, s32 irq_on)
 
        mutex_lock(&udev->cmdr_lock);
        tcmu_handle_completions(udev);
-       run_cmdr_queue(udev, false);
+       run_qfull_queue(udev, false);
        mutex_unlock(&udev->cmdr_lock);
 
        return 0;
@@ -1982,7 +2012,7 @@ static void tcmu_block_dev(struct tcmu_dev *udev)
        /* complete IO that has executed successfully */
        tcmu_handle_completions(udev);
        /* fail IO waiting to be queued */
-       run_cmdr_queue(udev, true);
+       run_qfull_queue(udev, true);
 
 unlock:
        mutex_unlock(&udev->cmdr_lock);
@@ -1997,7 +2027,7 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level)
        mutex_lock(&udev->cmdr_lock);
 
        idr_for_each_entry(&udev->commands, cmd, i) {
-               if (!list_empty(&cmd->cmdr_queue_entry))
+               if (!test_bit(TCMU_CMD_BIT_INFLIGHT, &cmd->flags))
                        continue;
 
                pr_debug("removing cmd %u on dev %s from ring (is expired %d)\n",
@@ -2006,6 +2036,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)) {
+                       list_del_init(&cmd->queue_entry);
                        if (err_level == 1) {
                                /*
                                 * Userspace was not able to start the
@@ -2666,6 +2697,10 @@ static void check_timedout_devices(void)
 
                mutex_lock(&udev->cmdr_lock);
                idr_for_each(&udev->commands, tcmu_check_expired_cmd, NULL);
+
+               tcmu_set_next_deadline(&udev->inflight_queue, &udev->cmd_timer);
+               tcmu_set_next_deadline(&udev->qfull_queue, &udev->qfull_timer);
+
                mutex_unlock(&udev->cmdr_lock);
 
                spin_lock_bh(&timed_out_udevs_lock);
index dfd2324..6fff161 100644 (file)
@@ -774,7 +774,7 @@ of_cpufreq_cooling_register(struct cpufreq_policy *policy)
 
                cdev = __cpufreq_cooling_register(np, policy, capacitance);
                if (IS_ERR(cdev)) {
-                       pr_err("cpu_cooling: cpu%d is not running as cooling device: %ld\n",
+                       pr_err("cpu_cooling: cpu%d failed to register as cooling device: %ld\n",
                               policy->cpu, PTR_ERR(cdev));
                        cdev = NULL;
                }
index 0582bd1..0ca908d 100644 (file)
@@ -4,7 +4,7 @@
 
 config INT340X_THERMAL
        tristate "ACPI INT340X thermal drivers"
-       depends on X86 && ACPI
+       depends on X86 && ACPI && PCI
        select THERMAL_GOV_USER_SPACE
        select ACPI_THERMAL_REL
        select ACPI_FAN
index 284cf2c..8e1cf4d 100644 (file)
@@ -84,7 +84,12 @@ static ssize_t power_limit_##index##_##suffix##_show(struct device *dev, \
        struct pci_dev *pci_dev; \
        struct platform_device *pdev; \
        struct proc_thermal_device *proc_dev; \
-\
+       \
+       if (proc_thermal_emum_mode == PROC_THERMAL_NONE) { \
+               dev_warn(dev, "Attempted to get power limit before device was initialized!\n"); \
+               return 0; \
+       } \
+       \
        if (proc_thermal_emum_mode == PROC_THERMAL_PLATFORM_DEV) { \
                pdev = to_platform_device(dev); \
                proc_dev = platform_get_drvdata(pdev); \
@@ -298,11 +303,6 @@ static int proc_thermal_add(struct device *dev,
        *priv = proc_priv;
 
        ret = proc_thermal_read_ppcc(proc_priv);
-       if (!ret) {
-               ret = sysfs_create_group(&dev->kobj,
-                                        &power_limit_attribute_group);
-
-       }
        if (ret)
                return ret;
 
@@ -316,8 +316,7 @@ static int proc_thermal_add(struct device *dev,
 
        proc_priv->int340x_zone = int340x_thermal_zone_add(adev, ops);
        if (IS_ERR(proc_priv->int340x_zone)) {
-               ret = PTR_ERR(proc_priv->int340x_zone);
-               goto remove_group;
+               return PTR_ERR(proc_priv->int340x_zone);
        } else
                ret = 0;
 
@@ -331,9 +330,6 @@ static int proc_thermal_add(struct device *dev,
 
 remove_zone:
        int340x_thermal_zone_remove(proc_priv->int340x_zone);
-remove_group:
-       sysfs_remove_group(&proc_priv->dev->kobj,
-                          &power_limit_attribute_group);
 
        return ret;
 }
@@ -364,7 +360,10 @@ static int int3401_add(struct platform_device *pdev)
        platform_set_drvdata(pdev, proc_priv);
        proc_thermal_emum_mode = PROC_THERMAL_PLATFORM_DEV;
 
-       return 0;
+       dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PLATFORM_DEV\n");
+
+       return sysfs_create_group(&pdev->dev.kobj,
+                                        &power_limit_attribute_group);
 }
 
 static int int3401_remove(struct platform_device *pdev)
@@ -423,7 +422,7 @@ static int  proc_thermal_pci_probe(struct pci_dev *pdev,
                proc_priv->soc_dts = intel_soc_dts_iosf_init(
                                        INTEL_SOC_DTS_INTERRUPT_MSI, 2, 0);
 
-               if (proc_priv->soc_dts && pdev->irq) {
+               if (!IS_ERR(proc_priv->soc_dts) && pdev->irq) {
                        ret = pci_enable_msi(pdev);
                        if (!ret) {
                                ret = request_threaded_irq(pdev->irq, NULL,
@@ -441,7 +440,10 @@ static int  proc_thermal_pci_probe(struct pci_dev *pdev,
                        dev_err(&pdev->dev, "No auxiliary DTSs enabled\n");
        }
 
-       return 0;
+       dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PCI\n");
+
+       return sysfs_create_group(&pdev->dev.kobj,
+                                        &power_limit_attribute_group);
 }
 
 static void  proc_thermal_pci_remove(struct pci_dev *pdev)
index 4bfdb4a..2df059c 100644 (file)
@@ -867,14 +867,14 @@ __init *thermal_of_build_thermal_zone(struct device_node *np)
 
        ret = of_property_read_u32(np, "polling-delay-passive", &prop);
        if (ret < 0) {
-               pr_err("missing polling-delay-passive property\n");
+               pr_err("%pOFn: missing polling-delay-passive property\n", np);
                goto free_tz;
        }
        tz->passive_delay = prop;
 
        ret = of_property_read_u32(np, "polling-delay", &prop);
        if (ret < 0) {
-               pr_err("missing polling-delay property\n");
+               pr_err("%pOFn: missing polling-delay property\n", np);
                goto free_tz;
        }
        tz->polling_delay = prop;
index 4164414..8bdf42b 100644 (file)
@@ -597,6 +597,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
                                /* too large for caller's buffer */
                                ret = -EOVERFLOW;
                        } else {
+                               __set_current_state(TASK_RUNNING);
                                if (copy_to_user(buf, rbuf->buf, rbuf->count))
                                        ret = -EFAULT;
                                else
index 189ab12..e441221 100644 (file)
@@ -1070,15 +1070,16 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
 
                        ret = 0;
                }
-       }
 
-       /* Initialise interrupt backoff work if required */
-       if (up->overrun_backoff_time_ms > 0) {
-               uart->overrun_backoff_time_ms = up->overrun_backoff_time_ms;
-               INIT_DELAYED_WORK(&uart->overrun_backoff,
-                                 serial_8250_overrun_backoff_work);
-       } else {
-               uart->overrun_backoff_time_ms = 0;
+               /* Initialise interrupt backoff work if required */
+               if (up->overrun_backoff_time_ms > 0) {
+                       uart->overrun_backoff_time_ms =
+                               up->overrun_backoff_time_ms;
+                       INIT_DELAYED_WORK(&uart->overrun_backoff,
+                                       serial_8250_overrun_backoff_work);
+               } else {
+                       uart->overrun_backoff_time_ms = 0;
+               }
        }
 
        mutex_unlock(&serial_mutex);
index e2c4076..c1fdbc0 100644 (file)
@@ -357,6 +357,9 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
        if (dmacnt == 2) {
                data->dma = devm_kzalloc(&pdev->dev, sizeof(*data->dma),
                                         GFP_KERNEL);
+               if (!data->dma)
+                       return -ENOMEM;
+
                data->dma->fn = mtk8250_dma_filter;
                data->dma->rx_size = MTK_UART_RX_SIZE;
                data->dma->rxconf.src_maxburst = MTK_UART_RX_TRIGGER;
index f80a300..48bd694 100644 (file)
@@ -3420,6 +3420,11 @@ static int
 serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
 {
        int num_iomem, num_port, first_port = -1, i;
+       int rc;
+
+       rc = serial_pci_is_class_communication(dev);
+       if (rc)
+               return rc;
 
        /*
         * Should we try to make guesses for multiport serial devices later?
@@ -3647,10 +3652,6 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
 
        board = &pci_boards[ent->driver_data];
 
-       rc = serial_pci_is_class_communication(dev);
-       if (rc)
-               return rc;
-
        rc = serial_pci_is_blacklisted(dev);
        if (rc)
                return rc;
index 67b9bf3..089a6f2 100644 (file)
@@ -85,6 +85,18 @@ config SERIAL_EARLYCON_ARM_SEMIHOST
          with "earlycon=smh" on the kernel command line. The console is
          enabled when early_param is processed.
 
+config SERIAL_EARLYCON_RISCV_SBI
+       bool "Early console using RISC-V SBI"
+       depends on RISCV
+       select SERIAL_CORE
+       select SERIAL_CORE_CONSOLE
+       select SERIAL_EARLYCON
+       help
+         Support for early debug console using RISC-V SBI. This enables
+         the console before standard serial driver is probed. This is enabled
+         with "earlycon=sbi" on the kernel command line. The console is
+         enabled when early_param is processed.
+
 config SERIAL_SB1250_DUART
        tristate "BCM1xxx on-chip DUART serial support"
        depends on SIBYTE_SB1xxx_SOC=y
index 8c30373..1511e8a 100644 (file)
@@ -7,6 +7,7 @@ obj-$(CONFIG_SERIAL_CORE) += serial_core.o
 
 obj-$(CONFIG_SERIAL_EARLYCON) += earlycon.o
 obj-$(CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST) += earlycon-arm-semihost.o
+obj-$(CONFIG_SERIAL_EARLYCON_RISCV_SBI) += earlycon-riscv-sbi.o
 
 # These Sparc drivers have to appear before others such as 8250
 # which share ttySx minor node space.  Otherwise console device
diff --git a/drivers/tty/serial/earlycon-riscv-sbi.c b/drivers/tty/serial/earlycon-riscv-sbi.c
new file mode 100644 (file)
index 0000000..ce81523
--- /dev/null
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RISC-V SBI based earlycon
+ *
+ * Copyright (C) 2018 Anup Patel <anup@brainfault.org>
+ */
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <asm/sbi.h>
+
+static void sbi_putc(struct uart_port *port, int c)
+{
+       sbi_console_putchar(c);
+}
+
+static void sbi_console_write(struct console *con,
+                             const char *s, unsigned n)
+{
+       struct earlycon_device *dev = con->data;
+       uart_console_write(&dev->port, s, n, sbi_putc);
+}
+
+static int __init early_sbi_setup(struct earlycon_device *device,
+                                 const char *opt)
+{
+       device->con->write = sbi_console_write;
+       return 0;
+}
+EARLYCON_DECLARE(sbi, early_sbi_setup);
index 241a48e..debdd1b 100644 (file)
@@ -1697,7 +1697,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
        }
 
        /* ask the core to calculate the divisor */
-       baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16);
+       baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 4);
 
        spin_lock_irqsave(&sport->port.lock, flags);
 
index e052b69..9de9f0f 100644 (file)
@@ -114,9 +114,9 @@ struct ltq_uart_port {
 
 static inline void asc_update_bits(u32 clear, u32 set, void __iomem *reg)
 {
-       u32 tmp = readl(reg);
+       u32 tmp = __raw_readl(reg);
 
-       writel((tmp & ~clear) | set, reg);
+       __raw_writel((tmp & ~clear) | set, reg);
 }
 
 static inline struct
@@ -144,7 +144,7 @@ lqasc_start_tx(struct uart_port *port)
 static void
 lqasc_stop_rx(struct uart_port *port)
 {
-       writel(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
+       __raw_writel(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
 }
 
 static int
@@ -153,11 +153,12 @@ lqasc_rx_chars(struct uart_port *port)
        struct tty_port *tport = &port->state->port;
        unsigned int ch = 0, rsr = 0, fifocnt;
 
-       fifocnt = readl(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_RXFFLMASK;
+       fifocnt = __raw_readl(port->membase + LTQ_ASC_FSTAT) &
+                 ASCFSTAT_RXFFLMASK;
        while (fifocnt--) {
                u8 flag = TTY_NORMAL;
                ch = readb(port->membase + LTQ_ASC_RBUF);
-               rsr = (readl(port->membase + LTQ_ASC_STATE)
+               rsr = (__raw_readl(port->membase + LTQ_ASC_STATE)
                        & ASCSTATE_ANY) | UART_DUMMY_UER_RX;
                tty_flip_buffer_push(tport);
                port->icount.rx++;
@@ -217,7 +218,7 @@ lqasc_tx_chars(struct uart_port *port)
                return;
        }
 
-       while (((readl(port->membase + LTQ_ASC_FSTAT) &
+       while (((__raw_readl(port->membase + LTQ_ASC_FSTAT) &
                ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF) != 0) {
                if (port->x_char) {
                        writeb(port->x_char, port->membase + LTQ_ASC_TBUF);
@@ -245,7 +246,7 @@ lqasc_tx_int(int irq, void *_port)
        unsigned long flags;
        struct uart_port *port = (struct uart_port *)_port;
        spin_lock_irqsave(&ltq_asc_lock, flags);
-       writel(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR);
+       __raw_writel(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR);
        spin_unlock_irqrestore(&ltq_asc_lock, flags);
        lqasc_start_tx(port);
        return IRQ_HANDLED;
@@ -270,7 +271,7 @@ lqasc_rx_int(int irq, void *_port)
        unsigned long flags;
        struct uart_port *port = (struct uart_port *)_port;
        spin_lock_irqsave(&ltq_asc_lock, flags);
-       writel(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR);
+       __raw_writel(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR);
        lqasc_rx_chars(port);
        spin_unlock_irqrestore(&ltq_asc_lock, flags);
        return IRQ_HANDLED;
@@ -280,7 +281,8 @@ static unsigned int
 lqasc_tx_empty(struct uart_port *port)
 {
        int status;
-       status = readl(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_TXFFLMASK;
+       status = __raw_readl(port->membase + LTQ_ASC_FSTAT) &
+                ASCFSTAT_TXFFLMASK;
        return status ? 0 : TIOCSER_TEMT;
 }
 
@@ -313,12 +315,12 @@ lqasc_startup(struct uart_port *port)
        asc_update_bits(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET),
                port->membase + LTQ_ASC_CLC);
 
-       writel(0, port->membase + LTQ_ASC_PISEL);
-       writel(
+       __raw_writel(0, port->membase + LTQ_ASC_PISEL);
+       __raw_writel(
                ((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) |
                ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU,
                port->membase + LTQ_ASC_TXFCON);
-       writel(
+       __raw_writel(
                ((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK)
                | ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU,
                port->membase + LTQ_ASC_RXFCON);
@@ -350,7 +352,7 @@ lqasc_startup(struct uart_port *port)
                goto err2;
        }
 
-       writel(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX,
+       __raw_writel(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX,
                port->membase + LTQ_ASC_IRNREN);
        return 0;
 
@@ -369,7 +371,7 @@ lqasc_shutdown(struct uart_port *port)
        free_irq(ltq_port->rx_irq, port);
        free_irq(ltq_port->err_irq, port);
 
-       writel(0, port->membase + LTQ_ASC_CON);
+       __raw_writel(0, port->membase + LTQ_ASC_CON);
        asc_update_bits(ASCRXFCON_RXFEN, ASCRXFCON_RXFFLU,
                port->membase + LTQ_ASC_RXFCON);
        asc_update_bits(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU,
@@ -461,13 +463,13 @@ lqasc_set_termios(struct uart_port *port,
        asc_update_bits(ASCCON_BRS, 0, port->membase + LTQ_ASC_CON);
 
        /* now we can write the new baudrate into the register */
-       writel(divisor, port->membase + LTQ_ASC_BG);
+       __raw_writel(divisor, port->membase + LTQ_ASC_BG);
 
        /* turn the baudrate generator back on */
        asc_update_bits(0, ASCCON_R, port->membase + LTQ_ASC_CON);
 
        /* enable rx */
-       writel(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE);
+       __raw_writel(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE);
 
        spin_unlock_irqrestore(&ltq_asc_lock, flags);
 
@@ -578,7 +580,7 @@ lqasc_console_putchar(struct uart_port *port, int ch)
                return;
 
        do {
-               fifofree = (readl(port->membase + LTQ_ASC_FSTAT)
+               fifofree = (__raw_readl(port->membase + LTQ_ASC_FSTAT)
                        & ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF;
        } while (fifofree == 0);
        writeb(ch, port->membase + LTQ_ASC_TBUF);
index a72d6d9..3801660 100644 (file)
@@ -225,7 +225,7 @@ static unsigned int qcom_geni_serial_get_mctrl(struct uart_port *uport)
        unsigned int mctrl = TIOCM_DSR | TIOCM_CAR;
        u32 geni_ios;
 
-       if (uart_console(uport) || !uart_cts_enabled(uport)) {
+       if (uart_console(uport)) {
                mctrl |= TIOCM_CTS;
        } else {
                geni_ios = readl_relaxed(uport->membase + SE_GENI_IOS);
@@ -241,7 +241,7 @@ static void qcom_geni_serial_set_mctrl(struct uart_port *uport,
 {
        u32 uart_manual_rfr = 0;
 
-       if (uart_console(uport) || !uart_cts_enabled(uport))
+       if (uart_console(uport))
                return;
 
        if (!(mctrl & TIOCM_RTS))
index d4cca5b..556f50a 100644 (file)
@@ -130,6 +130,9 @@ static void uart_start(struct tty_struct *tty)
        struct uart_port *port;
        unsigned long flags;
 
+       if (!state)
+               return;
+
        port = uart_port_lock(state, flags);
        __uart_start(tty);
        uart_port_unlock(port, flags);
@@ -550,10 +553,12 @@ static int uart_put_char(struct tty_struct *tty, unsigned char c)
        int ret = 0;
 
        circ = &state->xmit;
-       if (!circ->buf)
+       port = uart_port_lock(state, flags);
+       if (!circ->buf) {
+               uart_port_unlock(port, flags);
                return 0;
+       }
 
-       port = uart_port_lock(state, flags);
        if (port && uart_circ_chars_free(circ) != 0) {
                circ->buf[circ->head] = c;
                circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
@@ -586,11 +591,13 @@ static int uart_write(struct tty_struct *tty,
                return -EL3HLT;
        }
 
+       port = uart_port_lock(state, flags);
        circ = &state->xmit;
-       if (!circ->buf)
+       if (!circ->buf) {
+               uart_port_unlock(port, flags);
                return 0;
+       }
 
-       port = uart_port_lock(state, flags);
        while (port) {
                c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
                if (count < c)
@@ -723,6 +730,9 @@ static void uart_unthrottle(struct tty_struct *tty)
        upstat_t mask = UPSTAT_SYNC_FIFO;
        struct uart_port *port;
 
+       if (!state)
+               return;
+
        port = uart_port_ref(state);
        if (!port)
                return;
index 8df0fd8..64bbeb7 100644 (file)
@@ -1921,7 +1921,7 @@ out_nomem:
 
 static void sci_free_irq(struct sci_port *port)
 {
-       int i;
+       int i, j;
 
        /*
         * Intentionally in reverse order so we iterate over the muxed
@@ -1937,6 +1937,13 @@ static void sci_free_irq(struct sci_port *port)
                if (unlikely(irq < 0))
                        continue;
 
+               /* Check if already freed (irq was muxed) */
+               for (j = 0; j < i; j++)
+                       if (port->irqs[j] == irq)
+                               j = i + 1;
+               if (j > i)
+                       continue;
+
                free_irq(port->irqs[i], port);
                kfree(port->irqstr[i]);
 
index bfe9ad8..21ffcce 100644 (file)
@@ -1256,7 +1256,8 @@ static void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *
 static int tty_reopen(struct tty_struct *tty)
 {
        struct tty_driver *driver = tty->driver;
-       int retval;
+       struct tty_ldisc *ld;
+       int retval = 0;
 
        if (driver->type == TTY_DRIVER_TYPE_PTY &&
            driver->subtype == PTY_TYPE_MASTER)
@@ -1268,13 +1269,18 @@ static int tty_reopen(struct tty_struct *tty)
        if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN))
                return -EBUSY;
 
-       retval = tty_ldisc_lock(tty, 5 * HZ);
-       if (retval)
-               return retval;
+       ld = tty_ldisc_ref_wait(tty);
+       if (ld) {
+               tty_ldisc_deref(ld);
+       } else {
+               retval = tty_ldisc_lock(tty, 5 * HZ);
+               if (retval)
+                       return retval;
 
-       if (!tty->ldisc)
-               retval = tty_ldisc_reinit(tty, tty->termios.c_line);
-       tty_ldisc_unlock(tty);
+               if (!tty->ldisc)
+                       retval = tty_ldisc_reinit(tty, tty->termios.c_line);
+               tty_ldisc_unlock(tty);
+       }
 
        if (retval == 0)
                tty->count++;
@@ -2183,7 +2189,8 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
        ld = tty_ldisc_ref_wait(tty);
        if (!ld)
                return -EIO;
-       ld->ops->receive_buf(tty, &ch, &mbz, 1);
+       if (ld->ops->receive_buf)
+               ld->ops->receive_buf(tty, &ch, &mbz, 1);
        tty_ldisc_deref(ld);
        return 0;
 }
index 41ec8e5..bba7556 100644 (file)
@@ -1272,6 +1272,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
        if (con_is_visible(vc))
                update_screen(vc);
        vt_event_post(VT_EVENT_RESIZE, vc->vc_num, vc->vc_num);
+       notify_update(vc);
        return err;
 }
 
@@ -2764,8 +2765,8 @@ rescan_last_byte:
        con_flush(vc, draw_from, draw_to, &draw_x);
        vc_uniscr_debug_check(vc);
        console_conditional_schedule();
-       console_unlock();
        notify_update(vc);
+       console_unlock();
        return n;
 }
 
@@ -2884,8 +2885,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
        unsigned char c;
        static DEFINE_SPINLOCK(printing_lock);
        const ushort *start;
-       ushort cnt = 0;
-       ushort myx;
+       ushort start_x, cnt;
        int kmsg_console;
 
        /* console busy or not yet initialized */
@@ -2898,10 +2898,6 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
        if (kmsg_console && vc_cons_allocated(kmsg_console - 1))
                vc = vc_cons[kmsg_console - 1].d;
 
-       /* read `x' only after setting currcons properly (otherwise
-          the `x' macro will read the x of the foreground console). */
-       myx = vc->vc_x;
-
        if (!vc_cons_allocated(fg_console)) {
                /* impossible */
                /* printk("vt_console_print: tty %d not allocated ??\n", currcons+1); */
@@ -2916,53 +2912,41 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
                hide_cursor(vc);
 
        start = (ushort *)vc->vc_pos;
-
-       /* Contrived structure to try to emulate original need_wrap behaviour
-        * Problems caused when we have need_wrap set on '\n' character */
+       start_x = vc->vc_x;
+       cnt = 0;
        while (count--) {
                c = *b++;
                if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) {
-                       if (cnt > 0) {
-                               if (con_is_visible(vc))
-                                       vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
-                               vc->vc_x += cnt;
-                               if (vc->vc_need_wrap)
-                                       vc->vc_x--;
-                               cnt = 0;
-                       }
+                       if (cnt && con_is_visible(vc))
+                               vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x);
+                       cnt = 0;
                        if (c == 8) {           /* backspace */
                                bs(vc);
                                start = (ushort *)vc->vc_pos;
-                               myx = vc->vc_x;
+                               start_x = vc->vc_x;
                                continue;
                        }
                        if (c != 13)
                                lf(vc);
                        cr(vc);
                        start = (ushort *)vc->vc_pos;
-                       myx = vc->vc_x;
+                       start_x = vc->vc_x;
                        if (c == 10 || c == 13)
                                continue;
                }
+               vc_uniscr_putc(vc, c);
                scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos);
                notify_write(vc, c);
                cnt++;
-               if (myx == vc->vc_cols - 1) {
-                       vc->vc_need_wrap = 1;
-                       continue;
-               }
-               vc->vc_pos += 2;
-               myx++;
-       }
-       if (cnt > 0) {
-               if (con_is_visible(vc))
-                       vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
-               vc->vc_x += cnt;
-               if (vc->vc_x == vc->vc_cols) {
-                       vc->vc_x--;
+               if (vc->vc_x == vc->vc_cols - 1) {
                        vc->vc_need_wrap = 1;
+               } else {
+                       vc->vc_pos += 2;
+                       vc->vc_x++;
                }
        }
+       if (cnt && con_is_visible(vc))
+               vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x);
        set_cursor(vc);
        notify_update(vc);
 
index e81de9c..9b45aa4 100644 (file)
@@ -316,7 +316,8 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
        if (IS_ERR(data->usbmisc_data))
                return PTR_ERR(data->usbmisc_data);
 
-       if (of_usb_get_phy_mode(dev->of_node) == USBPHY_INTERFACE_MODE_HSIC) {
+       if ((of_usb_get_phy_mode(dev->of_node) == USBPHY_INTERFACE_MODE_HSIC)
+               && data->usbmisc_data) {
                pdata.flags |= CI_HDRC_IMX_IS_HSIC;
                data->usbmisc_data->hsic = 1;
                data->pinctrl = devm_pinctrl_get(dev);
index ed8c62b..739f896 100644 (file)
@@ -1865,6 +1865,13 @@ static const struct usb_device_id acm_ids[] = {
        .driver_info = IGNORE_DEVICE,
        },
 
+       { USB_DEVICE(0x1bc7, 0x0021), /* Telit 3G ACM only composition */
+       .driver_info = SEND_ZERO_PACKET,
+       },
+       { USB_DEVICE(0x1bc7, 0x0023), /* Telit 3G ACM + ECM composition */
+       .driver_info = SEND_ZERO_PACKET,
+       },
+
        /* control interfaces without any protocol set */
        { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
                USB_CDC_PROTO_NONE) },
index 356b05c..f713cec 100644 (file)
@@ -143,9 +143,12 @@ int usb_choose_configuration(struct usb_device *udev)
                        continue;
                }
 
-               if (i > 0 && desc && is_audio(desc) && is_uac3_config(desc)) {
-                       best = c;
-                       break;
+               if (i > 0 && desc && is_audio(desc)) {
+                       if (is_uac3_config(desc)) {
+                               best = c;
+                               break;
+                       }
+                       continue;
                }
 
                /* From the remaining configs, choose the first one whose
index dc7f7fd..c12ac56 100644 (file)
@@ -119,11 +119,6 @@ static const struct attribute_group ports_group = {
        .attrs = ports_attrs,
 };
 
-static const struct attribute_group *ports_groups[] = {
-       &ports_group,
-       NULL
-};
-
 /***************************************
  * Adding & removing ports
  ***************************************/
@@ -307,6 +302,7 @@ static int usbport_trig_notify(struct notifier_block *nb, unsigned long action,
 static int usbport_trig_activate(struct led_classdev *led_cdev)
 {
        struct usbport_trig_data *usbport_data;
+       int err;
 
        usbport_data = kzalloc(sizeof(*usbport_data), GFP_KERNEL);
        if (!usbport_data)
@@ -315,6 +311,9 @@ static int usbport_trig_activate(struct led_classdev *led_cdev)
 
        /* List of ports */
        INIT_LIST_HEAD(&usbport_data->ports);
+       err = sysfs_create_group(&led_cdev->dev->kobj, &ports_group);
+       if (err)
+               goto err_free;
        usb_for_each_dev(usbport_data, usbport_trig_add_usb_dev_ports);
        usbport_trig_update_count(usbport_data);
 
@@ -322,8 +321,11 @@ static int usbport_trig_activate(struct led_classdev *led_cdev)
        usbport_data->nb.notifier_call = usbport_trig_notify;
        led_set_trigger_data(led_cdev, usbport_data);
        usb_register_notify(&usbport_data->nb);
-
        return 0;
+
+err_free:
+       kfree(usbport_data);
+       return err;
 }
 
 static void usbport_trig_deactivate(struct led_classdev *led_cdev)
@@ -335,6 +337,8 @@ static void usbport_trig_deactivate(struct led_classdev *led_cdev)
                usbport_trig_remove_port(usbport_data, port);
        }
 
+       sysfs_remove_group(&led_cdev->dev->kobj, &ports_group);
+
        usb_unregister_notify(&usbport_data->nb);
 
        kfree(usbport_data);
@@ -344,7 +348,6 @@ static struct led_trigger usbport_led_trigger = {
        .name     = "usbport",
        .activate = usbport_trig_activate,
        .deactivate = usbport_trig_deactivate,
-       .groups = ports_groups,
 };
 
 static int __init usbport_trig_init(void)
index 514c521..8bc35d5 100644 (file)
@@ -394,7 +394,8 @@ static const struct usb_device_id usb_quirk_list[] = {
        { USB_DEVICE(0x1a40, 0x0101), .driver_info = USB_QUIRK_HUB_SLOW_RESET },
 
        /* Corsair K70 RGB */
-       { USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT },
+       { USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT |
+         USB_QUIRK_DELAY_CTRL_MSG },
 
        /* Corsair Strafe */
        { USB_DEVICE(0x1b1c, 0x1b15), .driver_info = USB_QUIRK_DELAY_INIT |
index 68ad75a..55ef3cc 100644 (file)
@@ -261,7 +261,7 @@ static void dwc2_gadget_wkup_alert_handler(struct dwc2_hsotg *hsotg)
 
        if (gintsts2 & GINTSTS2_WKUP_ALERT_INT) {
                dev_dbg(hsotg->dev, "%s: Wkup_Alert_Int\n", __func__);
-               dwc2_clear_bit(hsotg, GINTSTS2, GINTSTS2_WKUP_ALERT_INT);
+               dwc2_set_bit(hsotg, GINTSTS2, GINTSTS2_WKUP_ALERT_INT);
                dwc2_set_bit(hsotg, DCTL, DCTL_RMTWKUPSIG);
        }
 }
index cb7fcd7..c1e9ea6 100644 (file)
@@ -78,7 +78,7 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
        for (i = 0; i < exynos->num_clks; i++) {
                ret = clk_prepare_enable(exynos->clks[i]);
                if (ret) {
-                       while (--i > 0)
+                       while (i-- > 0)
                                clk_disable_unprepare(exynos->clks[i]);
                        return ret;
                }
@@ -223,7 +223,7 @@ static int dwc3_exynos_resume(struct device *dev)
        for (i = 0; i < exynos->num_clks; i++) {
                ret = clk_prepare_enable(exynos->clks[i]);
                if (ret) {
-                       while (--i > 0)
+                       while (i-- > 0)
                                clk_disable_unprepare(exynos->clks[i]);
                        return ret;
                }
index 07bd31b..6c9b76b 100644 (file)
@@ -177,6 +177,7 @@ static void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep,
        req->started = false;
        list_del(&req->list);
        req->remaining = 0;
+       req->needs_extra_trb = false;
 
        if (req->request.status == -EINPROGRESS)
                req->request.status = status;
@@ -1118,7 +1119,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
        unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
        unsigned int rem = length % maxp;
 
-       if (rem && usb_endpoint_dir_out(dep->endpoint.desc)) {
+       if ((!length || rem) && usb_endpoint_dir_out(dep->endpoint.desc)) {
                struct dwc3     *dwc = dep->dwc;
                struct dwc3_trb *trb;
 
@@ -1984,6 +1985,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
 
        /* begin to receive SETUP packets */
        dwc->ep0state = EP0_SETUP_PHASE;
+       dwc->link_state = DWC3_LINK_STATE_SS_DIS;
        dwc3_ep0_out_start(dwc);
 
        dwc3_gadget_enable_irq(dwc);
@@ -3379,6 +3381,8 @@ int dwc3_gadget_suspend(struct dwc3 *dwc)
        dwc3_disconnect_gadget(dwc);
        __dwc3_gadget_stop(dwc);
 
+       synchronize_irq(dwc->irq_gadget);
+
        return 0;
 }
 
index 9cdef10..ed68a48 100644 (file)
@@ -838,7 +838,7 @@ static struct usb_function *source_sink_alloc_func(
 
        ss = kzalloc(sizeof(*ss), GFP_KERNEL);
        if (!ss)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        ss_opts =  container_of(fi, struct f_ss_opts, func_inst);
 
index 01b44e1..ccbd1d3 100644 (file)
@@ -172,8 +172,9 @@ static int scratchpad_setup(struct bdc *bdc)
        /* Refer to BDC spec, Table 4 for description of SPB */
        sp_buff_size = 1 << (sp_buff_size + 5);
        dev_dbg(bdc->dev, "Allocating %d bytes for scratchpad\n", sp_buff_size);
-       bdc->scratchpad.buff  =  dma_zalloc_coherent(bdc->dev, sp_buff_size,
-                                       &bdc->scratchpad.sp_dma, GFP_KERNEL);
+       bdc->scratchpad.buff  =  dma_alloc_coherent(bdc->dev, sp_buff_size,
+                                                   &bdc->scratchpad.sp_dma,
+                                                   GFP_KERNEL);
 
        if (!bdc->scratchpad.buff)
                goto fail;
@@ -202,11 +203,9 @@ static int setup_srr(struct bdc *bdc, int interrupter)
        bdc_writel(bdc->regs, BDC_SRRINT(0), BDC_SRR_RWS | BDC_SRR_RST);
        bdc->srr.dqp_index = 0;
        /* allocate the status report descriptors */
-       bdc->srr.sr_bds = dma_zalloc_coherent(
-                                       bdc->dev,
-                                       NUM_SR_ENTRIES * sizeof(struct bdc_bd),
-                                       &bdc->srr.dma_addr,
-                                       GFP_KERNEL);
+       bdc->srr.sr_bds = dma_alloc_coherent(bdc->dev,
+                                            NUM_SR_ENTRIES * sizeof(struct bdc_bd),
+                                            &bdc->srr.dma_addr, GFP_KERNEL);
        if (!bdc->srr.sr_bds)
                return -ENOMEM;
 
index 660878a..b77f312 100644 (file)
@@ -2083,7 +2083,7 @@ static irqreturn_t net2272_irq(int irq, void *_dev)
 #if defined(PLX_PCI_RDK2)
        /* see if PCI int for us by checking irqstat */
        intcsr = readl(dev->rdk2.fpga_base_addr + RDK2_IRQSTAT);
-       if (!intcsr & (1 << NET2272_PCI_IRQ)) {
+       if (!(intcsr & (1 << NET2272_PCI_IRQ))) {
                spin_unlock(&dev->lock);
                return IRQ_NONE;
        }
index f26109e..66ec1fd 100644 (file)
@@ -302,3 +302,4 @@ MODULE_AUTHOR("Chao Xie <chao.xie@marvell.com>");
 MODULE_AUTHOR("Neil Zhang <zhangwm@marvell.com>");
 MODULE_ALIAS("mv-ehci");
 MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(of, ehci_mv_dt_ids);
index 6218bfe..98deb5f 100644 (file)
@@ -596,9 +596,9 @@ static int uhci_start(struct usb_hcd *hcd)
                                           &uhci_debug_operations);
 #endif
 
-       uhci->frame = dma_zalloc_coherent(uhci_dev(uhci),
-                       UHCI_NUMFRAMES * sizeof(*uhci->frame),
-                       &uhci->frame_dma_handle, GFP_KERNEL);
+       uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
+                                        UHCI_NUMFRAMES * sizeof(*uhci->frame),
+                                        &uhci->frame_dma_handle, GFP_KERNEL);
        if (!uhci->frame) {
                dev_err(uhci_dev(uhci),
                        "unable to allocate consistent memory for frame list\n");
index 36a3eb8..8067f17 100644 (file)
@@ -1672,8 +1672,8 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags)
        xhci->dcbaa->dev_context_ptrs[0] = cpu_to_le64(xhci->scratchpad->sp_dma);
        for (i = 0; i < num_sp; i++) {
                dma_addr_t dma;
-               void *buf = dma_zalloc_coherent(dev, xhci->page_size, &dma,
-                               flags);
+               void *buf = dma_alloc_coherent(dev, xhci->page_size, &dma,
+                                              flags);
                if (!buf)
                        goto fail_sp4;
 
@@ -1799,8 +1799,8 @@ int xhci_alloc_erst(struct xhci_hcd *xhci,
        struct xhci_erst_entry *entry;
 
        size = sizeof(struct xhci_erst_entry) * evt_ring->num_segs;
-       erst->entries = dma_zalloc_coherent(xhci_to_hcd(xhci)->self.sysdev,
-                                           size, &erst->erst_dma_addr, flags);
+       erst->entries = dma_alloc_coherent(xhci_to_hcd(xhci)->self.sysdev,
+                                          size, &erst->erst_dma_addr, flags);
        if (!erst->entries)
                return -ENOMEM;
 
index eae8b1b..ffe462a 100644 (file)
@@ -452,13 +452,10 @@ void musb_g_tx(struct musb *musb, u8 epnum)
        }
 
        if (request) {
-               u8      is_dma = 0;
-               bool    short_packet = false;
 
                trace_musb_req_tx(req);
 
                if (dma && (csr & MUSB_TXCSR_DMAENAB)) {
-                       is_dma = 1;
                        csr |= MUSB_TXCSR_P_WZC_BITS;
                        csr &= ~(MUSB_TXCSR_DMAENAB | MUSB_TXCSR_P_UNDERRUN |
                                 MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_AUTOSET);
@@ -476,16 +473,8 @@ void musb_g_tx(struct musb *musb, u8 epnum)
                 */
                if ((request->zero && request->length)
                        && (request->length % musb_ep->packet_sz == 0)
-                       && (request->actual == request->length))
-                               short_packet = true;
+                       && (request->actual == request->length)) {
 
-               if ((musb_dma_inventra(musb) || musb_dma_ux500(musb)) &&
-                       (is_dma && (!dma->desired_mode ||
-                               (request->actual &
-                                       (musb_ep->packet_sz - 1)))))
-                               short_packet = true;
-
-               if (short_packet) {
                        /*
                         * On DMA completion, FIFO may not be
                         * available yet...
index a688f7f..5fc6825 100644 (file)
@@ -346,12 +346,10 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
                                channel->status = MUSB_DMA_STATUS_FREE;
 
                                /* completed */
-                               if ((devctl & MUSB_DEVCTL_HM)
-                                       && (musb_channel->transmit)
-                                       && ((channel->desired_mode == 0)
-                                           || (channel->actual_len &
-                                           (musb_channel->max_packet_sz - 1)))
-                                   ) {
+                               if (musb_channel->transmit &&
+                                       (!channel->desired_mode ||
+                                       (channel->actual_len %
+                                           musb_channel->max_packet_sz))) {
                                        u8  epnum  = musb_channel->epnum;
                                        int offset = musb->io.ep_offset(epnum,
                                                                    MUSB_TXCSR);
@@ -363,11 +361,14 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
                                         */
                                        musb_ep_select(mbase, epnum);
                                        txcsr = musb_readw(mbase, offset);
-                                       txcsr &= ~(MUSB_TXCSR_DMAENAB
+                                       if (channel->desired_mode == 1) {
+                                               txcsr &= ~(MUSB_TXCSR_DMAENAB
                                                        | MUSB_TXCSR_AUTOSET);
-                                       musb_writew(mbase, offset, txcsr);
-                                       /* Send out the packet */
-                                       txcsr &= ~MUSB_TXCSR_DMAMODE;
+                                               musb_writew(mbase, offset, txcsr);
+                                               /* Send out the packet */
+                                               txcsr &= ~MUSB_TXCSR_DMAMODE;
+                                               txcsr |= MUSB_TXCSR_DMAENAB;
+                                       }
                                        txcsr |=  MUSB_TXCSR_TXPKTRDY;
                                        musb_writew(mbase, offset, txcsr);
                                }
index d7312ee..91ea308 100644 (file)
@@ -21,7 +21,7 @@ config AB8500_USB
 
 config FSL_USB2_OTG
        bool "Freescale USB OTG Transceiver Driver"
-       depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_OTG_FSM && PM
+       depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_OTG_FSM=y && PM
        depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't be 'y'
        select USB_PHY
        help
index 27bdb72..f5f0568 100644 (file)
@@ -61,9 +61,6 @@ static int am335x_phy_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       ret = usb_add_phy_dev(&am_phy->usb_phy_gen.phy);
-       if (ret)
-               return ret;
        am_phy->usb_phy_gen.phy.init = am335x_init;
        am_phy->usb_phy_gen.phy.shutdown = am335x_shutdown;
 
@@ -82,7 +79,7 @@ static int am335x_phy_probe(struct platform_device *pdev)
        device_set_wakeup_enable(dev, false);
        phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, am_phy->dr_mode, false);
 
-       return 0;
+       return usb_add_phy_dev(&am_phy->usb_phy_gen.phy);
 }
 
 static int am335x_phy_remove(struct platform_device *pdev)
index 1ab2a61..77ef4c4 100644 (file)
@@ -1783,6 +1783,10 @@ static int ftdi_set_bitmode(struct usb_serial_port *port, u8 mode)
        int result;
        u16 val;
 
+       result = usb_autopm_get_interface(serial->interface);
+       if (result)
+               return result;
+
        val = (mode << 8) | (priv->gpio_output << 4) | priv->gpio_value;
        result = usb_control_msg(serial->dev,
                                 usb_sndctrlpipe(serial->dev, 0),
@@ -1795,6 +1799,8 @@ static int ftdi_set_bitmode(struct usb_serial_port *port, u8 mode)
                        val, result);
        }
 
+       usb_autopm_put_interface(serial->interface);
+
        return result;
 }
 
@@ -1846,9 +1852,15 @@ static int ftdi_read_cbus_pins(struct usb_serial_port *port)
        unsigned char *buf;
        int result;
 
+       result = usb_autopm_get_interface(serial->interface);
+       if (result)
+               return result;
+
        buf = kmalloc(1, GFP_KERNEL);
-       if (!buf)
+       if (!buf) {
+               usb_autopm_put_interface(serial->interface);
                return -ENOMEM;
+       }
 
        result = usb_control_msg(serial->dev,
                                 usb_rcvctrlpipe(serial->dev, 0),
@@ -1863,6 +1875,7 @@ static int ftdi_read_cbus_pins(struct usb_serial_port *port)
        }
 
        kfree(buf);
+       usb_autopm_put_interface(serial->interface);
 
        return result;
 }
index 09e21e8..a68f1fb 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
 /*
        usa26msg.h
 
index dee454c..a19f3fe 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
 /*
        usa28msg.h
 
index 163b2de..8c3970f 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
 /*
        usa49msg.h
 
index 20fa3e2..dcf502f 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
 /*
        usa67msg.h
 
index 86708ec..c4ca0f6 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
 /*
        usa90msg.h
 
index 98e7a5d..bb3f9aa 100644 (file)
@@ -46,6 +46,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) },
        { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) },
        { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ZTEK) },
+       { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_TB) },
        { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
        { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
        { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID),
index 4e2554d..559941c 100644 (file)
@@ -8,6 +8,7 @@
 
 #define PL2303_VENDOR_ID       0x067b
 #define PL2303_PRODUCT_ID      0x2303
+#define PL2303_PRODUCT_ID_TB           0x2304
 #define PL2303_PRODUCT_ID_RSAQ2                0x04bb
 #define PL2303_PRODUCT_ID_DCU11                0x1234
 #define PL2303_PRODUCT_ID_PHAROS       0xaaa0
@@ -20,6 +21,7 @@
 #define PL2303_PRODUCT_ID_MOTOROLA     0x0307
 #define PL2303_PRODUCT_ID_ZTEK         0xe1f1
 
+
 #define ATEN_VENDOR_ID         0x0557
 #define ATEN_VENDOR_ID2                0x0547
 #define ATEN_PRODUCT_ID                0x2008
index 4d02735..edbbb13 100644 (file)
@@ -85,7 +85,8 @@ DEVICE(moto_modem, MOTO_IDS);
 /* Motorola Tetra driver */
 #define MOTOROLA_TETRA_IDS()                   \
        { USB_DEVICE(0x0cad, 0x9011) }, /* Motorola Solutions TETRA PEI */ \
-       { USB_DEVICE(0x0cad, 0x9012) }  /* MTP6550 */
+       { USB_DEVICE(0x0cad, 0x9012) }, /* MTP6550 */ \
+       { USB_DEVICE(0x0cad, 0x9016) }  /* TPG2200 */
 DEVICE(motorola_tetra, MOTOROLA_TETRA_IDS);
 
 /* Novatel Wireless GPS driver */
index fde2e71..a73ea49 100644 (file)
@@ -235,8 +235,12 @@ static int slave_configure(struct scsi_device *sdev)
                if (!(us->fflags & US_FL_NEEDS_CAP16))
                        sdev->try_rc_10_first = 1;
 
-               /* assume SPC3 or latter devices support sense size > 18 */
-               if (sdev->scsi_level > SCSI_SPC_2)
+               /*
+                * assume SPC3 or latter devices support sense size > 18
+                * unless US_FL_BAD_SENSE quirk is specified.
+                */
+               if (sdev->scsi_level > SCSI_SPC_2 &&
+                   !(us->fflags & US_FL_BAD_SENSE))
                        us->fflags |= US_FL_SANE_SENSE;
 
                /*
index f7f83b2..ea0d27a 100644 (file)
@@ -1266,6 +1266,18 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
                US_FL_FIX_CAPACITY ),
 
 /*
+ * Reported by Icenowy Zheng <icenowy@aosc.io>
+ * The SMI SM3350 USB-UFS bridge controller will enter a wrong state
+ * that do not process read/write command if a long sense is requested,
+ * so force to use 18-byte sense.
+ */
+UNUSUAL_DEV(  0x090c, 0x3350, 0x0000, 0xffff,
+               "SMI",
+               "SM3350 UFS-to-USB-Mass-Storage bridge",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_BAD_SENSE ),
+
+/*
  * Reported by Paul Hartman <paul.hartman+linux@gmail.com>
  * This card reader returns "Illegal Request, Logical Block Address
  * Out of Range" for the first READ(10) after a new card is inserted.
index 4bc29b5..f1c39a3 100644 (file)
@@ -2297,7 +2297,8 @@ static unsigned int tcpm_pd_select_pps_apdo(struct tcpm_port *port)
                                              pdo_pps_apdo_max_voltage(snk));
                port->pps_data.max_curr = min_pps_apdo_current(src, snk);
                port->pps_data.out_volt = min(port->pps_data.max_volt,
-                                             port->pps_data.out_volt);
+                                             max(port->pps_data.min_volt,
+                                                 port->pps_data.out_volt));
                port->pps_data.op_curr = min(port->pps_data.max_curr,
                                             port->pps_data.op_curr);
        }
diff --git a/drivers/usb/usbip/README b/drivers/usb/usbip/README
deleted file mode 100644 (file)
index 41a2cf2..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-TODO:
-       - more discussion about the protocol
-       - testing
-       - review of the userspace interface
-       - document the protocol
-
-Please send patches for this code to Greg Kroah-Hartman <greg@kroah.com>
index 228ccdb..b2aa986 100644 (file)
@@ -1,13 +1,9 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
+/* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * VFIO PCI mmap/mmap_fault tracepoints
  *
  * Copyright (C) 2018 IBM Corp.  All rights reserved.
  *     Author: Alexey Kardashevskiy <aik@ozlabs.ru>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #undef TRACE_SYSTEM
@@ -94,7 +90,7 @@ TRACE_EVENT(vfio_pci_npu2_mmap,
 #endif /* _TRACE_VFIO_PCI_H */
 
 #undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_PATH ../../drivers/vfio/pci
 #undef TRACE_INCLUDE_FILE
 #define TRACE_INCLUDE_FILE trace
 
index 054a2cf..32f695f 100644 (file)
@@ -1,14 +1,10 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  * VFIO PCI NVIDIA Whitherspoon GPU support a.k.a. NVLink2.
  *
  * Copyright (C) 2018 IBM Corp.  All rights reserved.
  *     Author: Alexey Kardashevskiy <aik@ozlabs.ru>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
  * Register an on-GPU RAM region for cacheable access.
  *
  * Derived from original vfio_pci_igd.c:
@@ -178,11 +174,11 @@ static int vfio_pci_nvgpu_add_capability(struct vfio_pci_device *vdev,
                struct vfio_pci_region *region, struct vfio_info_cap *caps)
 {
        struct vfio_pci_nvgpu_data *data = region->data;
-       struct vfio_region_info_cap_nvlink2_ssatgt cap = { 0 };
-
-       cap.header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT;
-       cap.header.version = 1;
-       cap.tgt = data->gpu_tgt;
+       struct vfio_region_info_cap_nvlink2_ssatgt cap = {
+               .header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT,
+               .header.version = 1,
+               .tgt = data->gpu_tgt
+       };
 
        return vfio_info_add_capability(caps, &cap.header, sizeof(cap));
 }
@@ -365,18 +361,18 @@ static int vfio_pci_npu2_add_capability(struct vfio_pci_device *vdev,
                struct vfio_pci_region *region, struct vfio_info_cap *caps)
 {
        struct vfio_pci_npu2_data *data = region->data;
-       struct vfio_region_info_cap_nvlink2_ssatgt captgt = { 0 };
-       struct vfio_region_info_cap_nvlink2_lnkspd capspd = { 0 };
+       struct vfio_region_info_cap_nvlink2_ssatgt captgt = {
+               .header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT,
+               .header.version = 1,
+               .tgt = data->gpu_tgt
+       };
+       struct vfio_region_info_cap_nvlink2_lnkspd capspd = {
+               .header.id = VFIO_REGION_INFO_CAP_NVLINK2_LNKSPD,
+               .header.version = 1,
+               .link_speed = data->link_speed
+       };
        int ret;
 
-       captgt.header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT;
-       captgt.header.version = 1;
-       captgt.tgt = data->gpu_tgt;
-
-       capspd.header.id = VFIO_REGION_INFO_CAP_NVLINK2_LNKSPD;
-       capspd.header.version = 1;
-       capspd.link_speed = data->link_speed;
-
        ret = vfio_info_add_capability(caps, &captgt.header, sizeof(captgt));
        if (ret)
                return ret;
index 7651cfb..73652e2 100644 (file)
@@ -878,7 +878,7 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
                return -EINVAL;
        if (!unmap->size || unmap->size & mask)
                return -EINVAL;
-       if (unmap->iova + unmap->size < unmap->iova ||
+       if (unmap->iova + unmap->size - 1 < unmap->iova ||
            unmap->size > SIZE_MAX)
                return -EINVAL;
 
index 36f3d0f..df51a35 100644 (file)
@@ -1236,7 +1236,8 @@ static void handle_rx(struct vhost_net *net)
                if (nvq->done_idx > VHOST_NET_BATCH)
                        vhost_net_signal_used(nvq);
                if (unlikely(vq_log))
-                       vhost_log_write(vq, vq_log, log, vhost_len);
+                       vhost_log_write(vq, vq_log, log, vhost_len,
+                                       vq->iov, in);
                total_len += vhost_len;
                if (unlikely(vhost_exceeds_weight(++recv_pkts, total_len))) {
                        vhost_poll_queue(&vq->poll);
@@ -1336,7 +1337,8 @@ static int vhost_net_open(struct inode *inode, struct file *f)
                n->vqs[i].rx_ring = NULL;
                vhost_net_buf_init(&n->vqs[i].rxq);
        }
-       vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX);
+       vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX,
+                      UIO_MAXIOV + VHOST_NET_BATCH);
 
        vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, EPOLLOUT, dev);
        vhost_poll_init(n->poll + VHOST_NET_VQ_RX, handle_rx_net, EPOLLIN, dev);
index 8e10ab4..23593cb 100644 (file)
@@ -1127,16 +1127,18 @@ vhost_scsi_send_tmf_reject(struct vhost_scsi *vs,
                           struct vhost_virtqueue *vq,
                           struct vhost_scsi_ctx *vc)
 {
-       struct virtio_scsi_ctrl_tmf_resp __user *resp;
        struct virtio_scsi_ctrl_tmf_resp rsp;
+       struct iov_iter iov_iter;
        int ret;
 
        pr_debug("%s\n", __func__);
        memset(&rsp, 0, sizeof(rsp));
        rsp.response = VIRTIO_SCSI_S_FUNCTION_REJECTED;
-       resp = vq->iov[vc->out].iov_base;
-       ret = __copy_to_user(resp, &rsp, sizeof(rsp));
-       if (!ret)
+
+       iov_iter_init(&iov_iter, READ, &vq->iov[vc->out], vc->in, sizeof(rsp));
+
+       ret = copy_to_iter(&rsp, sizeof(rsp), &iov_iter);
+       if (likely(ret == sizeof(rsp)))
                vhost_add_used_and_signal(&vs->dev, vq, vc->head, 0);
        else
                pr_err("Faulted on virtio_scsi_ctrl_tmf_resp\n");
@@ -1147,16 +1149,18 @@ vhost_scsi_send_an_resp(struct vhost_scsi *vs,
                        struct vhost_virtqueue *vq,
                        struct vhost_scsi_ctx *vc)
 {
-       struct virtio_scsi_ctrl_an_resp __user *resp;
        struct virtio_scsi_ctrl_an_resp rsp;
+       struct iov_iter iov_iter;
        int ret;
 
        pr_debug("%s\n", __func__);
        memset(&rsp, 0, sizeof(rsp));   /* event_actual = 0 */
        rsp.response = VIRTIO_SCSI_S_OK;
-       resp = vq->iov[vc->out].iov_base;
-       ret = __copy_to_user(resp, &rsp, sizeof(rsp));
-       if (!ret)
+
+       iov_iter_init(&iov_iter, READ, &vq->iov[vc->out], vc->in, sizeof(rsp));
+
+       ret = copy_to_iter(&rsp, sizeof(rsp), &iov_iter);
+       if (likely(ret == sizeof(rsp)))
                vhost_add_used_and_signal(&vs->dev, vq, vc->head, 0);
        else
                pr_err("Faulted on virtio_scsi_ctrl_an_resp\n");
@@ -1623,7 +1627,7 @@ static int vhost_scsi_open(struct inode *inode, struct file *f)
                vqs[i] = &vs->vqs[i].vq;
                vs->vqs[i].vq.handle_kick = vhost_scsi_handle_kick;
        }
-       vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ);
+       vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ, UIO_MAXIOV);
 
        vhost_scsi_init_inflight(vs, NULL);
 
index 9f7942c..24a129f 100644 (file)
@@ -390,9 +390,9 @@ static long vhost_dev_alloc_iovecs(struct vhost_dev *dev)
                vq->indirect = kmalloc_array(UIO_MAXIOV,
                                             sizeof(*vq->indirect),
                                             GFP_KERNEL);
-               vq->log = kmalloc_array(UIO_MAXIOV, sizeof(*vq->log),
+               vq->log = kmalloc_array(dev->iov_limit, sizeof(*vq->log),
                                        GFP_KERNEL);
-               vq->heads = kmalloc_array(UIO_MAXIOV, sizeof(*vq->heads),
+               vq->heads = kmalloc_array(dev->iov_limit, sizeof(*vq->heads),
                                          GFP_KERNEL);
                if (!vq->indirect || !vq->log || !vq->heads)
                        goto err_nomem;
@@ -414,7 +414,7 @@ static void vhost_dev_free_iovecs(struct vhost_dev *dev)
 }
 
 void vhost_dev_init(struct vhost_dev *dev,
-                   struct vhost_virtqueue **vqs, int nvqs)
+                   struct vhost_virtqueue **vqs, int nvqs, int iov_limit)
 {
        struct vhost_virtqueue *vq;
        int i;
@@ -427,6 +427,7 @@ void vhost_dev_init(struct vhost_dev *dev,
        dev->iotlb = NULL;
        dev->mm = NULL;
        dev->worker = NULL;
+       dev->iov_limit = iov_limit;
        init_llist_head(&dev->work_list);
        init_waitqueue_head(&dev->wait);
        INIT_LIST_HEAD(&dev->read_list);
@@ -1034,8 +1035,10 @@ ssize_t vhost_chr_write_iter(struct vhost_dev *dev,
        int type, ret;
 
        ret = copy_from_iter(&type, sizeof(type), from);
-       if (ret != sizeof(type))
+       if (ret != sizeof(type)) {
+               ret = -EINVAL;
                goto done;
+       }
 
        switch (type) {
        case VHOST_IOTLB_MSG:
@@ -1054,8 +1057,10 @@ ssize_t vhost_chr_write_iter(struct vhost_dev *dev,
 
        iov_iter_advance(from, offset);
        ret = copy_from_iter(&msg, sizeof(msg), from);
-       if (ret != sizeof(msg))
+       if (ret != sizeof(msg)) {
+               ret = -EINVAL;
                goto done;
+       }
        if (vhost_process_iotlb_msg(dev, &msg)) {
                ret = -EFAULT;
                goto done;
@@ -1733,13 +1738,87 @@ static int log_write(void __user *log_base,
        return r;
 }
 
+static int log_write_hva(struct vhost_virtqueue *vq, u64 hva, u64 len)
+{
+       struct vhost_umem *umem = vq->umem;
+       struct vhost_umem_node *u;
+       u64 start, end, l, min;
+       int r;
+       bool hit = false;
+
+       while (len) {
+               min = len;
+               /* More than one GPAs can be mapped into a single HVA. So
+                * iterate all possible umems here to be safe.
+                */
+               list_for_each_entry(u, &umem->umem_list, link) {
+                       if (u->userspace_addr > hva - 1 + len ||
+                           u->userspace_addr - 1 + u->size < hva)
+                               continue;
+                       start = max(u->userspace_addr, hva);
+                       end = min(u->userspace_addr - 1 + u->size,
+                                 hva - 1 + len);
+                       l = end - start + 1;
+                       r = log_write(vq->log_base,
+                                     u->start + start - u->userspace_addr,
+                                     l);
+                       if (r < 0)
+                               return r;
+                       hit = true;
+                       min = min(l, min);
+               }
+
+               if (!hit)
+                       return -EFAULT;
+
+               len -= min;
+               hva += min;
+       }
+
+       return 0;
+}
+
+static int log_used(struct vhost_virtqueue *vq, u64 used_offset, u64 len)
+{
+       struct iovec iov[64];
+       int i, ret;
+
+       if (!vq->iotlb)
+               return log_write(vq->log_base, vq->log_addr + used_offset, len);
+
+       ret = translate_desc(vq, (uintptr_t)vq->used + used_offset,
+                            len, iov, 64, VHOST_ACCESS_WO);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < ret; i++) {
+               ret = log_write_hva(vq, (uintptr_t)iov[i].iov_base,
+                                   iov[i].iov_len);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
-                   unsigned int log_num, u64 len)
+                   unsigned int log_num, u64 len, struct iovec *iov, int count)
 {
        int i, r;
 
        /* Make sure data written is seen before log. */
        smp_wmb();
+
+       if (vq->iotlb) {
+               for (i = 0; i < count; i++) {
+                       r = log_write_hva(vq, (uintptr_t)iov[i].iov_base,
+                                         iov[i].iov_len);
+                       if (r < 0)
+                               return r;
+               }
+               return 0;
+       }
+
        for (i = 0; i < log_num; ++i) {
                u64 l = min(log[i].len, len);
                r = log_write(vq->log_base, log[i].addr, l);
@@ -1769,9 +1848,8 @@ static int vhost_update_used_flags(struct vhost_virtqueue *vq)
                smp_wmb();
                /* Log used flag write. */
                used = &vq->used->flags;
-               log_write(vq->log_base, vq->log_addr +
-                         (used - (void __user *)vq->used),
-                         sizeof vq->used->flags);
+               log_used(vq, (used - (void __user *)vq->used),
+                        sizeof vq->used->flags);
                if (vq->log_ctx)
                        eventfd_signal(vq->log_ctx, 1);
        }
@@ -1789,9 +1867,8 @@ static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event)
                smp_wmb();
                /* Log avail event write */
                used = vhost_avail_event(vq);
-               log_write(vq->log_base, vq->log_addr +
-                         (used - (void __user *)vq->used),
-                         sizeof *vhost_avail_event(vq));
+               log_used(vq, (used - (void __user *)vq->used),
+                        sizeof *vhost_avail_event(vq));
                if (vq->log_ctx)
                        eventfd_signal(vq->log_ctx, 1);
        }
@@ -2191,10 +2268,8 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq,
                /* Make sure data is seen before log. */
                smp_wmb();
                /* Log used ring entry write. */
-               log_write(vq->log_base,
-                         vq->log_addr +
-                          ((void __user *)used - (void __user *)vq->used),
-                         count * sizeof *used);
+               log_used(vq, ((void __user *)used - (void __user *)vq->used),
+                        count * sizeof *used);
        }
        old = vq->last_used_idx;
        new = (vq->last_used_idx += count);
@@ -2236,9 +2311,8 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads,
                /* Make sure used idx is seen before log. */
                smp_wmb();
                /* Log used index update. */
-               log_write(vq->log_base,
-                         vq->log_addr + offsetof(struct vring_used, idx),
-                         sizeof vq->used->idx);
+               log_used(vq, offsetof(struct vring_used, idx),
+                        sizeof vq->used->idx);
                if (vq->log_ctx)
                        eventfd_signal(vq->log_ctx, 1);
        }
index 466ef75..9490e7d 100644 (file)
@@ -170,9 +170,11 @@ struct vhost_dev {
        struct list_head read_list;
        struct list_head pending_list;
        wait_queue_head_t wait;
+       int iov_limit;
 };
 
-void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs, int nvqs);
+void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs,
+                   int nvqs, int iov_limit);
 long vhost_dev_set_owner(struct vhost_dev *dev);
 bool vhost_dev_has_owner(struct vhost_dev *dev);
 long vhost_dev_check_owner(struct vhost_dev *);
@@ -205,7 +207,8 @@ bool vhost_vq_avail_empty(struct vhost_dev *, struct vhost_virtqueue *);
 bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *);
 
 int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
-                   unsigned int log_num, u64 len);
+                   unsigned int log_num, u64 len,
+                   struct iovec *iov, int count);
 int vq_iotlb_prefetch(struct vhost_virtqueue *vq);
 
 struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type);
index bc42d38..bb5fc0e 100644 (file)
@@ -531,7 +531,7 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file)
        vsock->vqs[VSOCK_VQ_TX].handle_kick = vhost_vsock_handle_tx_kick;
        vsock->vqs[VSOCK_VQ_RX].handle_kick = vhost_vsock_handle_rx_kick;
 
-       vhost_dev_init(&vsock->dev, vqs, ARRAY_SIZE(vsock->vqs));
+       vhost_dev_init(&vsock->dev, vqs, ARRAY_SIZE(vsock->vqs), UIO_MAXIOV);
 
        file->private_data = vsock;
        spin_lock_init(&vsock->send_pkt_list_lock);
@@ -642,7 +642,7 @@ static int vhost_vsock_set_cid(struct vhost_vsock *vsock, u64 guest_cid)
                hash_del_rcu(&vsock->hash);
 
        vsock->guest_cid = guest_cid;
-       hash_add_rcu(vhost_vsock_hash, &vsock->hash, guest_cid);
+       hash_add_rcu(vhost_vsock_hash, &vsock->hash, vsock->guest_cid);
        mutex_unlock(&vhost_vsock_mutex);
 
        return 0;
index 6d8dc2c..51e0c4b 100644 (file)
@@ -174,7 +174,7 @@ static int pm860x_backlight_dt_init(struct platform_device *pdev,
                return -ENODEV;
        }
        for_each_child_of_node(nproot, np) {
-               if (!of_node_cmp(np->name, name)) {
+               if (of_node_name_eq(np, name)) {
                        of_property_read_u32(np, "marvell,88pm860x-iset",
                                             &iset);
                        data->iset = PM8606_WLED_CURRENT(iset);
index f9ef067..feb9076 100644 (file)
@@ -30,6 +30,7 @@ struct pwm_bl_data {
        struct device           *dev;
        unsigned int            lth_brightness;
        unsigned int            *levels;
+       bool                    enabled;
        struct regulator        *power_supply;
        struct gpio_desc        *enable_gpio;
        unsigned int            scale;
@@ -50,7 +51,7 @@ static void pwm_backlight_power_on(struct pwm_bl_data *pb)
        int err;
 
        pwm_get_state(pb->pwm, &state);
-       if (state.enabled)
+       if (pb->enabled)
                return;
 
        err = regulator_enable(pb->power_supply);
@@ -65,6 +66,8 @@ static void pwm_backlight_power_on(struct pwm_bl_data *pb)
 
        if (pb->enable_gpio)
                gpiod_set_value_cansleep(pb->enable_gpio, 1);
+
+       pb->enabled = true;
 }
 
 static void pwm_backlight_power_off(struct pwm_bl_data *pb)
@@ -72,7 +75,7 @@ static void pwm_backlight_power_off(struct pwm_bl_data *pb)
        struct pwm_state state;
 
        pwm_get_state(pb->pwm, &state);
-       if (!state.enabled)
+       if (!pb->enabled)
                return;
 
        if (pb->enable_gpio)
@@ -86,6 +89,7 @@ static void pwm_backlight_power_off(struct pwm_bl_data *pb)
        pwm_apply_state(pb->pwm, &state);
 
        regulator_disable(pb->power_supply);
+       pb->enabled = false;
 }
 
 static int compute_duty_cycle(struct pwm_bl_data *pb, int brightness)
@@ -269,6 +273,16 @@ static int pwm_backlight_parse_dt(struct device *dev,
        memset(data, 0, sizeof(*data));
 
        /*
+        * These values are optional and set as 0 by default, the out values
+        * are modified only if a valid u32 value can be decoded.
+        */
+       of_property_read_u32(node, "post-pwm-on-delay-ms",
+                            &data->post_pwm_on_delay);
+       of_property_read_u32(node, "pwm-off-delay-ms", &data->pwm_off_delay);
+
+       data->enable_gpio = -EINVAL;
+
+       /*
         * Determine the number of brightness levels, if this property is not
         * set a default table of brightness levels will be used.
         */
@@ -380,15 +394,6 @@ static int pwm_backlight_parse_dt(struct device *dev,
                data->max_brightness--;
        }
 
-       /*
-        * These values are optional and set as 0 by default, the out values
-        * are modified only if a valid u32 value can be decoded.
-        */
-       of_property_read_u32(node, "post-pwm-on-delay-ms",
-                            &data->post_pwm_on_delay);
-       of_property_read_u32(node, "pwm-off-delay-ms", &data->pwm_off_delay);
-
-       data->enable_gpio = -EINVAL;
        return 0;
 }
 
@@ -483,6 +488,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
        pb->check_fb = data->check_fb;
        pb->exit = data->exit;
        pb->dev = &pdev->dev;
+       pb->enabled = false;
        pb->post_pwm_on_delay = data->post_pwm_on_delay;
        pb->pwm_off_delay = data->pwm_off_delay;
 
index 09731b2..c6b3bdb 100644 (file)
@@ -271,6 +271,7 @@ static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
+       c->vc_origin = c->vc_visible_origin;
        vgacon_scrollback_cur->save = 0;
 
        if (!vga_is_gfx && !vgacon_scrollback_cur->restore) {
@@ -287,8 +288,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
        int start, end, count, soff;
 
        if (!lines) {
-               c->vc_visible_origin = c->vc_origin;
-               vga_set_mem_top(c);
+               vgacon_restore_screen(c);
                return;
        }
 
@@ -298,6 +298,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
        if (!vgacon_scrollback_cur->save) {
                vgacon_cursor(c, CM_ERASE);
                vgacon_save_screen(c);
+               c->vc_origin = (unsigned long)c->vc_screenbuf;
                vgacon_scrollback_cur->save = 1;
        }
 
@@ -335,7 +336,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
                int copysize;
 
                int diff = c->vc_rows - count;
-               void *d = (void *) c->vc_origin;
+               void *d = (void *) c->vc_visible_origin;
                void *s = (void *) c->vc_screenbuf;
 
                count *= c->vc_size_row;
index 8976190..bfa1360 100644 (file)
@@ -510,6 +510,13 @@ static int __init fb_console_setup(char *this_opt)
                        continue;
                }
 #endif
+
+               if (!strncmp(options, "logo-pos:", 9)) {
+                       options += 9;
+                       if (!strcmp(options, "center"))
+                               fb_center_logo = true;
+                       continue;
+               }
        }
        return 1;
 }
index 558ed2e..cb43a22 100644 (file)
@@ -53,6 +53,9 @@ EXPORT_SYMBOL(registered_fb);
 int num_registered_fb __read_mostly;
 EXPORT_SYMBOL(num_registered_fb);
 
+bool fb_center_logo __read_mostly;
+EXPORT_SYMBOL(fb_center_logo);
+
 static struct fb_info *get_fb_info(unsigned int idx)
 {
        struct fb_info *fb_info;
@@ -506,8 +509,7 @@ static int fb_show_logo_line(struct fb_info *info, int rotate,
                fb_set_logo(info, logo, logo_new, fb_logo.depth);
        }
 
-#ifdef CONFIG_FB_LOGO_CENTER
-       {
+       if (fb_center_logo) {
                int xres = info->var.xres;
                int yres = info->var.yres;
 
@@ -520,11 +522,11 @@ static int fb_show_logo_line(struct fb_info *info, int rotate,
                        --n;
                image.dx = (xres - n * (logo->width + 8) - 8) / 2;
                image.dy = y ?: (yres - logo->height) / 2;
+       } else {
+               image.dx = 0;
+               image.dy = y;
        }
-#else
-       image.dx = 0;
-       image.dy = y;
-#endif
+
        image.width = logo->width;
        image.height = logo->height;
 
@@ -684,9 +686,8 @@ int fb_prepare_logo(struct fb_info *info, int rotate)
        }
 
        height = fb_logo.logo->height;
-#ifdef CONFIG_FB_LOGO_CENTER
-       height += (yres - fb_logo.logo->height) / 2;
-#endif
+       if (fb_center_logo)
+               height += (yres - fb_logo.logo->height) / 2;
 
        return fb_prepare_extra_logos(info, height, yres);
 }
index a74096c..43f2a48 100644 (file)
@@ -1446,9 +1446,9 @@ static int fb_probe(struct platform_device *device)
                da8xx_fb_fix.line_length - 1;
 
        /* allocate palette buffer */
-       par->v_palette_base = dma_zalloc_coherent(NULL, PALETTE_SIZE,
-                                                 &par->p_palette_base,
-                                                 GFP_KERNEL | GFP_DMA);
+       par->v_palette_base = dma_alloc_coherent(NULL, PALETTE_SIZE,
+                                                &par->p_palette_base,
+                                                GFP_KERNEL | GFP_DMA);
        if (!par->v_palette_base) {
                dev_err(&device->dev,
                        "GLCD: kmalloc for palette buffer failed\n");
index 31f769d..057d3cd 100644 (file)
@@ -318,28 +318,28 @@ static void __iomem *offb_map_reg(struct device_node *np, int index,
 }
 
 static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp,
-                                   const char *name, unsigned long address)
+                                   unsigned long address)
 {
        struct offb_par *par = (struct offb_par *) info->par;
 
-       if (dp && !strncmp(name, "ATY,Rage128", 11)) {
+       if (of_node_name_prefix(dp, "ATY,Rage128")) {
                par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
                if (par->cmap_adr)
                        par->cmap_type = cmap_r128;
-       } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12)
-                         || !strncmp(name, "ATY,RageM3p12A", 14))) {
+       } else if (of_node_name_prefix(dp, "ATY,RageM3pA") ||
+                  of_node_name_prefix(dp, "ATY,RageM3p12A")) {
                par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
                if (par->cmap_adr)
                        par->cmap_type = cmap_M3A;
-       } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) {
+       } else if (of_node_name_prefix(dp, "ATY,RageM3pB")) {
                par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
                if (par->cmap_adr)
                        par->cmap_type = cmap_M3B;
-       } else if (dp && !strncmp(name, "ATY,Rage6", 9)) {
+       } else if (of_node_name_prefix(dp, "ATY,Rage6")) {
                par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff);
                if (par->cmap_adr)
                        par->cmap_type = cmap_radeon;
-       } else if (!strncmp(name, "ATY,", 4)) {
+       } else if (of_node_name_prefix(dp, "ATY,")) {
                unsigned long base = address & 0xff000000UL;
                par->cmap_adr =
                        ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
@@ -350,7 +350,7 @@ static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp
                par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
                if (par->cmap_adr)
                        par->cmap_type = cmap_gxt2000;
-       } else if (dp && !strncmp(name, "vga,Display-", 12)) {
+       } else if (of_node_name_prefix(dp, "vga,Display-")) {
                /* Look for AVIVO initialized by SLOF */
                struct device_node *pciparent = of_get_parent(dp);
                const u32 *vid, *did;
@@ -438,7 +438,7 @@ static void __init offb_init_fb(const char *name,
 
        par->cmap_type = cmap_unknown;
        if (depth == 8)
-               offb_init_palette_hacks(info, dp, name, address);
+               offb_init_palette_hacks(info, dp, address);
        else
                fix->visual = FB_VISUAL_TRUECOLOR;
 
index 53f9361..8e23160 100644 (file)
@@ -609,6 +609,8 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
 
        int r = 0;
 
+       memset(&p, 0, sizeof(p));
+
        switch (cmd) {
        case OMAPFB_SYNC_GFX:
                DBG("ioctl SYNC_GFX\n");
index 1e972c4..d1f6196 100644 (file)
@@ -10,15 +10,6 @@ menuconfig LOGO
 
 if LOGO
 
-config FB_LOGO_CENTER
-       bool "Center the logo"
-       depends on FB=y
-       help
-         When this option is selected, the bootup logo is centered both
-         horizontally and vertically. If more than one logo is displayed
-         due to multiple CPUs, the collected line of logos is centered
-         as a whole.
-
 config FB_LOGO_EXTRA
        bool
        depends on FB=y
index 728ecd1..fb12fe2 100644 (file)
@@ -61,6 +61,10 @@ enum virtio_balloon_vq {
        VIRTIO_BALLOON_VQ_MAX
 };
 
+enum virtio_balloon_config_read {
+       VIRTIO_BALLOON_CONFIG_READ_CMD_ID = 0,
+};
+
 struct virtio_balloon {
        struct virtio_device *vdev;
        struct virtqueue *inflate_vq, *deflate_vq, *stats_vq, *free_page_vq;
@@ -77,14 +81,20 @@ struct virtio_balloon {
        /* Prevent updating balloon when it is being canceled. */
        spinlock_t stop_update_lock;
        bool stop_update;
+       /* Bitmap to indicate if reading the related config fields are needed */
+       unsigned long config_read_bitmap;
 
        /* The list of allocated free pages, waiting to be given back to mm */
        struct list_head free_page_list;
        spinlock_t free_page_list_lock;
        /* The number of free page blocks on the above list */
        unsigned long num_free_page_blocks;
-       /* The cmd id received from host */
-       u32 cmd_id_received;
+       /*
+        * The cmd id received from host.
+        * Read it via virtio_balloon_cmd_id_received to get the latest value
+        * sent from host.
+        */
+       u32 cmd_id_received_cache;
        /* The cmd id that is actively in use */
        __virtio32 cmd_id_active;
        /* Buffer to store the stop sign */
@@ -390,37 +400,31 @@ static unsigned long return_free_pages_to_mm(struct virtio_balloon *vb,
        return num_returned;
 }
 
+static void virtio_balloon_queue_free_page_work(struct virtio_balloon *vb)
+{
+       if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT))
+               return;
+
+       /* No need to queue the work if the bit was already set. */
+       if (test_and_set_bit(VIRTIO_BALLOON_CONFIG_READ_CMD_ID,
+                            &vb->config_read_bitmap))
+               return;
+
+       queue_work(vb->balloon_wq, &vb->report_free_page_work);
+}
+
 static void virtballoon_changed(struct virtio_device *vdev)
 {
        struct virtio_balloon *vb = vdev->priv;
        unsigned long flags;
-       s64 diff = towards_target(vb);
-
-       if (diff) {
-               spin_lock_irqsave(&vb->stop_update_lock, flags);
-               if (!vb->stop_update)
-                       queue_work(system_freezable_wq,
-                                  &vb->update_balloon_size_work);
-               spin_unlock_irqrestore(&vb->stop_update_lock, flags);
-       }
 
-       if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) {
-               virtio_cread(vdev, struct virtio_balloon_config,
-                            free_page_report_cmd_id, &vb->cmd_id_received);
-               if (vb->cmd_id_received == VIRTIO_BALLOON_CMD_ID_DONE) {
-                       /* Pass ULONG_MAX to give back all the free pages */
-                       return_free_pages_to_mm(vb, ULONG_MAX);
-               } else if (vb->cmd_id_received != VIRTIO_BALLOON_CMD_ID_STOP &&
-                          vb->cmd_id_received !=
-                          virtio32_to_cpu(vdev, vb->cmd_id_active)) {
-                       spin_lock_irqsave(&vb->stop_update_lock, flags);
-                       if (!vb->stop_update) {
-                               queue_work(vb->balloon_wq,
-                                          &vb->report_free_page_work);
-                       }
-                       spin_unlock_irqrestore(&vb->stop_update_lock, flags);
-               }
+       spin_lock_irqsave(&vb->stop_update_lock, flags);
+       if (!vb->stop_update) {
+               queue_work(system_freezable_wq,
+                          &vb->update_balloon_size_work);
+               virtio_balloon_queue_free_page_work(vb);
        }
+       spin_unlock_irqrestore(&vb->stop_update_lock, flags);
 }
 
 static void update_balloon_size(struct virtio_balloon *vb)
@@ -527,6 +531,17 @@ static int init_vqs(struct virtio_balloon *vb)
        return 0;
 }
 
+static u32 virtio_balloon_cmd_id_received(struct virtio_balloon *vb)
+{
+       if (test_and_clear_bit(VIRTIO_BALLOON_CONFIG_READ_CMD_ID,
+                              &vb->config_read_bitmap))
+               virtio_cread(vb->vdev, struct virtio_balloon_config,
+                            free_page_report_cmd_id,
+                            &vb->cmd_id_received_cache);
+
+       return vb->cmd_id_received_cache;
+}
+
 static int send_cmd_id_start(struct virtio_balloon *vb)
 {
        struct scatterlist sg;
@@ -537,7 +552,8 @@ static int send_cmd_id_start(struct virtio_balloon *vb)
        while (virtqueue_get_buf(vq, &unused))
                ;
 
-       vb->cmd_id_active = cpu_to_virtio32(vb->vdev, vb->cmd_id_received);
+       vb->cmd_id_active = virtio32_to_cpu(vb->vdev,
+                                       virtio_balloon_cmd_id_received(vb));
        sg_init_one(&sg, &vb->cmd_id_active, sizeof(vb->cmd_id_active));
        err = virtqueue_add_outbuf(vq, &sg, 1, &vb->cmd_id_active, GFP_KERNEL);
        if (!err)
@@ -620,7 +636,8 @@ static int send_free_pages(struct virtio_balloon *vb)
                 * stop the reporting.
                 */
                cmd_id_active = virtio32_to_cpu(vb->vdev, vb->cmd_id_active);
-               if (cmd_id_active != vb->cmd_id_received)
+               if (unlikely(cmd_id_active !=
+                            virtio_balloon_cmd_id_received(vb)))
                        break;
 
                /*
@@ -637,11 +654,9 @@ static int send_free_pages(struct virtio_balloon *vb)
        return 0;
 }
 
-static void report_free_page_func(struct work_struct *work)
+static void virtio_balloon_report_free_page(struct virtio_balloon *vb)
 {
        int err;
-       struct virtio_balloon *vb = container_of(work, struct virtio_balloon,
-                                                report_free_page_work);
        struct device *dev = &vb->vdev->dev;
 
        /* Start by sending the received cmd id to host with an outbuf. */
@@ -659,6 +674,23 @@ static void report_free_page_func(struct work_struct *work)
                dev_err(dev, "Failed to send a stop id, err = %d\n", err);
 }
 
+static void report_free_page_func(struct work_struct *work)
+{
+       struct virtio_balloon *vb = container_of(work, struct virtio_balloon,
+                                                report_free_page_work);
+       u32 cmd_id_received;
+
+       cmd_id_received = virtio_balloon_cmd_id_received(vb);
+       if (cmd_id_received == VIRTIO_BALLOON_CMD_ID_DONE) {
+               /* Pass ULONG_MAX to give back all the free pages */
+               return_free_pages_to_mm(vb, ULONG_MAX);
+       } else if (cmd_id_received != VIRTIO_BALLOON_CMD_ID_STOP &&
+                  cmd_id_received !=
+                  virtio32_to_cpu(vb->vdev, vb->cmd_id_active)) {
+               virtio_balloon_report_free_page(vb);
+       }
+}
+
 #ifdef CONFIG_BALLOON_COMPACTION
 /*
  * virtballoon_migratepage - perform the balloon page migration on behalf of
@@ -885,7 +917,7 @@ static int virtballoon_probe(struct virtio_device *vdev)
                        goto out_del_vqs;
                }
                INIT_WORK(&vb->report_free_page_work, report_free_page_func);
-               vb->cmd_id_received = VIRTIO_BALLOON_CMD_ID_STOP;
+               vb->cmd_id_received_cache = VIRTIO_BALLOON_CMD_ID_STOP;
                vb->cmd_id_active = cpu_to_virtio32(vb->vdev,
                                                  VIRTIO_BALLOON_CMD_ID_STOP);
                vb->cmd_id_stop = cpu_to_virtio32(vb->vdev,
index 4cd9ea5..d9dd0f7 100644 (file)
@@ -468,7 +468,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 {
        struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
        unsigned int irq = platform_get_irq(vm_dev->pdev, 0);
-       int i, err;
+       int i, err, queue_idx = 0;
 
        err = request_irq(irq, vm_interrupt, IRQF_SHARED,
                        dev_name(&vdev->dev), vm_dev);
@@ -476,7 +476,12 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
                return err;
 
        for (i = 0; i < nvqs; ++i) {
-               vqs[i] = vm_setup_vq(vdev, i, callbacks[i], names[i],
+               if (!names[i]) {
+                       vqs[i] = NULL;
+                       continue;
+               }
+
+               vqs[i] = vm_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
                                     ctx ? ctx[i] : false);
                if (IS_ERR(vqs[i])) {
                        vm_del_vqs(vdev);
index 465a6f5..d0584c0 100644 (file)
@@ -285,7 +285,7 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
        u16 msix_vec;
-       int i, err, nvectors, allocated_vectors;
+       int i, err, nvectors, allocated_vectors, queue_idx = 0;
 
        vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL);
        if (!vp_dev->vqs)
@@ -321,7 +321,7 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
                        msix_vec = allocated_vectors++;
                else
                        msix_vec = VP_MSIX_VQ_VECTOR;
-               vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i],
+               vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
                                     ctx ? ctx[i] : false,
                                     msix_vec);
                if (IS_ERR(vqs[i])) {
@@ -356,7 +356,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
                const char * const names[], const bool *ctx)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
-       int i, err;
+       int i, err, queue_idx = 0;
 
        vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL);
        if (!vp_dev->vqs)
@@ -374,7 +374,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
                        vqs[i] = NULL;
                        continue;
                }
-               vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i],
+               vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
                                     ctx ? ctx[i] : false,
                                     VIRTIO_MSI_NO_VECTOR);
                if (IS_ERR(vqs[i])) {
index cd7e755..a0b07c3 100644 (file)
@@ -152,7 +152,12 @@ struct vring_virtqueue {
                /* Available for packed ring */
                struct {
                        /* Actual memory layout for this queue. */
-                       struct vring_packed vring;
+                       struct {
+                               unsigned int num;
+                               struct vring_packed_desc *desc;
+                               struct vring_packed_desc_event *driver;
+                               struct vring_packed_desc_event *device;
+                       } vring;
 
                        /* Driver ring wrap counter. */
                        bool avail_wrap_counter;
@@ -1609,6 +1614,9 @@ static struct virtqueue *vring_create_virtqueue_packed(
                !context;
        vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
 
+       if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
+               vq->weak_barriers = false;
+
        vq->packed.ring_dma_addr = ring_dma_addr;
        vq->packed.driver_event_dma_addr = driver_event_dma_addr;
        vq->packed.device_event_dma_addr = device_event_dma_addr;
@@ -2079,6 +2087,9 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
                !context;
        vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
 
+       if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
+               vq->weak_barriers = false;
+
        vq->split.queue_dma_addr = 0;
        vq->split.queue_size_in_bytes = 0;
 
@@ -2213,6 +2224,8 @@ void vring_transport_features(struct virtio_device *vdev)
                        break;
                case VIRTIO_F_RING_PACKED:
                        break;
+               case VIRTIO_F_ORDER_PLATFORM:
+                       break;
                default:
                        /* We don't understand this bit. */
                        __virtio_clear_bit(vdev, i);
index 5c4a764..81208cd 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/watchdog.h>
 #include <linux/moduleparam.h>
 #include <linux/platform_device.h>
+#include <linux/mod_devicetable.h>
 
 #include <asm/mach-ralink/ralink_regs.h>
 
index 98967f0..db7c57d 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/watchdog.h>
 #include <linux/moduleparam.h>
 #include <linux/platform_device.h>
+#include <linux/mod_devicetable.h>
 
 #include <asm/mach-ralink/ralink_regs.h>
 
index 0d3a0fb..5294120 100644 (file)
@@ -79,13 +79,13 @@ static int tqmx86_wdt_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       if (IS_ERR(res))
-               return PTR_ERR(res);
+       if (!res)
+               return -ENODEV;
 
        priv->io_base = devm_ioport_map(&pdev->dev, res->start,
                                        resource_size(res));
-       if (IS_ERR(priv->io_base))
-               return PTR_ERR(priv->io_base);
+       if (!priv->io_base)
+               return -ENOMEM;
 
        watchdog_set_drvdata(&priv->wdd, priv);
 
index 93194f3..117e76b 100644 (file)
@@ -1650,7 +1650,7 @@ void xen_callback_vector(void)
                        xen_have_vector_callback = 0;
                        return;
                }
-               pr_info("Xen HVM callback vector for event delivery is enabled\n");
+               pr_info_once("Xen HVM callback vector for event delivery is enabled\n");
                alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR,
                                xen_hvm_callback_vector);
        }
index 2e5d845..7aa64d1 100644 (file)
@@ -160,9 +160,10 @@ static void pvcalls_conn_back_read(void *opaque)
 
        /* write the data, then modify the indexes */
        virt_wmb();
-       if (ret < 0)
+       if (ret < 0) {
+               atomic_set(&map->read, 0);
                intf->in_error = ret;
-       else
+       else
                intf->in_prod = prod + ret;
        /* update the indexes, then notify the other end */
        virt_wmb();
@@ -282,13 +283,11 @@ static int pvcalls_back_socket(struct xenbus_device *dev,
 static void pvcalls_sk_state_change(struct sock *sock)
 {
        struct sock_mapping *map = sock->sk_user_data;
-       struct pvcalls_data_intf *intf;
 
        if (map == NULL)
                return;
 
-       intf = map->ring;
-       intf->in_error = -ENOTCONN;
+       atomic_inc(&map->read);
        notify_remote_via_irq(map->irq);
 }
 
index 77224d8..8a249c9 100644 (file)
 #define PVCALLS_NR_RSP_PER_RING __CONST_RING_SIZE(xen_pvcalls, XEN_PAGE_SIZE)
 #define PVCALLS_FRONT_MAX_SPIN 5000
 
+static struct proto pvcalls_proto = {
+       .name   = "PVCalls",
+       .owner  = THIS_MODULE,
+       .obj_size = sizeof(struct sock),
+};
+
 struct pvcalls_bedata {
        struct xen_pvcalls_front_ring ring;
        grant_ref_t ref;
@@ -335,6 +341,42 @@ int pvcalls_front_socket(struct socket *sock)
        return ret;
 }
 
+static void free_active_ring(struct sock_mapping *map)
+{
+       if (!map->active.ring)
+               return;
+
+       free_pages((unsigned long)map->active.data.in,
+                       map->active.ring->ring_order);
+       free_page((unsigned long)map->active.ring);
+}
+
+static int alloc_active_ring(struct sock_mapping *map)
+{
+       void *bytes;
+
+       map->active.ring = (struct pvcalls_data_intf *)
+               get_zeroed_page(GFP_KERNEL);
+       if (!map->active.ring)
+               goto out;
+
+       map->active.ring->ring_order = PVCALLS_RING_ORDER;
+       bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+                                       PVCALLS_RING_ORDER);
+       if (!bytes)
+               goto out;
+
+       map->active.data.in = bytes;
+       map->active.data.out = bytes +
+               XEN_FLEX_RING_SIZE(PVCALLS_RING_ORDER);
+
+       return 0;
+
+out:
+       free_active_ring(map);
+       return -ENOMEM;
+}
+
 static int create_active(struct sock_mapping *map, int *evtchn)
 {
        void *bytes;
@@ -343,15 +385,7 @@ static int create_active(struct sock_mapping *map, int *evtchn)
        *evtchn = -1;
        init_waitqueue_head(&map->active.inflight_conn_req);
 
-       map->active.ring = (struct pvcalls_data_intf *)
-               __get_free_page(GFP_KERNEL | __GFP_ZERO);
-       if (map->active.ring == NULL)
-               goto out_error;
-       map->active.ring->ring_order = PVCALLS_RING_ORDER;
-       bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
-                                       PVCALLS_RING_ORDER);
-       if (bytes == NULL)
-               goto out_error;
+       bytes = map->active.data.in;
        for (i = 0; i < (1 << PVCALLS_RING_ORDER); i++)
                map->active.ring->ref[i] = gnttab_grant_foreign_access(
                        pvcalls_front_dev->otherend_id,
@@ -361,10 +395,6 @@ static int create_active(struct sock_mapping *map, int *evtchn)
                pvcalls_front_dev->otherend_id,
                pfn_to_gfn(virt_to_pfn((void *)map->active.ring)), 0);
 
-       map->active.data.in = bytes;
-       map->active.data.out = bytes +
-               XEN_FLEX_RING_SIZE(PVCALLS_RING_ORDER);
-
        ret = xenbus_alloc_evtchn(pvcalls_front_dev, evtchn);
        if (ret)
                goto out_error;
@@ -385,8 +415,6 @@ static int create_active(struct sock_mapping *map, int *evtchn)
 out_error:
        if (*evtchn >= 0)
                xenbus_free_evtchn(pvcalls_front_dev, *evtchn);
-       free_pages((unsigned long)map->active.data.in, PVCALLS_RING_ORDER);
-       free_page((unsigned long)map->active.ring);
        return ret;
 }
 
@@ -406,17 +434,24 @@ int pvcalls_front_connect(struct socket *sock, struct sockaddr *addr,
                return PTR_ERR(map);
 
        bedata = dev_get_drvdata(&pvcalls_front_dev->dev);
+       ret = alloc_active_ring(map);
+       if (ret < 0) {
+               pvcalls_exit_sock(sock);
+               return ret;
+       }
 
        spin_lock(&bedata->socket_lock);
        ret = get_request(bedata, &req_id);
        if (ret < 0) {
                spin_unlock(&bedata->socket_lock);
+               free_active_ring(map);
                pvcalls_exit_sock(sock);
                return ret;
        }
        ret = create_active(map, &evtchn);
        if (ret < 0) {
                spin_unlock(&bedata->socket_lock);
+               free_active_ring(map);
                pvcalls_exit_sock(sock);
                return ret;
        }
@@ -469,8 +504,10 @@ static int __write_ring(struct pvcalls_data_intf *intf,
        virt_mb();
 
        size = pvcalls_queued(prod, cons, array_size);
-       if (size >= array_size)
+       if (size > array_size)
                return -EINVAL;
+       if (size == array_size)
+               return 0;
        if (len > array_size - size)
                len = array_size - size;
 
@@ -560,15 +597,13 @@ static int __read_ring(struct pvcalls_data_intf *intf,
        error = intf->in_error;
        /* get pointers before reading from the ring */
        virt_rmb();
-       if (error < 0)
-               return error;
 
        size = pvcalls_queued(prod, cons, array_size);
        masked_prod = pvcalls_mask(prod, array_size);
        masked_cons = pvcalls_mask(cons, array_size);
 
        if (size == 0)
-               return 0;
+               return error ?: size;
 
        if (len > size)
                len = size;
@@ -780,25 +815,36 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
                }
        }
 
-       spin_lock(&bedata->socket_lock);
-       ret = get_request(bedata, &req_id);
-       if (ret < 0) {
+       map2 = kzalloc(sizeof(*map2), GFP_KERNEL);
+       if (map2 == NULL) {
                clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
                          (void *)&map->passive.flags);
-               spin_unlock(&bedata->socket_lock);
+               pvcalls_exit_sock(sock);
+               return -ENOMEM;
+       }
+       ret = alloc_active_ring(map2);
+       if (ret < 0) {
+               clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
+                               (void *)&map->passive.flags);
+               kfree(map2);
                pvcalls_exit_sock(sock);
                return ret;
        }
-       map2 = kzalloc(sizeof(*map2), GFP_ATOMIC);
-       if (map2 == NULL) {
+       spin_lock(&bedata->socket_lock);
+       ret = get_request(bedata, &req_id);
+       if (ret < 0) {
                clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
                          (void *)&map->passive.flags);
                spin_unlock(&bedata->socket_lock);
+               free_active_ring(map2);
+               kfree(map2);
                pvcalls_exit_sock(sock);
-               return -ENOMEM;
+               return ret;
        }
+
        ret = create_active(map2, &evtchn);
        if (ret < 0) {
+               free_active_ring(map2);
                kfree(map2);
                clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
                          (void *)&map->passive.flags);
@@ -839,7 +885,7 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
 
 received:
        map2->sock = newsock;
-       newsock->sk = kzalloc(sizeof(*newsock->sk), GFP_KERNEL);
+       newsock->sk = sk_alloc(sock_net(sock->sk), PF_INET, GFP_KERNEL, &pvcalls_proto, false);
        if (!newsock->sk) {
                bedata->rsp[req_id].req_id = PVCALLS_INVALID_ID;
                map->passive.inflight_req_id = PVCALLS_INVALID_ID;
@@ -1032,8 +1078,8 @@ int pvcalls_front_release(struct socket *sock)
                spin_lock(&bedata->socket_lock);
                list_del(&map->list);
                spin_unlock(&bedata->socket_lock);
-               if (READ_ONCE(map->passive.inflight_req_id) !=
-                   PVCALLS_INVALID_ID) {
+               if (READ_ONCE(map->passive.inflight_req_id) != PVCALLS_INVALID_ID &&
+                       READ_ONCE(map->passive.inflight_req_id) != 0) {
                        pvcalls_front_free_map(bedata,
                                               map->passive.accept_map);
                }
index 989cf87..bb78884 100644 (file)
@@ -645,7 +645,7 @@ xen_swiotlb_dma_mmap(struct device *dev, struct vm_area_struct *vma,
                     void *cpu_addr, dma_addr_t dma_addr, size_t size,
                     unsigned long attrs)
 {
-#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+#ifdef CONFIG_ARM
        if (xen_get_dma_ops(dev)->mmap)
                return xen_get_dma_ops(dev)->mmap(dev, vma, cpu_addr,
                                                    dma_addr, size, attrs);
@@ -662,7 +662,7 @@ xen_swiotlb_get_sgtable(struct device *dev, struct sg_table *sgt,
                        void *cpu_addr, dma_addr_t handle, size_t size,
                        unsigned long attrs)
 {
-#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+#ifdef CONFIG_ARM
        if (xen_get_dma_ops(dev)->get_sgtable) {
 #if 0
        /*
index 0568fd9..e432bd2 100644 (file)
@@ -208,7 +208,7 @@ again:
                /* The new front of the queue now owns the state variables. */
                next = list_entry(vnode->pending_locks.next,
                                  struct file_lock, fl_u.afs.link);
-               vnode->lock_key = afs_file_key(next->fl_file);
+               vnode->lock_key = key_get(afs_file_key(next->fl_file));
                vnode->lock_type = (next->fl_type == F_RDLCK) ? AFS_LOCK_READ : AFS_LOCK_WRITE;
                vnode->lock_state = AFS_VNODE_LOCK_WAITING_FOR_CB;
                goto again;
@@ -413,7 +413,7 @@ static void afs_dequeue_lock(struct afs_vnode *vnode, struct file_lock *fl)
        /* The new front of the queue now owns the state variables. */
        next = list_entry(vnode->pending_locks.next,
                          struct file_lock, fl_u.afs.link);
-       vnode->lock_key = afs_file_key(next->fl_file);
+       vnode->lock_key = key_get(afs_file_key(next->fl_file));
        vnode->lock_type = (next->fl_type == F_RDLCK) ? AFS_LOCK_READ : AFS_LOCK_WRITE;
        vnode->lock_state = AFS_VNODE_LOCK_WAITING_FOR_CB;
        afs_lock_may_be_available(vnode);
index 6b17d36..1a4ce07 100644 (file)
@@ -414,7 +414,6 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
        } else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
                valid = true;
        } else {
-               vnode->cb_s_break = vnode->cb_interest->server->cb_s_break;
                vnode->cb_v_break = vnode->volume->cb_v_break;
                valid = false;
        }
@@ -546,6 +545,8 @@ void afs_evict_inode(struct inode *inode)
 #endif
 
        afs_put_permits(rcu_access_pointer(vnode->permit_cache));
+       key_put(vnode->lock_key);
+       vnode->lock_key = NULL;
        _leave("");
 }
 
index 07bc10f..d443e2b 100644 (file)
@@ -161,3 +161,14 @@ struct yfs_xdr_YFSStoreVolumeStatus {
        struct yfs_xdr_u64      max_quota;
        struct yfs_xdr_u64      file_quota;
 } __packed;
+
+enum yfs_lock_type {
+       yfs_LockNone            = -1,
+       yfs_LockRead            = 0,
+       yfs_LockWrite           = 1,
+       yfs_LockExtend          = 2,
+       yfs_LockRelease         = 3,
+       yfs_LockMandatoryRead   = 0x100,
+       yfs_LockMandatoryWrite  = 0x101,
+       yfs_LockMandatoryExtend = 0x102,
+};
index a7b4486..2c588f9 100644 (file)
@@ -23,6 +23,7 @@ struct workqueue_struct *afs_async_calls;
 static void afs_wake_up_call_waiter(struct sock *, struct rxrpc_call *, unsigned long);
 static long afs_wait_for_call_to_complete(struct afs_call *, struct afs_addr_cursor *);
 static void afs_wake_up_async_call(struct sock *, struct rxrpc_call *, unsigned long);
+static void afs_delete_async_call(struct work_struct *);
 static void afs_process_async_call(struct work_struct *);
 static void afs_rx_new_call(struct sock *, struct rxrpc_call *, unsigned long);
 static void afs_rx_discard_new_call(struct rxrpc_call *, unsigned long);
@@ -203,20 +204,26 @@ void afs_put_call(struct afs_call *call)
        }
 }
 
+static struct afs_call *afs_get_call(struct afs_call *call,
+                                    enum afs_call_trace why)
+{
+       int u = atomic_inc_return(&call->usage);
+
+       trace_afs_call(call, why, u,
+                      atomic_read(&call->net->nr_outstanding_calls),
+                      __builtin_return_address(0));
+       return call;
+}
+
 /*
  * Queue the call for actual work.
  */
 static void afs_queue_call_work(struct afs_call *call)
 {
        if (call->type->work) {
-               int u = atomic_inc_return(&call->usage);
-
-               trace_afs_call(call, afs_call_trace_work, u,
-                              atomic_read(&call->net->nr_outstanding_calls),
-                              __builtin_return_address(0));
-
                INIT_WORK(&call->work, call->type->work);
 
+               afs_get_call(call, afs_call_trace_work);
                if (!queue_work(afs_wq, &call->work))
                        afs_put_call(call);
        }
@@ -398,6 +405,12 @@ long afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call,
                }
        }
 
+       /* If the call is going to be asynchronous, we need an extra ref for
+        * the call to hold itself so the caller need not hang on to its ref.
+        */
+       if (call->async)
+               afs_get_call(call, afs_call_trace_get);
+
        /* create a call */
        rxcall = rxrpc_kernel_begin_call(call->net->socket, srx, call->key,
                                         (unsigned long)call,
@@ -438,15 +451,17 @@ long afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call,
                        goto error_do_abort;
        }
 
-       /* at this point, an async call may no longer exist as it may have
-        * already completed */
-       if (call->async)
+       /* Note that at this point, we may have received the reply or an abort
+        * - and an asynchronous call may already have completed.
+        */
+       if (call->async) {
+               afs_put_call(call);
                return -EINPROGRESS;
+       }
 
        return afs_wait_for_call_to_complete(call, ac);
 
 error_do_abort:
-       call->state = AFS_CALL_COMPLETE;
        if (ret != -ECONNABORTED) {
                rxrpc_kernel_abort_call(call->net->socket, rxcall,
                                        RX_USER_ABORT, ret, "KSD");
@@ -463,8 +478,24 @@ error_do_abort:
 error_kill_call:
        if (call->type->done)
                call->type->done(call);
-       afs_put_call(call);
+
+       /* We need to dispose of the extra ref we grabbed for an async call.
+        * The call, however, might be queued on afs_async_calls and we need to
+        * make sure we don't get any more notifications that might requeue it.
+        */
+       if (call->rxcall) {
+               rxrpc_kernel_end_call(call->net->socket, call->rxcall);
+               call->rxcall = NULL;
+       }
+       if (call->async) {
+               if (cancel_work_sync(&call->async_work))
+                       afs_put_call(call);
+               afs_put_call(call);
+       }
+
        ac->error = ret;
+       call->state = AFS_CALL_COMPLETE;
+       afs_put_call(call);
        _leave(" = %d", ret);
        return ret;
 }
index 95d0761..155dc14 100644 (file)
@@ -42,9 +42,7 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell,
                if (vldb->fs_mask[i] & type_mask)
                        nr_servers++;
 
-       slist = kzalloc(sizeof(struct afs_server_list) +
-                       sizeof(struct afs_server_entry) * nr_servers,
-                       GFP_KERNEL);
+       slist = kzalloc(struct_size(slist, servers, nr_servers), GFP_KERNEL);
        if (!slist)
                goto error;
 
index 12658c1..5aa5792 100644 (file)
@@ -803,7 +803,7 @@ int yfs_fs_create_file(struct afs_fs_cursor *fc,
        bp = xdr_encode_YFSFid(bp, &vnode->fid);
        bp = xdr_encode_string(bp, name, namesz);
        bp = xdr_encode_YFSStoreStatus_mode(bp, mode);
-       bp = xdr_encode_u32(bp, 0); /* ViceLockType */
+       bp = xdr_encode_u32(bp, yfs_LockNone); /* ViceLockType */
        yfs_check_req(call, bp);
 
        afs_use_fs_server(call, fc->cbi);
index b906ff7..aaaaf4d 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1436,6 +1436,7 @@ static int aio_prep_rw(struct kiocb *req, const struct iocb *iocb)
        if (unlikely(!req->ki_filp))
                return -EBADF;
        req->ki_complete = aio_complete_rw;
+       req->private = NULL;
        req->ki_pos = iocb->aio_offset;
        req->ki_flags = iocb_flags(req->ki_filp);
        if (iocb->aio_flags & IOCB_FLAG_RESFD)
index d441244..28d9c2b 100644 (file)
@@ -596,7 +596,6 @@ int autofs_expire_run(struct super_block *sb,
        pkt.len = dentry->d_name.len;
        memcpy(pkt.name, dentry->d_name.name, pkt.len);
        pkt.name[pkt.len] = '\0';
-       dput(dentry);
 
        if (copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)))
                ret = -EFAULT;
@@ -609,6 +608,8 @@ int autofs_expire_run(struct super_block *sb,
        complete_all(&ino->expire_complete);
        spin_unlock(&sbi->fs_lock);
 
+       dput(dentry);
+
        return ret;
 }
 
index 0e8ea2d..078992e 100644 (file)
@@ -266,8 +266,10 @@ int autofs_fill_super(struct super_block *s, void *data, int silent)
        }
        root_inode = autofs_get_inode(s, S_IFDIR | 0755);
        root = d_make_root(root_inode);
-       if (!root)
+       if (!root) {
+               ret = -ENOMEM;
                goto fail_ino;
+       }
        pipe = NULL;
 
        root->d_fsdata = ino;
index d0078cb..7cde3f4 100644 (file)
@@ -42,14 +42,10 @@ static int load_script(struct linux_binprm *bprm)
        fput(bprm->file);
        bprm->file = NULL;
 
-       for (cp = bprm->buf+2;; cp++) {
-               if (cp >= bprm->buf + BINPRM_BUF_SIZE)
-                       return -ENOEXEC;
-               if (!*cp || (*cp == '\n'))
-                       break;
-       }
+       bprm->buf[BINPRM_BUF_SIZE - 1] = '\0';
+       if ((cp = strchr(bprm->buf, '\n')) == NULL)
+               cp = bprm->buf+BINPRM_BUF_SIZE-1;
        *cp = '\0';
-
        while (cp > bprm->buf) {
                cp--;
                if ((*cp == ' ') || (*cp == '\t'))
index c546cdc..58a4c12 100644 (file)
@@ -104,6 +104,20 @@ void invalidate_bdev(struct block_device *bdev)
 }
 EXPORT_SYMBOL(invalidate_bdev);
 
+static void set_init_blocksize(struct block_device *bdev)
+{
+       unsigned bsize = bdev_logical_block_size(bdev);
+       loff_t size = i_size_read(bdev->bd_inode);
+
+       while (bsize < PAGE_SIZE) {
+               if (size & bsize)
+                       break;
+               bsize <<= 1;
+       }
+       bdev->bd_block_size = bsize;
+       bdev->bd_inode->i_blkbits = blksize_bits(bsize);
+}
+
 int set_blocksize(struct block_device *bdev, int size)
 {
        /* Size must be a power of two, and between 512 and PAGE_SIZE */
@@ -1431,18 +1445,9 @@ EXPORT_SYMBOL(check_disk_change);
 
 void bd_set_size(struct block_device *bdev, loff_t size)
 {
-       unsigned bsize = bdev_logical_block_size(bdev);
-
        inode_lock(bdev->bd_inode);
        i_size_write(bdev->bd_inode, size);
        inode_unlock(bdev->bd_inode);
-       while (bsize < PAGE_SIZE) {
-               if (size & bsize)
-                       break;
-               bsize <<= 1;
-       }
-       bdev->bd_block_size = bsize;
-       bdev->bd_inode->i_blkbits = blksize_bits(bsize);
 }
 EXPORT_SYMBOL(bd_set_size);
 
@@ -1519,8 +1524,10 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                                }
                        }
 
-                       if (!ret)
+                       if (!ret) {
                                bd_set_size(bdev,(loff_t)get_capacity(disk)<<9);
+                               set_init_blocksize(bdev);
+                       }
 
                        /*
                         * If the device is invalidated, rescan partition
@@ -1555,6 +1562,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                                goto out_clear;
                        }
                        bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9);
+                       set_init_blocksize(bdev);
                }
 
                if (bdev->bd_bdi == &noop_backing_dev_info)
index d92462f..5a6c39b 100644 (file)
@@ -968,6 +968,48 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
        return 0;
 }
 
+static struct extent_buffer *alloc_tree_block_no_bg_flush(
+                                         struct btrfs_trans_handle *trans,
+                                         struct btrfs_root *root,
+                                         u64 parent_start,
+                                         const struct btrfs_disk_key *disk_key,
+                                         int level,
+                                         u64 hint,
+                                         u64 empty_size)
+{
+       struct btrfs_fs_info *fs_info = root->fs_info;
+       struct extent_buffer *ret;
+
+       /*
+        * If we are COWing a node/leaf from the extent, chunk, device or free
+        * space trees, make sure that we do not finish block group creation of
+        * pending block groups. We do this to avoid a deadlock.
+        * COWing can result in allocation of a new chunk, and flushing pending
+        * block groups (btrfs_create_pending_block_groups()) can be triggered
+        * when finishing allocation of a new chunk. Creation of a pending block
+        * group modifies the extent, chunk, device and free space trees,
+        * therefore we could deadlock with ourselves since we are holding a
+        * lock on an extent buffer that btrfs_create_pending_block_groups() may
+        * try to COW later.
+        * For similar reasons, we also need to delay flushing pending block
+        * groups when splitting a leaf or node, from one of those trees, since
+        * we are holding a write lock on it and its parent or when inserting a
+        * new root node for one of those trees.
+        */
+       if (root == fs_info->extent_root ||
+           root == fs_info->chunk_root ||
+           root == fs_info->dev_root ||
+           root == fs_info->free_space_root)
+               trans->can_flush_pending_bgs = false;
+
+       ret = btrfs_alloc_tree_block(trans, root, parent_start,
+                                    root->root_key.objectid, disk_key, level,
+                                    hint, empty_size);
+       trans->can_flush_pending_bgs = true;
+
+       return ret;
+}
+
 /*
  * does the dirty work in cow of a single block.  The parent block (if
  * supplied) is updated to point to the new cow copy.  The new buffer is marked
@@ -1015,26 +1057,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
        if ((root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) && parent)
                parent_start = parent->start;
 
-       /*
-        * If we are COWing a node/leaf from the extent, chunk or device trees,
-        * make sure that we do not finish block group creation of pending block
-        * groups. We do this to avoid a deadlock.
-        * COWing can result in allocation of a new chunk, and flushing pending
-        * block groups (btrfs_create_pending_block_groups()) can be triggered
-        * when finishing allocation of a new chunk. Creation of a pending block
-        * group modifies the extent, chunk and device trees, therefore we could
-        * deadlock with ourselves since we are holding a lock on an extent
-        * buffer that btrfs_create_pending_block_groups() may try to COW later.
-        */
-       if (root == fs_info->extent_root ||
-           root == fs_info->chunk_root ||
-           root == fs_info->dev_root)
-               trans->can_flush_pending_bgs = false;
-
-       cow = btrfs_alloc_tree_block(trans, root, parent_start,
-                       root->root_key.objectid, &disk_key, level,
-                       search_start, empty_size);
-       trans->can_flush_pending_bgs = true;
+       cow = alloc_tree_block_no_bg_flush(trans, root, parent_start, &disk_key,
+                                          level, search_start, empty_size);
        if (IS_ERR(cow))
                return PTR_ERR(cow);
 
@@ -3343,8 +3367,8 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
        else
                btrfs_node_key(lower, &lower_key, 0);
 
-       c = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid,
-                                  &lower_key, level, root->node->start, 0);
+       c = alloc_tree_block_no_bg_flush(trans, root, 0, &lower_key, level,
+                                        root->node->start, 0);
        if (IS_ERR(c))
                return PTR_ERR(c);
 
@@ -3473,8 +3497,8 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
        mid = (c_nritems + 1) / 2;
        btrfs_node_key(c, &disk_key, mid);
 
-       split = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid,
-                       &disk_key, level, c->start, 0);
+       split = alloc_tree_block_no_bg_flush(trans, root, 0, &disk_key, level,
+                                            c->start, 0);
        if (IS_ERR(split))
                return PTR_ERR(split);
 
@@ -4258,8 +4282,8 @@ again:
        else
                btrfs_item_key(l, &disk_key, mid);
 
-       right = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid,
-                       &disk_key, 0, l->start, 0);
+       right = alloc_tree_block_no_bg_flush(trans, root, 0, &disk_key, 0,
+                                            l->start, 0);
        if (IS_ERR(right))
                return PTR_ERR(right);
 
index 0a68cf7..7a2a262 100644 (file)
@@ -35,6 +35,7 @@
 struct btrfs_trans_handle;
 struct btrfs_transaction;
 struct btrfs_pending_snapshot;
+struct btrfs_delayed_ref_root;
 extern struct kmem_cache *btrfs_trans_handle_cachep;
 extern struct kmem_cache *btrfs_bit_radix_cachep;
 extern struct kmem_cache *btrfs_path_cachep;
@@ -786,6 +787,9 @@ enum {
         * main phase. The fs_info::balance_ctl is initialized.
         */
        BTRFS_FS_BALANCE_RUNNING,
+
+       /* Indicate that the cleaner thread is awake and doing something. */
+       BTRFS_FS_CLEANER_RUNNING,
 };
 
 struct btrfs_fs_info {
@@ -2661,6 +2665,9 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
                           unsigned long count);
 int btrfs_async_run_delayed_refs(struct btrfs_fs_info *fs_info,
                                 unsigned long count, u64 transid, int wait);
+void btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info,
+                                 struct btrfs_delayed_ref_root *delayed_refs,
+                                 struct btrfs_delayed_ref_head *head);
 int btrfs_lookup_data_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len);
 int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
                             struct btrfs_fs_info *fs_info, u64 bytenr,
index 8da2f38..6a2a2a9 100644 (file)
@@ -1682,6 +1682,8 @@ static int cleaner_kthread(void *arg)
        while (1) {
                again = 0;
 
+               set_bit(BTRFS_FS_CLEANER_RUNNING, &fs_info->flags);
+
                /* Make the cleaner go to sleep early. */
                if (btrfs_need_cleaner_sleep(fs_info))
                        goto sleep;
@@ -1728,6 +1730,7 @@ static int cleaner_kthread(void *arg)
                 */
                btrfs_delete_unused_bgs(fs_info);
 sleep:
+               clear_bit(BTRFS_FS_CLEANER_RUNNING, &fs_info->flags);
                if (kthread_should_park())
                        kthread_parkme();
                if (kthread_should_stop())
@@ -4201,6 +4204,14 @@ static void btrfs_destroy_all_ordered_extents(struct btrfs_fs_info *fs_info)
                spin_lock(&fs_info->ordered_root_lock);
        }
        spin_unlock(&fs_info->ordered_root_lock);
+
+       /*
+        * We need this here because if we've been flipped read-only we won't
+        * get sync() from the umount, so we need to make sure any ordered
+        * extents that haven't had their dirty pages IO start writeout yet
+        * actually get run and error out properly.
+        */
+       btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1);
 }
 
 static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
@@ -4265,6 +4276,7 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
                if (pin_bytes)
                        btrfs_pin_extent(fs_info, head->bytenr,
                                         head->num_bytes, 1);
+               btrfs_cleanup_ref_head_accounting(fs_info, delayed_refs, head);
                btrfs_put_delayed_ref_head(head);
                cond_resched();
                spin_lock(&delayed_refs->lock);
index b15afea..d81035b 100644 (file)
@@ -2456,12 +2456,10 @@ static int run_and_cleanup_extent_op(struct btrfs_trans_handle *trans,
        return ret ? ret : 1;
 }
 
-static void cleanup_ref_head_accounting(struct btrfs_trans_handle *trans,
-                                       struct btrfs_delayed_ref_head *head)
+void btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info,
+                                 struct btrfs_delayed_ref_root *delayed_refs,
+                                 struct btrfs_delayed_ref_head *head)
 {
-       struct btrfs_fs_info *fs_info = trans->fs_info;
-       struct btrfs_delayed_ref_root *delayed_refs =
-               &trans->transaction->delayed_refs;
        int nr_items = 1;       /* Dropping this ref head update. */
 
        if (head->total_ref_mod < 0) {
@@ -2544,7 +2542,7 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans,
                }
        }
 
-       cleanup_ref_head_accounting(trans, head);
+       btrfs_cleanup_ref_head_accounting(fs_info, delayed_refs, head);
 
        trace_run_delayed_ref_head(fs_info, head, 0);
        btrfs_delayed_ref_unlock(head);
@@ -4954,6 +4952,15 @@ static void flush_space(struct btrfs_fs_info *fs_info,
                        ret = 0;
                break;
        case COMMIT_TRANS:
+               /*
+                * If we have pending delayed iputs then we could free up a
+                * bunch of pinned space, so make sure we run the iputs before
+                * we do our pinned bytes check below.
+                */
+               mutex_lock(&fs_info->cleaner_delayed_iput_mutex);
+               btrfs_run_delayed_iputs(fs_info);
+               mutex_unlock(&fs_info->cleaner_delayed_iput_mutex);
+
                ret = may_commit_transaction(fs_info, space_info);
                break;
        default:
@@ -7188,7 +7195,7 @@ static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans,
        if (head->must_insert_reserved)
                ret = 1;
 
-       cleanup_ref_head_accounting(trans, head);
+       btrfs_cleanup_ref_head_accounting(trans->fs_info, delayed_refs, head);
        mutex_unlock(&head->mutex);
        btrfs_put_delayed_ref_head(head);
        return ret;
index 43eb453..5c34966 100644 (file)
@@ -3129,9 +3129,6 @@ out:
        /* once for the tree */
        btrfs_put_ordered_extent(ordered_extent);
 
-       /* Try to release some metadata so we don't get an OOM but don't wait */
-       btrfs_btree_balance_dirty_nodelay(fs_info);
-
        return ret;
 }
 
@@ -3254,6 +3251,8 @@ void btrfs_add_delayed_iput(struct inode *inode)
        ASSERT(list_empty(&binode->delayed_iput));
        list_add_tail(&binode->delayed_iput, &fs_info->delayed_iputs);
        spin_unlock(&fs_info->delayed_iput_lock);
+       if (!test_bit(BTRFS_FS_CLEANER_RUNNING, &fs_info->flags))
+               wake_up_process(fs_info->cleaner_kthread);
 }
 
 void btrfs_run_delayed_iputs(struct btrfs_fs_info *fs_info)
index fab9443..9c8e173 100644 (file)
@@ -3221,6 +3221,26 @@ static void btrfs_double_inode_lock(struct inode *inode1, struct inode *inode2)
        inode_lock_nested(inode2, I_MUTEX_CHILD);
 }
 
+static void btrfs_double_extent_unlock(struct inode *inode1, u64 loff1,
+                                      struct inode *inode2, u64 loff2, u64 len)
+{
+       unlock_extent(&BTRFS_I(inode1)->io_tree, loff1, loff1 + len - 1);
+       unlock_extent(&BTRFS_I(inode2)->io_tree, loff2, loff2 + len - 1);
+}
+
+static void btrfs_double_extent_lock(struct inode *inode1, u64 loff1,
+                                    struct inode *inode2, u64 loff2, u64 len)
+{
+       if (inode1 < inode2) {
+               swap(inode1, inode2);
+               swap(loff1, loff2);
+       } else if (inode1 == inode2 && loff2 < loff1) {
+               swap(loff1, loff2);
+       }
+       lock_extent(&BTRFS_I(inode1)->io_tree, loff1, loff1 + len - 1);
+       lock_extent(&BTRFS_I(inode2)->io_tree, loff2, loff2 + len - 1);
+}
+
 static int btrfs_extent_same_range(struct inode *src, u64 loff, u64 olen,
                                   struct inode *dst, u64 dst_loff)
 {
@@ -3242,11 +3262,12 @@ static int btrfs_extent_same_range(struct inode *src, u64 loff, u64 olen,
                return -EINVAL;
 
        /*
-        * Lock destination range to serialize with concurrent readpages().
+        * Lock destination range to serialize with concurrent readpages() and
+        * source range to serialize with relocation.
         */
-       lock_extent(&BTRFS_I(dst)->io_tree, dst_loff, dst_loff + len - 1);
+       btrfs_double_extent_lock(src, loff, dst, dst_loff, len);
        ret = btrfs_clone(src, dst, loff, olen, len, dst_loff, 1);
-       unlock_extent(&BTRFS_I(dst)->io_tree, dst_loff, dst_loff + len - 1);
+       btrfs_double_extent_unlock(src, loff, dst, dst_loff, len);
 
        return ret;
 }
@@ -3905,17 +3926,33 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src,
                len = ALIGN(src->i_size, bs) - off;
 
        if (destoff > inode->i_size) {
+               const u64 wb_start = ALIGN_DOWN(inode->i_size, bs);
+
                ret = btrfs_cont_expand(inode, inode->i_size, destoff);
                if (ret)
                        return ret;
+               /*
+                * We may have truncated the last block if the inode's size is
+                * not sector size aligned, so we need to wait for writeback to
+                * complete before proceeding further, otherwise we can race
+                * with cloning and attempt to increment a reference to an
+                * extent that no longer exists (writeback completed right after
+                * we found the previous extent covering eof and before we
+                * attempted to increment its reference count).
+                */
+               ret = btrfs_wait_ordered_range(inode, wb_start,
+                                              destoff - wb_start);
+               if (ret)
+                       return ret;
        }
 
        /*
-        * Lock destination range to serialize with concurrent readpages().
+        * Lock destination range to serialize with concurrent readpages() and
+        * source range to serialize with relocation.
         */
-       lock_extent(&BTRFS_I(inode)->io_tree, destoff, destoff + len - 1);
+       btrfs_double_extent_lock(src, off, inode, destoff, len);
        ret = btrfs_clone(src, inode, off, olen, len, destoff, 0);
-       unlock_extent(&BTRFS_I(inode)->io_tree, destoff, destoff + len - 1);
+       btrfs_double_extent_unlock(src, off, inode, destoff, len);
        /*
         * Truncate page cache pages so that future reads will see the cloned
         * data immediately and not the previous data.
index c5586ff..0a3f122 100644 (file)
@@ -1621,6 +1621,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
                                flags | SB_RDONLY, device_name, data);
                        if (IS_ERR(mnt_root)) {
                                root = ERR_CAST(mnt_root);
+                               kfree(subvol_name);
                                goto out;
                        }
 
@@ -1630,12 +1631,14 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
                        if (error < 0) {
                                root = ERR_PTR(error);
                                mntput(mnt_root);
+                               kfree(subvol_name);
                                goto out;
                        }
                }
        }
        if (IS_ERR(mnt_root)) {
                root = ERR_CAST(mnt_root);
+               kfree(subvol_name);
                goto out;
        }
 
index 127fa15..4ec2b66 100644 (file)
@@ -850,14 +850,6 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
 
        btrfs_trans_release_chunk_metadata(trans);
 
-       if (lock && should_end_transaction(trans) &&
-           READ_ONCE(cur_trans->state) == TRANS_STATE_RUNNING) {
-               spin_lock(&info->trans_lock);
-               if (cur_trans->state == TRANS_STATE_RUNNING)
-                       cur_trans->state = TRANS_STATE_BLOCKED;
-               spin_unlock(&info->trans_lock);
-       }
-
        if (lock && READ_ONCE(cur_trans->state) == TRANS_STATE_BLOCKED) {
                if (throttle)
                        return btrfs_commit_transaction(trans);
@@ -1879,6 +1871,21 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans, int err)
        kmem_cache_free(btrfs_trans_handle_cachep, trans);
 }
 
+/*
+ * Release reserved delayed ref space of all pending block groups of the
+ * transaction and remove them from the list
+ */
+static void btrfs_cleanup_pending_block_groups(struct btrfs_trans_handle *trans)
+{
+       struct btrfs_fs_info *fs_info = trans->fs_info;
+       struct btrfs_block_group_cache *block_group, *tmp;
+
+       list_for_each_entry_safe(block_group, tmp, &trans->new_bgs, bg_list) {
+               btrfs_delayed_refs_rsv_release(fs_info, 1);
+               list_del_init(&block_group->bg_list);
+       }
+}
+
 static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info)
 {
        /*
@@ -2270,6 +2277,7 @@ scrub_continue:
        btrfs_scrub_continue(fs_info);
 cleanup_transaction:
        btrfs_trans_release_metadata(trans);
+       btrfs_cleanup_pending_block_groups(trans);
        btrfs_trans_release_chunk_metadata(trans);
        trans->block_rsv = NULL;
        btrfs_warn(fs_info, "Skipping commit of aborted transaction.");
index 2576b1a..1556192 100644 (file)
@@ -957,11 +957,11 @@ static noinline struct btrfs_device *device_list_add(const char *path,
                else
                        fs_devices = alloc_fs_devices(disk_super->fsid, NULL);
 
-               fs_devices->fsid_change = fsid_change_in_progress;
-
                if (IS_ERR(fs_devices))
                        return ERR_CAST(fs_devices);
 
+               fs_devices->fsid_change = fsid_change_in_progress;
+
                mutex_lock(&fs_devices->device_list_mutex);
                list_add(&fs_devices->fs_list, &fs_uuids);
 
@@ -7825,6 +7825,18 @@ static int verify_one_dev_extent(struct btrfs_fs_info *fs_info,
                ret = -EUCLEAN;
                goto out;
        }
+
+       /* It's possible this device is a dummy for seed device */
+       if (dev->disk_total_bytes == 0) {
+               dev = find_device(fs_info->fs_devices->seed, devid, NULL);
+               if (!dev) {
+                       btrfs_err(fs_info, "failed to find seed devid %llu",
+                                 devid);
+                       ret = -EUCLEAN;
+                       goto out;
+               }
+       }
+
        if (physical_offset + physical_len > dev->disk_total_bytes) {
                btrfs_err(fs_info,
 "dev extent devid %llu physical offset %llu len %llu is beyond device boundary %llu",
index 52d024b..48318fb 100644 (file)
@@ -200,6 +200,7 @@ __find_get_block_slow(struct block_device *bdev, sector_t block)
        struct buffer_head *head;
        struct page *page;
        int all_mapped = 1;
+       static DEFINE_RATELIMIT_STATE(last_warned, HZ, 1);
 
        index = block >> (PAGE_SHIFT - bd_inode->i_blkbits);
        page = find_get_page_flags(bd_mapping, index, FGP_ACCESSED);
@@ -227,15 +228,15 @@ __find_get_block_slow(struct block_device *bdev, sector_t block)
         * file io on the block device and getblk.  It gets dealt with
         * elsewhere, don't buffer_error if we had some unmapped buffers
         */
-       if (all_mapped) {
-               printk("__find_get_block_slow() failed. "
-                       "block=%llu, b_blocknr=%llu\n",
-                       (unsigned long long)block,
-                       (unsigned long long)bh->b_blocknr);
-               printk("b_state=0x%08lx, b_size=%zu\n",
-                       bh->b_state, bh->b_size);
-               printk("device %pg blocksize: %d\n", bdev,
-                       1 << bd_inode->i_blkbits);
+       ratelimit_set_flags(&last_warned, RATELIMIT_MSG_ON_RELEASE);
+       if (all_mapped && __ratelimit(&last_warned)) {
+               printk("__find_get_block_slow() failed. block=%llu, "
+                      "b_blocknr=%llu, b_state=0x%08lx, b_size=%zu, "
+                      "device %pg blocksize: %d\n",
+                      (unsigned long long)block,
+                      (unsigned long long)bh->b_blocknr,
+                      bh->b_state, bh->b_size, bdev,
+                      1 << bd_inode->i_blkbits);
        }
 out_unlock:
        spin_unlock(&bd_mapping->private_lock);
index 5d0c05e..a47c541 100644 (file)
@@ -1494,10 +1494,7 @@ static vm_fault_t ceph_filemap_fault(struct vm_fault *vmf)
                if (err < 0 || off >= i_size_read(inode)) {
                        unlock_page(page);
                        put_page(page);
-                       if (err == -ENOMEM)
-                               ret = VM_FAULT_OOM;
-                       else
-                               ret = VM_FAULT_SIGBUS;
+                       ret = vmf_error(err);
                        goto out_inline;
                }
                if (err < PAGE_SIZE)
index 94c026b..bba28a5 100644 (file)
@@ -1035,6 +1035,8 @@ static void drop_inode_snap_realm(struct ceph_inode_info *ci)
        list_del_init(&ci->i_snap_realm_item);
        ci->i_snap_realm_counter++;
        ci->i_snap_realm = NULL;
+       if (realm->ino == ci->i_vino.ino)
+               realm->inode = NULL;
        spin_unlock(&realm->inodes_with_caps_lock);
        ceph_put_snap_realm(ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc,
                            realm);
index 03f4d24..9455d3a 100644 (file)
@@ -3,19 +3,6 @@
  * quota.c - CephFS quota
  *
  * Copyright (C) 2017-2018 SUSE
- *
- * 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.  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, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/statfs.h>
index 4e9a7cc..da2cd8e 100644 (file)
@@ -530,7 +530,7 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
        seq_putc(m, ',');
        pos = m->count;
 
-       ret = ceph_print_client_options(m, fsc->client);
+       ret = ceph_print_client_options(m, fsc->client, false);
        if (ret)
                return ret;
 
@@ -640,7 +640,7 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
        opt = NULL; /* fsc->client now owns this */
 
        fsc->client->extra_mon_dispatch = extra_mon_dispatch;
-       fsc->client->osdc.abort_on_full = true;
+       ceph_set_opt(fsc->client, ABORT_ON_FULL);
 
        if (!fsopt->mds_namespace) {
                ceph_monc_want_map(&fsc->client->monc, CEPH_SUB_MDSMAP,
index 593fb42..e92a2fe 100644 (file)
@@ -252,6 +252,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
        seq_printf(m, ",ACL");
 #endif
        seq_putc(m, '\n');
+       seq_printf(m, "CIFSMaxBufSize: %d\n", CIFSMaxBufSize);
        seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid);
        seq_printf(m, "Servers:");
 
index 26776ed..7652551 100644 (file)
@@ -150,5 +150,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.15"
+#define CIFS_VERSION   "2.17"
 #endif                         /* _CIFSFS_H */
index 01ded70..94dbdbe 100644 (file)
@@ -1438,6 +1438,7 @@ struct mid_q_entry {
        int mid_state;  /* wish this were enum but can not pass to wait_event */
        unsigned int mid_flags;
        __le16 command;         /* smb command code */
+       unsigned int optype;    /* operation type */
        bool large_buf:1;       /* if valid response, is pointer to large buf */
        bool multiRsp:1;        /* multiple trans2 responses for one request  */
        bool multiEnd:1;        /* both received */
@@ -1574,6 +1575,25 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
        kfree(param);
 }
 
+static inline bool is_interrupt_error(int error)
+{
+       switch (error) {
+       case -EINTR:
+       case -ERESTARTSYS:
+       case -ERESTARTNOHAND:
+       case -ERESTARTNOINTR:
+               return true;
+       }
+       return false;
+}
+
+static inline bool is_retryable_error(int error)
+{
+       if (is_interrupt_error(error) || error == -EAGAIN)
+               return true;
+       return false;
+}
+
 #define   MID_FREE 0
 #define   MID_REQUEST_ALLOCATED 1
 #define   MID_REQUEST_SUBMITTED 2
index b1f49c1..bb54ccf 100644 (file)
@@ -128,24 +128,31 @@ static int __cifs_reconnect_tcon(const struct nls_table *nlsc,
        int rc;
        struct dfs_cache_tgt_list tl;
        struct dfs_cache_tgt_iterator *it = NULL;
-       char tree[MAX_TREE_SIZE + 1];
+       char *tree;
        const char *tcp_host;
        size_t tcp_host_len;
        const char *dfs_host;
        size_t dfs_host_len;
 
+       tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL);
+       if (!tree)
+               return -ENOMEM;
+
        if (tcon->ipc) {
-               snprintf(tree, sizeof(tree), "\\\\%s\\IPC$",
+               snprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$",
                         tcon->ses->server->hostname);
-               return CIFSTCon(0, tcon->ses, tree, tcon, nlsc);
+               rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc);
+               goto out;
        }
 
-       if (!tcon->dfs_path)
-               return CIFSTCon(0, tcon->ses, tcon->treeName, tcon, nlsc);
+       if (!tcon->dfs_path) {
+               rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, nlsc);
+               goto out;
+       }
 
        rc = dfs_cache_noreq_find(tcon->dfs_path + 1, NULL, &tl);
        if (rc)
-               return rc;
+               goto out;
 
        extract_unc_hostname(tcon->ses->server->hostname, &tcp_host,
                             &tcp_host_len);
@@ -165,7 +172,7 @@ static int __cifs_reconnect_tcon(const struct nls_table *nlsc,
                        continue;
                }
 
-               snprintf(tree, sizeof(tree), "\\%s", tgt);
+               snprintf(tree, MAX_TREE_SIZE, "\\%s", tgt);
 
                rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc);
                if (!rc)
@@ -182,6 +189,8 @@ static int __cifs_reconnect_tcon(const struct nls_table *nlsc,
                        rc = -ENOENT;
        }
        dfs_cache_free_tgts(&tl);
+out:
+       kfree(tree);
        return rc;
 }
 #else
@@ -1540,18 +1549,26 @@ cifs_discard_remaining_data(struct TCP_Server_Info *server)
 }
 
 static int
-cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+__cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid,
+                    bool malformed)
 {
        int length;
-       struct cifs_readdata *rdata = mid->callback_data;
 
        length = cifs_discard_remaining_data(server);
-       dequeue_mid(mid, rdata->result);
+       dequeue_mid(mid, malformed);
        mid->resp_buf = server->smallbuf;
        server->smallbuf = NULL;
        return length;
 }
 
+static int
+cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+{
+       struct cifs_readdata *rdata = mid->callback_data;
+
+       return  __cifs_readv_discard(server, mid, rdata->result);
+}
+
 int
 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 {
@@ -1593,12 +1610,23 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
                return -1;
        }
 
+       /* set up first two iov for signature check and to get credits */
+       rdata->iov[0].iov_base = buf;
+       rdata->iov[0].iov_len = 4;
+       rdata->iov[1].iov_base = buf + 4;
+       rdata->iov[1].iov_len = server->total_read - 4;
+       cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
+                rdata->iov[0].iov_base, rdata->iov[0].iov_len);
+       cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
+                rdata->iov[1].iov_base, rdata->iov[1].iov_len);
+
        /* Was the SMB read successful? */
        rdata->result = server->ops->map_error(buf, false);
        if (rdata->result != 0) {
                cifs_dbg(FYI, "%s: server returned error %d\n",
                         __func__, rdata->result);
-               return cifs_readv_discard(server, mid);
+               /* normal error on read response */
+               return __cifs_readv_discard(server, mid, false);
        }
 
        /* Is there enough to get to the rest of the READ_RSP header? */
@@ -1642,14 +1670,6 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
                server->total_read += length;
        }
 
-       /* set up first iov for signature check */
-       rdata->iov[0].iov_base = buf;
-       rdata->iov[0].iov_len = 4;
-       rdata->iov[1].iov_base = buf + 4;
-       rdata->iov[1].iov_len = server->total_read - 4;
-       cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n",
-                rdata->iov[0].iov_base, server->total_read);
-
        /* how much data is in the response? */
 #ifdef CONFIG_CIFS_SMB_DIRECT
        use_rdma_mr = rdata->mr;
@@ -2114,7 +2134,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata)
 
                for (j = 0; j < nr_pages; j++) {
                        unlock_page(wdata2->pages[j]);
-                       if (rc != 0 && rc != -EAGAIN) {
+                       if (rc != 0 && !is_retryable_error(rc)) {
                                SetPageError(wdata2->pages[j]);
                                end_page_writeback(wdata2->pages[j]);
                                put_page(wdata2->pages[j]);
@@ -2123,7 +2143,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata)
 
                if (rc) {
                        kref_put(&wdata2->refcount, cifs_writedata_release);
-                       if (rc == -EAGAIN)
+                       if (is_retryable_error(rc))
                                continue;
                        break;
                }
@@ -2132,7 +2152,8 @@ cifs_writev_requeue(struct cifs_writedata *wdata)
                i += nr_pages;
        } while (i < wdata->nr_pages);
 
-       mapping_set_error(inode->i_mapping, rc);
+       if (rc != 0 && !is_retryable_error(rc))
+               mapping_set_error(inode->i_mapping, rc);
        kref_put(&wdata->refcount, cifs_writedata_release);
 }
 
index f665296..8463c94 100644 (file)
@@ -433,9 +433,10 @@ static void reconn_inval_dfs_target(struct TCP_Server_Info *server,
        kfree(server->hostname);
 
        server->hostname = extract_hostname(name);
-       if (!server->hostname) {
-               cifs_dbg(FYI, "%s: failed to extract hostname from target: %d\n",
-                        __func__, -ENOMEM);
+       if (IS_ERR(server->hostname)) {
+               cifs_dbg(FYI,
+                        "%s: failed to extract hostname from target: %ld\n",
+                        __func__, PTR_ERR(server->hostname));
        }
 }
 
@@ -719,6 +720,21 @@ server_unresponsive(struct TCP_Server_Info *server)
        return false;
 }
 
+static inline bool
+zero_credits(struct TCP_Server_Info *server)
+{
+       int val;
+
+       spin_lock(&server->req_lock);
+       val = server->credits + server->echo_credits + server->oplock_credits;
+       if (server->in_flight == 0 && val == 0) {
+               spin_unlock(&server->req_lock);
+               return true;
+       }
+       spin_unlock(&server->req_lock);
+       return false;
+}
+
 static int
 cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
 {
@@ -731,6 +747,12 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
        for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
                try_to_freeze();
 
+               /* reconnect if no credits and no requests in flight */
+               if (zero_credits(server)) {
+                       cifs_reconnect(server);
+                       return -ECONNABORTED;
+               }
+
                if (server_unresponsive(server))
                        return -ECONNABORTED;
                if (cifs_rdma_enabled(server) && server->smbd_conn)
index cd63c4a..09b7d0d 100644 (file)
@@ -776,6 +776,7 @@ static int get_tgt_list(const struct dfs_cache_entry *ce,
                it->it_name = kstrndup(t->t_name, strlen(t->t_name),
                                       GFP_KERNEL);
                if (!it->it_name) {
+                       kfree(it);
                        rc = -ENOMEM;
                        goto err_free_it;
                }
index e3e3a75..659ce1b 100644 (file)
@@ -733,7 +733,8 @@ reopen_success:
 
        if (can_flush) {
                rc = filemap_write_and_wait(inode->i_mapping);
-               mapping_set_error(inode->i_mapping, rc);
+               if (!is_interrupt_error(rc))
+                       mapping_set_error(inode->i_mapping, rc);
 
                if (tcon->unix_ext)
                        rc = cifs_get_inode_info_unix(&inode, full_path,
@@ -1132,14 +1133,18 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
 
        /*
         * Accessing maxBuf is racy with cifs_reconnect - need to store value
-        * and check it for zero before using.
+        * and check it before using.
         */
        max_buf = tcon->ses->server->maxBuf;
-       if (!max_buf) {
+       if (max_buf < (sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE))) {
                free_xid(xid);
                return -EINVAL;
        }
 
+       BUILD_BUG_ON(sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE) >
+                    PAGE_SIZE);
+       max_buf = min_t(unsigned int, max_buf - sizeof(struct smb_hdr),
+                       PAGE_SIZE);
        max_num = (max_buf - sizeof(struct smb_hdr)) /
                                                sizeof(LOCKING_ANDX_RANGE);
        buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
@@ -1472,12 +1477,16 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
 
        /*
         * Accessing maxBuf is racy with cifs_reconnect - need to store value
-        * and check it for zero before using.
+        * and check it before using.
         */
        max_buf = tcon->ses->server->maxBuf;
-       if (!max_buf)
+       if (max_buf < (sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE)))
                return -EINVAL;
 
+       BUILD_BUG_ON(sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE) >
+                    PAGE_SIZE);
+       max_buf = min_t(unsigned int, max_buf - sizeof(struct smb_hdr),
+                       PAGE_SIZE);
        max_num = (max_buf - sizeof(struct smb_hdr)) /
                                                sizeof(LOCKING_ANDX_RANGE);
        buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
@@ -2110,6 +2119,7 @@ static int cifs_writepages(struct address_space *mapping,
        pgoff_t end, index;
        struct cifs_writedata *wdata;
        int rc = 0;
+       int saved_rc = 0;
        unsigned int xid;
 
        /*
@@ -2138,8 +2148,10 @@ retry:
 
                rc = server->ops->wait_mtu_credits(server, cifs_sb->wsize,
                                                   &wsize, &credits);
-               if (rc)
+               if (rc != 0) {
+                       done = true;
                        break;
+               }
 
                tofind = min((wsize / PAGE_SIZE) - 1, end - index) + 1;
 
@@ -2147,6 +2159,7 @@ retry:
                                                  &found_pages);
                if (!wdata) {
                        rc = -ENOMEM;
+                       done = true;
                        add_credits_and_wake_if(server, credits, 0);
                        break;
                }
@@ -2175,7 +2188,7 @@ retry:
                if (rc != 0) {
                        add_credits_and_wake_if(server, wdata->credits, 0);
                        for (i = 0; i < nr_pages; ++i) {
-                               if (rc == -EAGAIN)
+                               if (is_retryable_error(rc))
                                        redirty_page_for_writepage(wbc,
                                                           wdata->pages[i]);
                                else
@@ -2183,7 +2196,7 @@ retry:
                                end_page_writeback(wdata->pages[i]);
                                put_page(wdata->pages[i]);
                        }
-                       if (rc != -EAGAIN)
+                       if (!is_retryable_error(rc))
                                mapping_set_error(mapping, rc);
                }
                kref_put(&wdata->refcount, cifs_writedata_release);
@@ -2193,6 +2206,15 @@ retry:
                        continue;
                }
 
+               /* Return immediately if we received a signal during writing */
+               if (is_interrupt_error(rc)) {
+                       done = true;
+                       break;
+               }
+
+               if (rc != 0 && saved_rc == 0)
+                       saved_rc = rc;
+
                wbc->nr_to_write -= nr_pages;
                if (wbc->nr_to_write <= 0)
                        done = true;
@@ -2210,6 +2232,9 @@ retry:
                goto retry;
        }
 
+       if (saved_rc != 0)
+               rc = saved_rc;
+
        if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
                mapping->writeback_index = index;
 
@@ -2242,8 +2267,8 @@ cifs_writepage_locked(struct page *page, struct writeback_control *wbc)
        set_page_writeback(page);
 retry_write:
        rc = cifs_partialpagewrite(page, 0, PAGE_SIZE);
-       if (rc == -EAGAIN) {
-               if (wbc->sync_mode == WB_SYNC_ALL)
+       if (is_retryable_error(rc)) {
+               if (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN)
                        goto retry_write;
                redirty_page_for_writepage(wbc, page);
        } else if (rc != 0) {
@@ -2671,6 +2696,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
 
                        rc = cifs_write_allocate_pages(wdata->pages, nr_pages);
                        if (rc) {
+                               kvfree(wdata->pages);
                                kfree(wdata);
                                add_credits_and_wake_if(server, credits, 0);
                                break;
@@ -2682,6 +2708,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
                        if (rc) {
                                for (i = 0; i < nr_pages; i++)
                                        put_page(wdata->pages[i]);
+                               kvfree(wdata->pages);
                                kfree(wdata);
                                add_credits_and_wake_if(server, credits, 0);
                                break;
@@ -3361,8 +3388,12 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
                        }
 
                        rc = cifs_read_allocate_pages(rdata, npages);
-                       if (rc)
-                               goto error;
+                       if (rc) {
+                               kvfree(rdata->pages);
+                               kfree(rdata);
+                               add_credits_and_wake_if(server, credits, 0);
+                               break;
+                       }
 
                        rdata->tailsz = PAGE_SIZE;
                }
@@ -3382,7 +3413,6 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
                if (!rdata->cfile->invalidHandle ||
                    !(rc = cifs_reopen_file(rdata->cfile, true)))
                        rc = server->ops->async_readv(rdata);
-error:
                if (rc) {
                        add_credits_and_wake_if(server, rdata->credits, 0);
                        kref_put(&rdata->refcount,
index 13fb59a..4780036 100644 (file)
@@ -2257,6 +2257,11 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
         * the flush returns error?
         */
        rc = filemap_write_and_wait(inode->i_mapping);
+       if (is_interrupt_error(rc)) {
+               rc = -ERESTARTSYS;
+               goto out;
+       }
+
        mapping_set_error(inode->i_mapping, rc);
        rc = 0;
 
@@ -2400,6 +2405,11 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
         * the flush returns error?
         */
        rc = filemap_write_and_wait(inode->i_mapping);
+       if (is_interrupt_error(rc)) {
+               rc = -ERESTARTSYS;
+               goto cifs_setattr_exit;
+       }
+
        mapping_set_error(inode->i_mapping, rc);
        rc = 0;
 
index 4ed10dd..b204e84 100644 (file)
@@ -122,12 +122,14 @@ smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
 
        /*
         * Accessing maxBuf is racy with cifs_reconnect - need to store value
-        * and check it for zero before using.
+        * and check it before using.
         */
        max_buf = tcon->ses->server->maxBuf;
-       if (!max_buf)
+       if (max_buf < sizeof(struct smb2_lock_element))
                return -EINVAL;
 
+       BUILD_BUG_ON(sizeof(struct smb2_lock_element) > PAGE_SIZE);
+       max_buf = min_t(unsigned int, max_buf, PAGE_SIZE);
        max_num = max_buf / sizeof(struct smb2_lock_element);
        buf = kcalloc(max_num, sizeof(struct smb2_lock_element), GFP_KERNEL);
        if (!buf)
@@ -264,6 +266,8 @@ smb2_push_mandatory_locks(struct cifsFileInfo *cfile)
                return -EINVAL;
        }
 
+       BUILD_BUG_ON(sizeof(struct smb2_lock_element) > PAGE_SIZE);
+       max_buf = min_t(unsigned int, max_buf, PAGE_SIZE);
        max_num = max_buf / sizeof(struct smb2_lock_element);
        buf = kcalloc(max_num, sizeof(struct smb2_lock_element), GFP_KERNEL);
        if (!buf) {
index f14533d..01a76bc 100644 (file)
@@ -293,6 +293,8 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
        int rc;
        struct smb2_file_all_info *smb2_data;
        __u32 create_options = 0;
+       struct cifs_fid fid;
+       bool no_cached_open = tcon->nohandlecache;
 
        *adjust_tz = false;
        *symlink = false;
@@ -301,6 +303,21 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
                            GFP_KERNEL);
        if (smb2_data == NULL)
                return -ENOMEM;
+
+       /* If it is a root and its handle is cached then use it */
+       if (!strlen(full_path) && !no_cached_open) {
+               rc = open_shroot(xid, tcon, &fid);
+               if (rc)
+                       goto out;
+               rc = SMB2_query_info(xid, tcon, fid.persistent_fid,
+                                    fid.volatile_fid, smb2_data);
+               close_shroot(&tcon->crfid);
+               if (rc)
+                       goto out;
+               move_smb2_info_to_cifs(data, smb2_data);
+               goto out;
+       }
+
        if (backup_cred(cifs_sb))
                create_options |= CREATE_OPEN_BACKUP_INTENT;
 
index 6a9c475..7b8b58f 100644 (file)
@@ -648,6 +648,13 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
        if (rsp->sync_hdr.Command != SMB2_OPLOCK_BREAK)
                return false;
 
+       if (rsp->sync_hdr.CreditRequest) {
+               spin_lock(&server->req_lock);
+               server->credits += le16_to_cpu(rsp->sync_hdr.CreditRequest);
+               spin_unlock(&server->req_lock);
+               wake_up(&server->request_q);
+       }
+
        if (rsp->StructureSize !=
                                smb2_rsp_struct_sizes[SMB2_OPLOCK_BREAK_HE]) {
                if (le16_to_cpu(rsp->StructureSize) == 44)
index cf7eb89..6f96e22 100644 (file)
@@ -34,6 +34,7 @@
 #include "cifs_ioctl.h"
 #include "smbdirect.h"
 
+/* Change credits for different ops and return the total number of credits */
 static int
 change_conf(struct TCP_Server_Info *server)
 {
@@ -41,17 +42,15 @@ change_conf(struct TCP_Server_Info *server)
        server->oplock_credits = server->echo_credits = 0;
        switch (server->credits) {
        case 0:
-               return -1;
+               return 0;
        case 1:
                server->echoes = false;
                server->oplocks = false;
-               cifs_dbg(VFS, "disabling echoes and oplocks\n");
                break;
        case 2:
                server->echoes = true;
                server->oplocks = false;
                server->echo_credits = 1;
-               cifs_dbg(FYI, "disabling oplocks\n");
                break;
        default:
                server->echoes = true;
@@ -64,14 +63,15 @@ change_conf(struct TCP_Server_Info *server)
                server->echo_credits = 1;
        }
        server->credits -= server->echo_credits + server->oplock_credits;
-       return 0;
+       return server->credits + server->echo_credits + server->oplock_credits;
 }
 
 static void
 smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
                 const int optype)
 {
-       int *val, rc = 0;
+       int *val, rc = -1;
+
        spin_lock(&server->req_lock);
        val = server->ops->get_credits_field(server, optype);
 
@@ -101,8 +101,26 @@ smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
        }
        spin_unlock(&server->req_lock);
        wake_up(&server->request_q);
-       if (rc)
-               cifs_reconnect(server);
+
+       if (server->tcpStatus == CifsNeedReconnect)
+               return;
+
+       switch (rc) {
+       case -1:
+               /* change_conf hasn't been executed */
+               break;
+       case 0:
+               cifs_dbg(VFS, "Possible client or server bug - zero credits\n");
+               break;
+       case 1:
+               cifs_dbg(VFS, "disabling echoes and oplocks\n");
+               break;
+       case 2:
+               cifs_dbg(FYI, "disabling oplocks\n");
+               break;
+       default:
+               cifs_dbg(FYI, "add %u credits total=%d\n", add, rc);
+       }
 }
 
 static void
@@ -136,7 +154,11 @@ smb2_get_credits(struct mid_q_entry *mid)
 {
        struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)mid->resp_buf;
 
-       return le16_to_cpu(shdr->CreditRequest);
+       if (mid->mid_state == MID_RESPONSE_RECEIVED
+           || mid->mid_state == MID_RESPONSE_MALFORMED)
+               return le16_to_cpu(shdr->CreditRequest);
+
+       return 0;
 }
 
 static int
@@ -165,14 +187,14 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
 
                        scredits = server->credits;
                        /* can deadlock with reopen */
-                       if (scredits == 1) {
+                       if (scredits <= 8) {
                                *num = SMB2_MAX_BUFFER_SIZE;
                                *credits = 0;
                                break;
                        }
 
-                       /* leave one credit for a possible reopen */
-                       scredits--;
+                       /* leave some credits for reopen and other ops */
+                       scredits -= 8;
                        *num = min_t(unsigned int, size,
                                     scredits * SMB2_MAX_BUFFER_SIZE);
 
@@ -844,7 +866,9 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
                                      FILE_READ_EA,
                                      FILE_FULL_EA_INFORMATION,
                                      SMB2_O_INFO_FILE,
-                                     SMB2_MAX_EA_BUF,
+                                     CIFSMaxBufSize -
+                                     MAX_SMB2_CREATE_RESPONSE_SIZE -
+                                     MAX_SMB2_CLOSE_RESPONSE_SIZE,
                                      &rsp_iov, &buftype, cifs_sb);
        if (rc) {
                /*
@@ -3189,11 +3213,23 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
                        server->ops->is_status_pending(buf, server, 0))
                return -1;
 
-       rdata->result = server->ops->map_error(buf, false);
+       /* set up first two iov to get credits */
+       rdata->iov[0].iov_base = buf;
+       rdata->iov[0].iov_len = 4;
+       rdata->iov[1].iov_base = buf + 4;
+       rdata->iov[1].iov_len =
+               min_t(unsigned int, buf_len, server->vals->read_rsp_size) - 4;
+       cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
+                rdata->iov[0].iov_base, rdata->iov[0].iov_len);
+       cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
+                rdata->iov[1].iov_base, rdata->iov[1].iov_len);
+
+       rdata->result = server->ops->map_error(buf, true);
        if (rdata->result != 0) {
                cifs_dbg(FYI, "%s: server returned error %d\n",
                         __func__, rdata->result);
-               dequeue_mid(mid, rdata->result);
+               /* normal error on read response */
+               dequeue_mid(mid, false);
                return 0;
        }
 
@@ -3266,14 +3302,6 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
                return 0;
        }
 
-       /* set up first iov for signature check */
-       rdata->iov[0].iov_base = buf;
-       rdata->iov[0].iov_len = 4;
-       rdata->iov[1].iov_base = buf + 4;
-       rdata->iov[1].iov_len = server->vals->read_rsp_size - 4;
-       cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
-                rdata->iov[0].iov_base, server->vals->read_rsp_size);
-
        length = rdata->copy_into_pages(server, rdata, &iter);
 
        kfree(bvec);
index e57f6aa..77b3aaa 100644 (file)
@@ -162,24 +162,31 @@ static int __smb2_reconnect(const struct nls_table *nlsc,
        int rc;
        struct dfs_cache_tgt_list tl;
        struct dfs_cache_tgt_iterator *it = NULL;
-       char tree[MAX_TREE_SIZE + 1];
+       char *tree;
        const char *tcp_host;
        size_t tcp_host_len;
        const char *dfs_host;
        size_t dfs_host_len;
 
+       tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL);
+       if (!tree)
+               return -ENOMEM;
+
        if (tcon->ipc) {
-               snprintf(tree, sizeof(tree), "\\\\%s\\IPC$",
+               snprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$",
                         tcon->ses->server->hostname);
-               return SMB2_tcon(0, tcon->ses, tree, tcon, nlsc);
+               rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc);
+               goto out;
        }
 
-       if (!tcon->dfs_path)
-               return SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nlsc);
+       if (!tcon->dfs_path) {
+               rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nlsc);
+               goto out;
+       }
 
        rc = dfs_cache_noreq_find(tcon->dfs_path + 1, NULL, &tl);
        if (rc)
-               return rc;
+               goto out;
 
        extract_unc_hostname(tcon->ses->server->hostname, &tcp_host,
                             &tcp_host_len);
@@ -199,7 +206,7 @@ static int __smb2_reconnect(const struct nls_table *nlsc,
                        continue;
                }
 
-               snprintf(tree, sizeof(tree), "\\%s", tgt);
+               snprintf(tree, MAX_TREE_SIZE, "\\%s", tgt);
 
                rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc);
                if (!rc)
@@ -216,6 +223,8 @@ static int __smb2_reconnect(const struct nls_table *nlsc,
                        rc = -ENOENT;
        }
        dfs_cache_free_tgts(&tl);
+out:
+       kfree(tree);
        return rc;
 }
 #else
@@ -2807,6 +2816,7 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
        int resp_buftype = CIFS_NO_BUFFER;
        struct cifs_ses *ses = tcon->ses;
        int flags = 0;
+       bool allocated = false;
 
        cifs_dbg(FYI, "Query Info\n");
 
@@ -2846,14 +2856,21 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
                                        "Error %d allocating memory for acl\n",
                                        rc);
                                *dlen = 0;
+                               rc = -ENOMEM;
                                goto qinf_exit;
                        }
+                       allocated = true;
                }
        }
 
        rc = smb2_validate_and_copy_iov(le16_to_cpu(rsp->OutputBufferOffset),
                                        le32_to_cpu(rsp->OutputBufferLength),
                                        &rsp_iov, min_len, *data);
+       if (rc && allocated) {
+               kfree(*data);
+               *data = NULL;
+               *dlen = 0;
+       }
 
 qinf_exit:
        SMB2_query_info_free(&rqst);
@@ -2907,9 +2924,10 @@ smb2_echo_callback(struct mid_q_entry *mid)
 {
        struct TCP_Server_Info *server = mid->callback_data;
        struct smb2_echo_rsp *rsp = (struct smb2_echo_rsp *)mid->resp_buf;
-       unsigned int credits_received = 1;
+       unsigned int credits_received = 0;
 
-       if (mid->mid_state == MID_RESPONSE_RECEIVED)
+       if (mid->mid_state == MID_RESPONSE_RECEIVED
+           || mid->mid_state == MID_RESPONSE_MALFORMED)
                credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest);
 
        DeleteMidQEntry(mid);
@@ -3166,7 +3184,7 @@ smb2_readv_callback(struct mid_q_entry *mid)
        struct TCP_Server_Info *server = tcon->ses->server;
        struct smb2_sync_hdr *shdr =
                                (struct smb2_sync_hdr *)rdata->iov[0].iov_base;
-       unsigned int credits_received = 1;
+       unsigned int credits_received = 0;
        struct smb_rqst rqst = { .rq_iov = rdata->iov,
                                 .rq_nvec = 2,
                                 .rq_pages = rdata->pages,
@@ -3205,6 +3223,9 @@ smb2_readv_callback(struct mid_q_entry *mid)
                task_io_account_read(rdata->got_bytes);
                cifs_stats_bytes_read(tcon, rdata->got_bytes);
                break;
+       case MID_RESPONSE_MALFORMED:
+               credits_received = le16_to_cpu(shdr->CreditRequest);
+               /* fall through */
        default:
                if (rdata->result != -ENODATA)
                        rdata->result = -EIO;
@@ -3220,8 +3241,17 @@ smb2_readv_callback(struct mid_q_entry *mid)
                rdata->mr = NULL;
        }
 #endif
-       if (rdata->result)
+       if (rdata->result && rdata->result != -ENODATA) {
                cifs_stats_fail_inc(tcon, SMB2_READ_HE);
+               trace_smb3_read_err(0 /* xid */,
+                                   rdata->cfile->fid.persistent_fid,
+                                   tcon->tid, tcon->ses->Suid, rdata->offset,
+                                   rdata->bytes, rdata->result);
+       } else
+               trace_smb3_read_done(0 /* xid */,
+                                    rdata->cfile->fid.persistent_fid,
+                                    tcon->tid, tcon->ses->Suid,
+                                    rdata->offset, rdata->got_bytes);
 
        queue_work(cifsiod_wq, &rdata->work);
        DeleteMidQEntry(mid);
@@ -3278,12 +3308,14 @@ smb2_async_readv(struct cifs_readdata *rdata)
        if (rdata->credits) {
                shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes,
                                                SMB2_MAX_BUFFER_SIZE));
-               shdr->CreditRequest = shdr->CreditCharge;
+               shdr->CreditRequest =
+                       cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 1);
                spin_lock(&server->req_lock);
                server->credits += rdata->credits -
                                                le16_to_cpu(shdr->CreditCharge);
                spin_unlock(&server->req_lock);
                wake_up(&server->request_q);
+               rdata->credits = le16_to_cpu(shdr->CreditCharge);
                flags |= CIFS_HAS_CREDITS;
        }
 
@@ -3294,13 +3326,11 @@ smb2_async_readv(struct cifs_readdata *rdata)
        if (rc) {
                kref_put(&rdata->refcount, cifs_readdata_release);
                cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE);
-               trace_smb3_read_err(rc, 0 /* xid */, io_parms.persistent_fid,
-                                  io_parms.tcon->tid, io_parms.tcon->ses->Suid,
-                                  io_parms.offset, io_parms.length);
-       } else
-               trace_smb3_read_done(0 /* xid */, io_parms.persistent_fid,
-                                  io_parms.tcon->tid, io_parms.tcon->ses->Suid,
-                                  io_parms.offset, io_parms.length);
+               trace_smb3_read_err(0 /* xid */, io_parms.persistent_fid,
+                                   io_parms.tcon->tid,
+                                   io_parms.tcon->ses->Suid,
+                                   io_parms.offset, io_parms.length, rc);
+       }
 
        cifs_small_buf_release(buf);
        return rc;
@@ -3344,10 +3374,11 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
                if (rc != -ENODATA) {
                        cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE);
                        cifs_dbg(VFS, "Send error in read = %d\n", rc);
+                       trace_smb3_read_err(xid, req->PersistentFileId,
+                                           io_parms->tcon->tid, ses->Suid,
+                                           io_parms->offset, io_parms->length,
+                                           rc);
                }
-               trace_smb3_read_err(rc, xid, req->PersistentFileId,
-                                   io_parms->tcon->tid, ses->Suid,
-                                   io_parms->offset, io_parms->length);
                free_rsp_buf(resp_buftype, rsp_iov.iov_base);
                return rc == -ENODATA ? 0 : rc;
        } else
@@ -3388,7 +3419,7 @@ smb2_writev_callback(struct mid_q_entry *mid)
        struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
        unsigned int written;
        struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf;
-       unsigned int credits_received = 1;
+       unsigned int credits_received = 0;
 
        switch (mid->mid_state) {
        case MID_RESPONSE_RECEIVED:
@@ -3416,6 +3447,9 @@ smb2_writev_callback(struct mid_q_entry *mid)
        case MID_RETRY_NEEDED:
                wdata->result = -EAGAIN;
                break;
+       case MID_RESPONSE_MALFORMED:
+               credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest);
+               /* fall through */
        default:
                wdata->result = -EIO;
                break;
@@ -3433,8 +3467,17 @@ smb2_writev_callback(struct mid_q_entry *mid)
                wdata->mr = NULL;
        }
 #endif
-       if (wdata->result)
+       if (wdata->result) {
                cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
+               trace_smb3_write_err(0 /* no xid */,
+                                    wdata->cfile->fid.persistent_fid,
+                                    tcon->tid, tcon->ses->Suid, wdata->offset,
+                                    wdata->bytes, wdata->result);
+       } else
+               trace_smb3_write_done(0 /* no xid */,
+                                     wdata->cfile->fid.persistent_fid,
+                                     tcon->tid, tcon->ses->Suid,
+                                     wdata->offset, wdata->bytes);
 
        queue_work(cifsiod_wq, &wdata->work);
        DeleteMidQEntry(mid);
@@ -3555,12 +3598,14 @@ smb2_async_writev(struct cifs_writedata *wdata,
        if (wdata->credits) {
                shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes,
                                                    SMB2_MAX_BUFFER_SIZE));
-               shdr->CreditRequest = shdr->CreditCharge;
+               shdr->CreditRequest =
+                       cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 1);
                spin_lock(&server->req_lock);
                server->credits += wdata->credits -
                                                le16_to_cpu(shdr->CreditCharge);
                spin_unlock(&server->req_lock);
                wake_up(&server->request_q);
+               wdata->credits = le16_to_cpu(shdr->CreditCharge);
                flags |= CIFS_HAS_CREDITS;
        }
 
@@ -3574,10 +3619,7 @@ smb2_async_writev(struct cifs_writedata *wdata,
                                     wdata->bytes, rc);
                kref_put(&wdata->refcount, release);
                cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
-       } else
-               trace_smb3_write_done(0 /* no xid */, req->PersistentFileId,
-                                    tcon->tid, tcon->ses->Suid, wdata->offset,
-                                    wdata->bytes);
+       }
 
 async_writev_out:
        cifs_small_buf_release(req);
@@ -3803,8 +3845,8 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
                    rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) {
                        srch_inf->endOfSearch = true;
                        rc = 0;
-               }
-               cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
+               } else
+                       cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
                goto qdir_exit;
        }
 
@@ -4399,8 +4441,8 @@ SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
        rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov);
        cifs_small_buf_release(req);
 
-       please_key_low = (__u64 *)req->LeaseKey;
-       please_key_high = (__u64 *)(req->LeaseKey+8);
+       please_key_low = (__u64 *)lease_key;
+       please_key_high = (__u64 *)(lease_key+8);
        if (rc) {
                cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE);
                trace_smb3_lease_err(le32_to_cpu(lease_state), tcon->tid,
index 7a2d0a2..538e229 100644 (file)
@@ -84,8 +84,9 @@
 
 #define NUMBER_OF_SMB2_COMMANDS        0x0013
 
-/* 4 len + 52 transform hdr + 64 hdr + 56 create rsp */
-#define MAX_SMB2_HDR_SIZE 0x00b0
+/* 52 transform hdr + 64 hdr + 88 create rsp */
+#define SMB2_TRANSFORM_HEADER_SIZE 52
+#define MAX_SMB2_HDR_SIZE 204
 
 #define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe)
 #define SMB2_TRANSFORM_PROTO_NUM cpu_to_le32(0x424d53fd)
@@ -648,6 +649,13 @@ struct smb2_create_req {
        __u8   Buffer[0];
 } __packed;
 
+/*
+ * Maximum size of a SMB2_CREATE response is 64 (smb2 header) +
+ * 88 (fixed part of create response) + 520 (path) + 150 (contexts) +
+ * 2 bytes of padding.
+ */
+#define MAX_SMB2_CREATE_RESPONSE_SIZE 824
+
 struct smb2_create_rsp {
        struct smb2_sync_hdr sync_hdr;
        __le16 StructureSize;   /* Must be 89 */
@@ -996,6 +1004,11 @@ struct smb2_close_req {
        __u64  VolatileFileId; /* opaque endianness */
 } __packed;
 
+/*
+ * Maximum size of a SMB2_CLOSE response is 64 (smb2 header) + 60 (data)
+ */
+#define MAX_SMB2_CLOSE_RESPONSE_SIZE 124
+
 struct smb2_close_rsp {
        struct smb2_sync_hdr sync_hdr;
        __le16 StructureSize; /* 60 */
@@ -1398,8 +1411,6 @@ struct smb2_file_link_info { /* encoding of request for level 11 */
        char   FileName[0];     /* Name to be assigned to new link */
 } __packed; /* level 11 Set */
 
-#define SMB2_MAX_EA_BUF 65536
-
 struct smb2_file_full_ea_info { /* encoding of response for level 15 */
        __le32 next_entry_offset;
        __u8   flags;
index bd4a546..4654837 100644 (file)
@@ -3,16 +3,6 @@
  *   Copyright (C) 2018, Microsoft Corporation.
  *
  *   Author(s): Steve French <stfrench@microsoft.com>
- *
- *   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.  See
- *   the GNU General Public License for more details.
  */
 #define CREATE_TRACE_POINTS
 #include "trace.h"
index fb04980..59be482 100644 (file)
@@ -3,16 +3,6 @@
  *   Copyright (C) 2018, Microsoft Corporation.
  *
  *   Author(s): Steve French <stfrench@microsoft.com>
- *
- *   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.  See
- *   the GNU General Public License for more details.
  */
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM cifs
index 5be7302..53532bd 100644 (file)
@@ -387,7 +387,7 @@ smbd_done:
        if (rc < 0 && rc != -EINTR)
                cifs_dbg(VFS, "Error %d sending data on socket to server\n",
                         rc);
-       else
+       else if (rc > 0)
                rc = 0;
 
        return rc;
@@ -783,8 +783,25 @@ cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
 }
 
 static void
-cifs_noop_callback(struct mid_q_entry *mid)
+cifs_compound_callback(struct mid_q_entry *mid)
+{
+       struct TCP_Server_Info *server = mid->server;
+
+       add_credits(server, server->ops->get_credits(mid), mid->optype);
+}
+
+static void
+cifs_compound_last_callback(struct mid_q_entry *mid)
 {
+       cifs_compound_callback(mid);
+       cifs_wake_up_task(mid);
+}
+
+static void
+cifs_cancelled_callback(struct mid_q_entry *mid)
+{
+       cifs_compound_callback(mid);
+       DeleteMidQEntry(mid);
 }
 
 int
@@ -795,7 +812,8 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
        int i, j, rc = 0;
        int timeout, optype;
        struct mid_q_entry *midQ[MAX_COMPOUND];
-       unsigned int credits = 0;
+       bool cancelled_mid[MAX_COMPOUND] = {false};
+       unsigned int credits[MAX_COMPOUND] = {0};
        char *buf;
 
        timeout = flags & CIFS_TIMEOUT_MASK;
@@ -813,13 +831,31 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
                return -ENOENT;
 
        /*
-        * Ensure that we do not send more than 50 overlapping requests
-        * to the same server. We may make this configurable later or
-        * use ses->maxReq.
+        * Ensure we obtain 1 credit per request in the compound chain.
+        * It can be optimized further by waiting for all the credits
+        * at once but this can wait long enough if we don't have enough
+        * credits due to some heavy operations in progress or the server
+        * not granting us much, so a fallback to the current approach is
+        * needed anyway.
         */
-       rc = wait_for_free_request(ses->server, timeout, optype);
-       if (rc)
-               return rc;
+       for (i = 0; i < num_rqst; i++) {
+               rc = wait_for_free_request(ses->server, timeout, optype);
+               if (rc) {
+                       /*
+                        * We haven't sent an SMB packet to the server yet but
+                        * we already obtained credits for i requests in the
+                        * compound chain - need to return those credits back
+                        * for future use. Note that we need to call add_credits
+                        * multiple times to match the way we obtained credits
+                        * in the first place and to account for in flight
+                        * requests correctly.
+                        */
+                       for (j = 0; j < i; j++)
+                               add_credits(ses->server, 1, optype);
+                       return rc;
+               }
+               credits[i] = 1;
+       }
 
        /*
         * Make sure that we sign in the same order that we send on this socket
@@ -835,18 +871,24 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
                        for (j = 0; j < i; j++)
                                cifs_delete_mid(midQ[j]);
                        mutex_unlock(&ses->server->srv_mutex);
+
                        /* Update # of requests on wire to server */
-                       add_credits(ses->server, 1, optype);
+                       for (j = 0; j < num_rqst; j++)
+                               add_credits(ses->server, credits[j], optype);
                        return PTR_ERR(midQ[i]);
                }
 
                midQ[i]->mid_state = MID_REQUEST_SUBMITTED;
+               midQ[i]->optype = optype;
                /*
-                * We don't invoke the callback compounds unless it is the last
-                * request.
+                * Invoke callback for every part of the compound chain
+                * to calculate credits properly. Wake up this thread only when
+                * the last element is received.
                 */
                if (i < num_rqst - 1)
-                       midQ[i]->callback = cifs_noop_callback;
+                       midQ[i]->callback = cifs_compound_callback;
+               else
+                       midQ[i]->callback = cifs_compound_last_callback;
        }
        cifs_in_send_inc(ses->server);
        rc = smb_send_rqst(ses->server, num_rqst, rqst, flags);
@@ -860,8 +902,20 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
 
        mutex_unlock(&ses->server->srv_mutex);
 
-       if (rc < 0)
+       if (rc < 0) {
+               /* Sending failed for some reason - return credits back */
+               for (i = 0; i < num_rqst; i++)
+                       add_credits(ses->server, credits[i], optype);
                goto out;
+       }
+
+       /*
+        * At this point the request is passed to the network stack - we assume
+        * that any credits taken from the server structure on the client have
+        * been spent and we can't return them back. Once we receive responses
+        * we will collect credits granted by the server in the mid callbacks
+        * and add those credits to the server structure.
+        */
 
        /*
         * Compounding is never used during session establish.
@@ -875,36 +929,34 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
 
        for (i = 0; i < num_rqst; i++) {
                rc = wait_for_response(ses->server, midQ[i]);
-               if (rc != 0) {
+               if (rc != 0)
+                       break;
+       }
+       if (rc != 0) {
+               for (; i < num_rqst; i++) {
                        cifs_dbg(VFS, "Cancelling wait for mid %llu cmd: %d\n",
                                 midQ[i]->mid, le16_to_cpu(midQ[i]->command));
                        send_cancel(ses->server, &rqst[i], midQ[i]);
                        spin_lock(&GlobalMid_Lock);
                        if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) {
                                midQ[i]->mid_flags |= MID_WAIT_CANCELLED;
-                               midQ[i]->callback = DeleteMidQEntry;
-                               spin_unlock(&GlobalMid_Lock);
-                               add_credits(ses->server, 1, optype);
-                               return rc;
+                               midQ[i]->callback = cifs_cancelled_callback;
+                               cancelled_mid[i] = true;
+                               credits[i] = 0;
                        }
                        spin_unlock(&GlobalMid_Lock);
                }
        }
 
-       for (i = 0; i < num_rqst; i++)
-               if (midQ[i]->resp_buf)
-                       credits += ses->server->ops->get_credits(midQ[i]);
-       if (!credits)
-               credits = 1;
-
        for (i = 0; i < num_rqst; i++) {
                if (rc < 0)
                        goto out;
 
                rc = cifs_sync_mid_result(midQ[i], ses->server);
                if (rc != 0) {
-                       add_credits(ses->server, credits, optype);
-                       return rc;
+                       /* mark this mid as cancelled to not free it below */
+                       cancelled_mid[i] = true;
+                       goto out;
                }
 
                if (!midQ[i]->resp_buf ||
@@ -951,9 +1003,10 @@ out:
         * This is prevented above by using a noop callback that will not
         * wake this thread except for the very last PDU.
         */
-       for (i = 0; i < num_rqst; i++)
-               cifs_delete_mid(midQ[i]);
-       add_credits(ses->server, credits, optype);
+       for (i = 0; i < num_rqst; i++) {
+               if (!cancelled_mid[i])
+                       cifs_delete_mid(midQ[i]);
+       }
 
        return rc;
 }
index 2593153..aac41ad 100644 (file)
@@ -119,6 +119,7 @@ struct dentry_stat_t dentry_stat = {
 
 static DEFINE_PER_CPU(long, nr_dentry);
 static DEFINE_PER_CPU(long, nr_dentry_unused);
+static DEFINE_PER_CPU(long, nr_dentry_negative);
 
 #if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)
 
@@ -152,11 +153,22 @@ static long get_nr_dentry_unused(void)
        return sum < 0 ? 0 : sum;
 }
 
+static long get_nr_dentry_negative(void)
+{
+       int i;
+       long sum = 0;
+
+       for_each_possible_cpu(i)
+               sum += per_cpu(nr_dentry_negative, i);
+       return sum < 0 ? 0 : sum;
+}
+
 int proc_nr_dentry(struct ctl_table *table, int write, void __user *buffer,
                   size_t *lenp, loff_t *ppos)
 {
        dentry_stat.nr_dentry = get_nr_dentry();
        dentry_stat.nr_unused = get_nr_dentry_unused();
+       dentry_stat.nr_negative = get_nr_dentry_negative();
        return proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
 }
 #endif
@@ -317,6 +329,8 @@ static inline void __d_clear_type_and_inode(struct dentry *dentry)
        flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU);
        WRITE_ONCE(dentry->d_flags, flags);
        dentry->d_inode = NULL;
+       if (dentry->d_flags & DCACHE_LRU_LIST)
+               this_cpu_inc(nr_dentry_negative);
 }
 
 static void dentry_free(struct dentry *dentry)
@@ -371,6 +385,11 @@ static void dentry_unlink_inode(struct dentry * dentry)
  * The per-cpu "nr_dentry_unused" counters are updated with
  * the DCACHE_LRU_LIST bit.
  *
+ * The per-cpu "nr_dentry_negative" counters are only updated
+ * when deleted from or added to the per-superblock LRU list, not
+ * from/to the shrink list. That is to avoid an unneeded dec/inc
+ * pair when moving from LRU to shrink list in select_collect().
+ *
  * These helper functions make sure we always follow the
  * rules. d_lock must be held by the caller.
  */
@@ -380,6 +399,8 @@ static void d_lru_add(struct dentry *dentry)
        D_FLAG_VERIFY(dentry, 0);
        dentry->d_flags |= DCACHE_LRU_LIST;
        this_cpu_inc(nr_dentry_unused);
+       if (d_is_negative(dentry))
+               this_cpu_inc(nr_dentry_negative);
        WARN_ON_ONCE(!list_lru_add(&dentry->d_sb->s_dentry_lru, &dentry->d_lru));
 }
 
@@ -388,6 +409,8 @@ static void d_lru_del(struct dentry *dentry)
        D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
        dentry->d_flags &= ~DCACHE_LRU_LIST;
        this_cpu_dec(nr_dentry_unused);
+       if (d_is_negative(dentry))
+               this_cpu_dec(nr_dentry_negative);
        WARN_ON_ONCE(!list_lru_del(&dentry->d_sb->s_dentry_lru, &dentry->d_lru));
 }
 
@@ -418,6 +441,8 @@ static void d_lru_isolate(struct list_lru_one *lru, struct dentry *dentry)
        D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
        dentry->d_flags &= ~DCACHE_LRU_LIST;
        this_cpu_dec(nr_dentry_unused);
+       if (d_is_negative(dentry))
+               this_cpu_dec(nr_dentry_negative);
        list_lru_isolate(lru, &dentry->d_lru);
 }
 
@@ -426,6 +451,8 @@ static void d_lru_shrink_move(struct list_lru_one *lru, struct dentry *dentry,
 {
        D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
        dentry->d_flags |= DCACHE_SHRINK_LIST;
+       if (d_is_negative(dentry))
+               this_cpu_dec(nr_dentry_negative);
        list_lru_isolate_move(lru, &dentry->d_lru, list);
 }
 
@@ -1188,15 +1215,11 @@ static enum lru_status dentry_lru_isolate_shrink(struct list_head *item,
  */
 void shrink_dcache_sb(struct super_block *sb)
 {
-       long freed;
-
        do {
                LIST_HEAD(dispose);
 
-               freed = list_lru_walk(&sb->s_dentry_lru,
+               list_lru_walk(&sb->s_dentry_lru,
                        dentry_lru_isolate_shrink, &dispose, 1024);
-
-               this_cpu_sub(nr_dentry_unused, freed);
                shrink_dentry_list(&dispose);
        } while (list_lru_count(&sb->s_dentry_lru) > 0);
 }
@@ -1820,6 +1843,11 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
        WARN_ON(d_in_lookup(dentry));
 
        spin_lock(&dentry->d_lock);
+       /*
+        * Decrement negative dentry count if it was in the LRU list.
+        */
+       if (dentry->d_flags & DCACHE_LRU_LIST)
+               this_cpu_dec(nr_dentry_negative);
        hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
        raw_write_seqcount_begin(&dentry->d_seq);
        __d_set_inode_and_type(dentry, inode, add_flags);
index 13b0135..29c68c5 100644 (file)
@@ -324,7 +324,7 @@ static struct dentry *failed_creating(struct dentry *dentry)
        inode_unlock(d_inode(dentry->d_parent));
        dput(dentry);
        simple_release_fs(&debugfs_mount, &debugfs_mount_count);
-       return NULL;
+       return ERR_PTR(-ENOMEM);
 }
 
 static struct dentry *end_creating(struct dentry *dentry)
@@ -347,7 +347,7 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode,
        dentry = start_creating(name, parent);
 
        if (IS_ERR(dentry))
-               return NULL;
+               return dentry;
 
        inode = debugfs_get_inode(dentry->d_sb);
        if (unlikely(!inode))
@@ -386,7 +386,8 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode,
  * This function will return a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the debugfs_remove() function when the file is
  * to be removed (no automatic cleanup happens if your module is unloaded,
- * you are responsible here.)  If an error occurs, %NULL will be returned.
+ * you are responsible here.)  If an error occurs, %ERR_PTR(-ERROR) will be
+ * returned.
  *
  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
  * returned.
@@ -464,7 +465,8 @@ EXPORT_SYMBOL_GPL(debugfs_create_file_unsafe);
  * This function will return a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the debugfs_remove() function when the file is
  * to be removed (no automatic cleanup happens if your module is unloaded,
- * you are responsible here.)  If an error occurs, %NULL will be returned.
+ * you are responsible here.)  If an error occurs, %ERR_PTR(-ERROR) will be
+ * returned.
  *
  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
  * returned.
@@ -495,7 +497,8 @@ EXPORT_SYMBOL_GPL(debugfs_create_file_size);
  * This function will return a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the debugfs_remove() function when the file is
  * to be removed (no automatic cleanup happens if your module is unloaded,
- * you are responsible here.)  If an error occurs, %NULL will be returned.
+ * you are responsible here.)  If an error occurs, %ERR_PTR(-ERROR) will be
+ * returned.
  *
  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
  * returned.
@@ -506,7 +509,7 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
        struct inode *inode;
 
        if (IS_ERR(dentry))
-               return NULL;
+               return dentry;
 
        inode = debugfs_get_inode(dentry->d_sb);
        if (unlikely(!inode))
@@ -545,7 +548,7 @@ struct dentry *debugfs_create_automount(const char *name,
        struct inode *inode;
 
        if (IS_ERR(dentry))
-               return NULL;
+               return dentry;
 
        inode = debugfs_get_inode(dentry->d_sb);
        if (unlikely(!inode))
@@ -581,8 +584,8 @@ EXPORT_SYMBOL(debugfs_create_automount);
  * This function will return a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the debugfs_remove() function when the symbolic
  * link is to be removed (no automatic cleanup happens if your module is
- * unloaded, you are responsible here.)  If an error occurs, %NULL will be
- * returned.
+ * unloaded, you are responsible here.)  If an error occurs, %ERR_PTR(-ERROR)
+ * will be returned.
  *
  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
  * returned.
@@ -594,12 +597,12 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
        struct inode *inode;
        char *link = kstrdup(target, GFP_KERNEL);
        if (!link)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        dentry = start_creating(name, parent);
        if (IS_ERR(dentry)) {
                kfree(link);
-               return NULL;
+               return dentry;
        }
 
        inode = debugfs_get_inode(dentry->d_sb);
@@ -787,6 +790,13 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
        struct dentry *dentry = NULL, *trap;
        struct name_snapshot old_name;
 
+       if (IS_ERR(old_dir))
+               return old_dir;
+       if (IS_ERR(new_dir))
+               return new_dir;
+       if (IS_ERR_OR_NULL(old_dentry))
+               return old_dentry;
+
        trap = lock_rename(new_dir, old_dir);
        /* Source or destination directories don't exist? */
        if (d_really_is_negative(old_dir) || d_really_is_negative(new_dir))
@@ -820,7 +830,9 @@ exit:
        if (dentry && !IS_ERR(dentry))
                dput(dentry);
        unlock_rename(new_dir, old_dir);
-       return NULL;
+       if (IS_ERR(dentry))
+               return dentry;
+       return ERR_PTR(-EINVAL);
 }
 EXPORT_SYMBOL_GPL(debugfs_rename);
 
index dbc1a1f..ec2fb6f 100644 (file)
@@ -679,6 +679,7 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio,
        unsigned long fs_count; /* Number of filesystem-sized blocks */
        int create;
        unsigned int i_blkbits = sdio->blkbits + sdio->blkfactor;
+       loff_t i_size;
 
        /*
         * If there was a memory error and we've overwritten all the
@@ -708,8 +709,8 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio,
                 */
                create = dio->op == REQ_OP_WRITE;
                if (dio->flags & DIO_SKIP_HOLES) {
-                       if (fs_startblk <= ((i_size_read(dio->inode) - 1) >>
-                                                       i_blkbits))
+                       i_size = i_size_read(dio->inode);
+                       if (i_size && fs_startblk <= (i_size - 1) >> i_blkbits)
                                create = 0;
                }
 
index 8237701..d31b6c7 100644 (file)
@@ -21,8 +21,13 @@ static void drop_pagecache_sb(struct super_block *sb, void *unused)
        spin_lock(&sb->s_inode_list_lock);
        list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
                spin_lock(&inode->i_lock);
+               /*
+                * We must skip inodes in unusual state. We may also skip
+                * inodes without pages but we deliberately won't in case
+                * we need to reschedule to avoid softlockups.
+                */
                if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) ||
-                   (inode->i_mapping->nrpages == 0)) {
+                   (inode->i_mapping->nrpages == 0 && !need_resched())) {
                        spin_unlock(&inode->i_lock);
                        continue;
                }
@@ -30,6 +35,7 @@ static void drop_pagecache_sb(struct super_block *sb, void *unused)
                spin_unlock(&inode->i_lock);
                spin_unlock(&sb->s_inode_list_lock);
 
+               cond_resched();
                invalidate_mapping_pages(inode->i_mapping, 0, -1);
                iput(toput_inode);
                toput_inode = inode;
index 712f009..5508baa 100644 (file)
@@ -116,16 +116,8 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
                goto out;
        }
 
-       ret = file_write_and_wait_range(file, start, end);
-       if (ret)
-               return ret;
-
        if (!journal) {
-               struct writeback_control wbc = {
-                       .sync_mode = WB_SYNC_ALL
-               };
-
-               ret = ext4_write_inode(inode, &wbc);
+               ret = __generic_file_fsync(file, start, end, datasync);
                if (!ret)
                        ret = ext4_sync_parent(inode);
                if (test_opt(inode->i_sb, BARRIER))
@@ -133,6 +125,9 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
                goto out;
        }
 
+       ret = file_write_and_wait_range(file, start, end);
+       if (ret)
+               return ret;
        /*
         * data=writeback,ordered:
         *  The caller's filemap_fdatawrite()/wait will sync the data.
index b40168f..36855c1 100644 (file)
@@ -331,11 +331,22 @@ struct inode_switch_wbs_context {
        struct work_struct      work;
 };
 
+static void bdi_down_write_wb_switch_rwsem(struct backing_dev_info *bdi)
+{
+       down_write(&bdi->wb_switch_rwsem);
+}
+
+static void bdi_up_write_wb_switch_rwsem(struct backing_dev_info *bdi)
+{
+       up_write(&bdi->wb_switch_rwsem);
+}
+
 static void inode_switch_wbs_work_fn(struct work_struct *work)
 {
        struct inode_switch_wbs_context *isw =
                container_of(work, struct inode_switch_wbs_context, work);
        struct inode *inode = isw->inode;
+       struct backing_dev_info *bdi = inode_to_bdi(inode);
        struct address_space *mapping = inode->i_mapping;
        struct bdi_writeback *old_wb = inode->i_wb;
        struct bdi_writeback *new_wb = isw->new_wb;
@@ -344,6 +355,12 @@ static void inode_switch_wbs_work_fn(struct work_struct *work)
        bool switched = false;
 
        /*
+        * If @inode switches cgwb membership while sync_inodes_sb() is
+        * being issued, sync_inodes_sb() might miss it.  Synchronize.
+        */
+       down_read(&bdi->wb_switch_rwsem);
+
+       /*
         * By the time control reaches here, RCU grace period has passed
         * since I_WB_SWITCH assertion and all wb stat update transactions
         * between unlocked_inode_to_wb_begin/end() are guaranteed to be
@@ -428,6 +445,8 @@ skip_switch:
        spin_unlock(&new_wb->list_lock);
        spin_unlock(&old_wb->list_lock);
 
+       up_read(&bdi->wb_switch_rwsem);
+
        if (switched) {
                wb_wakeup(new_wb);
                wb_put(old_wb);
@@ -468,9 +487,18 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
        if (inode->i_state & I_WB_SWITCH)
                return;
 
+       /*
+        * Avoid starting new switches while sync_inodes_sb() is in
+        * progress.  Otherwise, if the down_write protected issue path
+        * blocks heavily, we might end up starting a large number of
+        * switches which will block on the rwsem.
+        */
+       if (!down_read_trylock(&bdi->wb_switch_rwsem))
+               return;
+
        isw = kzalloc(sizeof(*isw), GFP_ATOMIC);
        if (!isw)
-               return;
+               goto out_unlock;
 
        /* find and pin the new wb */
        rcu_read_lock();
@@ -504,12 +532,14 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
         * Let's continue after I_WB_SWITCH is guaranteed to be visible.
         */
        call_rcu(&isw->rcu_head, inode_switch_wbs_rcu_fn);
-       return;
+       goto out_unlock;
 
 out_free:
        if (isw->new_wb)
                wb_put(isw->new_wb);
        kfree(isw);
+out_unlock:
+       up_read(&bdi->wb_switch_rwsem);
 }
 
 /**
@@ -887,6 +917,9 @@ fs_initcall(cgroup_writeback_init);
 
 #else  /* CONFIG_CGROUP_WRITEBACK */
 
+static void bdi_down_write_wb_switch_rwsem(struct backing_dev_info *bdi) { }
+static void bdi_up_write_wb_switch_rwsem(struct backing_dev_info *bdi) { }
+
 static struct bdi_writeback *
 locked_inode_to_wb_and_lock_list(struct inode *inode)
        __releases(&inode->i_lock)
@@ -2413,8 +2446,11 @@ void sync_inodes_sb(struct super_block *sb)
                return;
        WARN_ON(!rwsem_is_locked(&sb->s_umount));
 
+       /* protect against inode wb switch, see inode_switch_wbs_work_fn() */
+       bdi_down_write_wb_switch_rwsem(bdi);
        bdi_split_work_to_wbs(bdi, &work, false);
        wb_wait_for_completion(bdi, &done);
+       bdi_up_write_wb_switch_rwsem(bdi);
 
        wait_sb_inodes(sb);
 }
index a5e516a..809c0f2 100644 (file)
@@ -1742,7 +1742,6 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
        req->in.h.nodeid = outarg->nodeid;
        req->in.numargs = 2;
        req->in.argpages = 1;
-       req->page_descs[0].offset = offset;
        req->end = fuse_retrieve_end;
 
        index = outarg->offset >> PAGE_SHIFT;
@@ -1757,6 +1756,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
 
                this_num = min_t(unsigned, num, PAGE_SIZE - offset);
                req->pages[req->num_pages] = page;
+               req->page_descs[req->num_pages].offset = offset;
                req->page_descs[req->num_pages].length = this_num;
                req->num_pages++;
 
@@ -2077,8 +2077,10 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
 
        ret = fuse_dev_do_write(fud, &cs, len);
 
+       pipe_lock(pipe);
        for (idx = 0; idx < nbuf; idx++)
                pipe_buf_release(pipe, &bufs[idx]);
+       pipe_unlock(pipe);
 
 out:
        kvfree(bufs);
index ffaffe1..a59c16b 100644 (file)
@@ -1782,7 +1782,7 @@ static bool fuse_writepage_in_flight(struct fuse_req *new_req,
                spin_unlock(&fc->lock);
 
                dec_wb_stat(&bdi->wb, WB_WRITEBACK);
-               dec_node_page_state(page, NR_WRITEBACK_TEMP);
+               dec_node_page_state(new_req->pages[0], NR_WRITEBACK_TEMP);
                wb_writeout_inc(&bdi->wb);
                fuse_writepage_free(fc, new_req);
                fuse_request_free(new_req);
index 76baaa6..c2d4099 100644 (file)
@@ -628,6 +628,7 @@ void fuse_conn_init(struct fuse_conn *fc, struct user_namespace *user_ns)
        get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key));
        fc->pid_ns = get_pid_ns(task_active_pid_ns(current));
        fc->user_ns = get_user_ns(user_ns);
+       fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ;
 }
 EXPORT_SYMBOL_GPL(fuse_conn_init);
 
@@ -1162,7 +1163,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
        fc->user_id = d.user_id;
        fc->group_id = d.group_id;
        fc->max_read = max_t(unsigned, 4096, d.max_read);
-       fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ;
 
        /* Used by get_root_inode() */
        sb->s_fs_info = fc;
index f15b4c5..78510ab 100644 (file)
@@ -28,7 +28,6 @@
 #include "util.h"
 #include "trans.h"
 #include "dir.h"
-#include "lops.h"
 
 struct workqueue_struct *gfs2_freeze_wq;
 
index 5bfaf38..b8830fd 100644 (file)
@@ -733,7 +733,7 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
        lh->lh_crc = cpu_to_be32(crc);
 
        gfs2_log_write(sdp, page, sb->s_blocksize, 0, addr);
-       gfs2_log_submit_bio(&sdp->sd_log_bio, REQ_OP_WRITE | op_flags);
+       gfs2_log_submit_bio(&sdp->sd_log_bio, REQ_OP_WRITE, op_flags);
        log_flush_wait(sdp);
 }
 
@@ -810,7 +810,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
 
        gfs2_ordered_write(sdp);
        lops_before_commit(sdp, tr);
-       gfs2_log_submit_bio(&sdp->sd_log_bio, REQ_OP_WRITE);
+       gfs2_log_submit_bio(&sdp->sd_log_bio, REQ_OP_WRITE, 0);
 
        if (sdp->sd_log_head != sdp->sd_log_flush_head) {
                log_flush_wait(sdp);
index 94dcab6..2295042 100644 (file)
@@ -17,9 +17,7 @@
 #include <linux/bio.h>
 #include <linux/fs.h>
 #include <linux/list_sort.h>
-#include <linux/blkdev.h>
 
-#include "bmap.h"
 #include "dir.h"
 #include "gfs2.h"
 #include "incore.h"
@@ -195,6 +193,7 @@ static void gfs2_end_log_write_bh(struct gfs2_sbd *sdp, struct bio_vec *bvec,
 /**
  * gfs2_end_log_write - end of i/o to the log
  * @bio: The bio
+ * @error: Status of i/o request
  *
  * Each bio_vec contains either data from the pagecache or data
  * relating to the log itself. Here we iterate over the bio_vec
@@ -231,19 +230,20 @@ static void gfs2_end_log_write(struct bio *bio)
 /**
  * gfs2_log_submit_bio - Submit any pending log bio
  * @biop: Address of the bio pointer
- * @opf: REQ_OP | op_flags
+ * @op: REQ_OP
+ * @op_flags: req_flag_bits
  *
  * Submit any pending part-built or full bio to the block device. If
  * there is no pending bio, then this is a no-op.
  */
 
-void gfs2_log_submit_bio(struct bio **biop, int opf)
+void gfs2_log_submit_bio(struct bio **biop, int op, int op_flags)
 {
        struct bio *bio = *biop;
        if (bio) {
                struct gfs2_sbd *sdp = bio->bi_private;
                atomic_inc(&sdp->sd_log_in_flight);
-               bio->bi_opf = opf;
+               bio_set_op_attrs(bio, op, op_flags);
                submit_bio(bio);
                *biop = NULL;
        }
@@ -304,7 +304,7 @@ static struct bio *gfs2_log_get_bio(struct gfs2_sbd *sdp, u64 blkno,
                nblk >>= sdp->sd_fsb2bb_shift;
                if (blkno == nblk && !flush)
                        return bio;
-               gfs2_log_submit_bio(biop, op);
+               gfs2_log_submit_bio(biop, op, 0);
        }
 
        *biop = gfs2_log_alloc_bio(sdp, blkno, end_io);
@@ -375,184 +375,6 @@ void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page)
                       gfs2_log_bmap(sdp));
 }
 
-/**
- * gfs2_end_log_read - end I/O callback for reads from the log
- * @bio: The bio
- *
- * Simply unlock the pages in the bio. The main thread will wait on them and
- * process them in order as necessary.
- */
-
-static void gfs2_end_log_read(struct bio *bio)
-{
-       struct page *page;
-       struct bio_vec *bvec;
-       int i;
-
-       bio_for_each_segment_all(bvec, bio, i) {
-               page = bvec->bv_page;
-               if (bio->bi_status) {
-                       int err = blk_status_to_errno(bio->bi_status);
-
-                       SetPageError(page);
-                       mapping_set_error(page->mapping, err);
-               }
-               unlock_page(page);
-       }
-
-       bio_put(bio);
-}
-
-/**
- * gfs2_jhead_pg_srch - Look for the journal head in a given page.
- * @jd: The journal descriptor
- * @page: The page to look in
- *
- * Returns: 1 if found, 0 otherwise.
- */
-
-static bool gfs2_jhead_pg_srch(struct gfs2_jdesc *jd,
-                             struct gfs2_log_header_host *head,
-                             struct page *page)
-{
-       struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
-       struct gfs2_log_header_host uninitialized_var(lh);
-       void *kaddr = kmap_atomic(page);
-       unsigned int offset;
-       bool ret = false;
-
-       for (offset = 0; offset < PAGE_SIZE; offset += sdp->sd_sb.sb_bsize) {
-               if (!__get_log_header(sdp, kaddr + offset, 0, &lh)) {
-                       if (lh.lh_sequence > head->lh_sequence)
-                               *head = lh;
-                       else {
-                               ret = true;
-                               break;
-                       }
-               }
-       }
-       kunmap_atomic(kaddr);
-       return ret;
-}
-
-/**
- * gfs2_jhead_process_page - Search/cleanup a page
- * @jd: The journal descriptor
- * @index: Index of the page to look into
- * @done: If set, perform only cleanup, else search and set if found.
- *
- * Find the page with 'index' in the journal's mapping. Search the page for
- * the journal head if requested (cleanup == false). Release refs on the
- * page so the page cache can reclaim it (put_page() twice). We grabbed a
- * reference on this page two times, first when we did a find_or_create_page()
- * to obtain the page to add it to the bio and second when we do a
- * find_get_page() here to get the page to wait on while I/O on it is being
- * completed.
- * This function is also used to free up a page we might've grabbed but not
- * used. Maybe we added it to a bio, but not submitted it for I/O. Or we
- * submitted the I/O, but we already found the jhead so we only need to drop
- * our references to the page.
- */
-
-static void gfs2_jhead_process_page(struct gfs2_jdesc *jd, unsigned long index,
-                                   struct gfs2_log_header_host *head,
-                                   bool *done)
-{
-       struct page *page;
-
-       page = find_get_page(jd->jd_inode->i_mapping, index);
-       wait_on_page_locked(page);
-
-       if (PageError(page))
-               *done = true;
-
-       if (!*done)
-               *done = gfs2_jhead_pg_srch(jd, head, page);
-
-       put_page(page); /* Once for find_get_page */
-       put_page(page); /* Once more for find_or_create_page */
-}
-
-/**
- * gfs2_find_jhead - find the head of a log
- * @jd: The journal descriptor
- * @head: The log descriptor for the head of the log is returned here
- *
- * Do a search of a journal by reading it in large chunks using bios and find
- * the valid log entry with the highest sequence number.  (i.e. the log head)
- *
- * Returns: 0 on success, errno otherwise
- */
-
-int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
-{
-       struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
-       struct address_space *mapping = jd->jd_inode->i_mapping;
-       struct gfs2_journal_extent *je;
-       u32 block, read_idx = 0, submit_idx = 0, index = 0;
-       int shift = PAGE_SHIFT - sdp->sd_sb.sb_bsize_shift;
-       int blocks_per_page = 1 << shift, sz, ret = 0;
-       struct bio *bio = NULL;
-       struct page *page;
-       bool done = false;
-       errseq_t since;
-
-       memset(head, 0, sizeof(*head));
-       if (list_empty(&jd->extent_list))
-               gfs2_map_journal_extents(sdp, jd);
-
-       since = filemap_sample_wb_err(mapping);
-       list_for_each_entry(je, &jd->extent_list, list) {
-               for (block = 0; block < je->blocks; block += blocks_per_page) {
-                       index = (je->lblock + block) >> shift;
-
-                       page = find_or_create_page(mapping, index, GFP_NOFS);
-                       if (!page) {
-                               ret = -ENOMEM;
-                               done = true;
-                               goto out;
-                       }
-
-                       if (bio) {
-                               sz = bio_add_page(bio, page, PAGE_SIZE, 0);
-                               if (sz == PAGE_SIZE)
-                                       goto page_added;
-                               submit_idx = index;
-                               submit_bio(bio);
-                               bio = NULL;
-                       }
-
-                       bio = gfs2_log_alloc_bio(sdp,
-                                                je->dblock + (index << shift),
-                                                gfs2_end_log_read);
-                       bio->bi_opf = REQ_OP_READ;
-                       sz = bio_add_page(bio, page, PAGE_SIZE, 0);
-                       gfs2_assert_warn(sdp, sz == PAGE_SIZE);
-
-page_added:
-                       if (submit_idx <= read_idx + BIO_MAX_PAGES) {
-                               /* Keep at least one bio in flight */
-                               continue;
-                       }
-
-                       gfs2_jhead_process_page(jd, read_idx++, head, &done);
-                       if (done)
-                               goto out;  /* found */
-               }
-       }
-
-out:
-       if (bio)
-               submit_bio(bio);
-       while (read_idx <= index)
-               gfs2_jhead_process_page(jd, read_idx++, head, &done);
-
-       if (!ret)
-               ret = filemap_check_wb_err(mapping, since);
-
-       return ret;
-}
-
 static struct page *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type,
                                      u32 ld_length, u32 ld_data1)
 {
index 331160f..711c4d8 100644 (file)
@@ -30,10 +30,8 @@ extern u64 gfs2_log_bmap(struct gfs2_sbd *sdp);
 extern void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
                           unsigned size, unsigned offset, u64 blkno);
 extern void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page);
-extern void gfs2_log_submit_bio(struct bio **biop, int opf);
+extern void gfs2_log_submit_bio(struct bio **biop, int op, int op_flags);
 extern void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh);
-extern int gfs2_find_jhead(struct gfs2_jdesc *jd,
-                          struct gfs2_log_header_host *head);
 
 static inline unsigned int buf_limit(struct gfs2_sbd *sdp)
 {
index 1179763..b041cb8 100644 (file)
@@ -41,7 +41,6 @@
 #include "dir.h"
 #include "meta_io.h"
 #include "trace_gfs2.h"
-#include "lops.h"
 
 #define DO 0
 #define UNDO 1
index 7389e44..2dac430 100644 (file)
@@ -182,6 +182,129 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
 }
 
 /**
+ * find_good_lh - find a good log header
+ * @jd: the journal
+ * @blk: the segment to start searching from
+ * @lh: the log header to fill in
+ * @forward: if true search forward in the log, else search backward
+ *
+ * Call get_log_header() to get a log header for a segment, but if the
+ * segment is bad, either scan forward or backward until we find a good one.
+ *
+ * Returns: errno
+ */
+
+static int find_good_lh(struct gfs2_jdesc *jd, unsigned int *blk,
+                       struct gfs2_log_header_host *head)
+{
+       unsigned int orig_blk = *blk;
+       int error;
+
+       for (;;) {
+               error = get_log_header(jd, *blk, head);
+               if (error <= 0)
+                       return error;
+
+               if (++*blk == jd->jd_blocks)
+                       *blk = 0;
+
+               if (*blk == orig_blk) {
+                       gfs2_consist_inode(GFS2_I(jd->jd_inode));
+                       return -EIO;
+               }
+       }
+}
+
+/**
+ * jhead_scan - make sure we've found the head of the log
+ * @jd: the journal
+ * @head: this is filled in with the log descriptor of the head
+ *
+ * At this point, seg and lh should be either the head of the log or just
+ * before.  Scan forward until we find the head.
+ *
+ * Returns: errno
+ */
+
+static int jhead_scan(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
+{
+       unsigned int blk = head->lh_blkno;
+       struct gfs2_log_header_host lh;
+       int error;
+
+       for (;;) {
+               if (++blk == jd->jd_blocks)
+                       blk = 0;
+
+               error = get_log_header(jd, blk, &lh);
+               if (error < 0)
+                       return error;
+               if (error == 1)
+                       continue;
+
+               if (lh.lh_sequence == head->lh_sequence) {
+                       gfs2_consist_inode(GFS2_I(jd->jd_inode));
+                       return -EIO;
+               }
+               if (lh.lh_sequence < head->lh_sequence)
+                       break;
+
+               *head = lh;
+       }
+
+       return 0;
+}
+
+/**
+ * gfs2_find_jhead - find the head of a log
+ * @jd: the journal
+ * @head: the log descriptor for the head of the log is returned here
+ *
+ * Do a binary search of a journal and find the valid log entry with the
+ * highest sequence number.  (i.e. the log head)
+ *
+ * Returns: errno
+ */
+
+int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
+{
+       struct gfs2_log_header_host lh_1, lh_m;
+       u32 blk_1, blk_2, blk_m;
+       int error;
+
+       blk_1 = 0;
+       blk_2 = jd->jd_blocks - 1;
+
+       for (;;) {
+               blk_m = (blk_1 + blk_2) / 2;
+
+               error = find_good_lh(jd, &blk_1, &lh_1);
+               if (error)
+                       return error;
+
+               error = find_good_lh(jd, &blk_m, &lh_m);
+               if (error)
+                       return error;
+
+               if (blk_1 == blk_m || blk_m == blk_2)
+                       break;
+
+               if (lh_1.lh_sequence <= lh_m.lh_sequence)
+                       blk_1 = blk_m;
+               else
+                       blk_2 = blk_m;
+       }
+
+       error = jhead_scan(jd, &lh_1);
+       if (error)
+               return error;
+
+       *head = lh_1;
+
+       return error;
+}
+
+/**
  * foreach_descriptor - go through the active part of the log
  * @jd: the journal
  * @start: the first log header in the active region
index 99575ab..11d8124 100644 (file)
@@ -27,6 +27,8 @@ extern int gfs2_revoke_add(struct gfs2_jdesc *jd, u64 blkno, unsigned int where)
 extern int gfs2_revoke_check(struct gfs2_jdesc *jd, u64 blkno, unsigned int where);
 extern void gfs2_revoke_clean(struct gfs2_jdesc *jd);
 
+extern int gfs2_find_jhead(struct gfs2_jdesc *jd,
+                   struct gfs2_log_header_host *head);
 extern int gfs2_recover_journal(struct gfs2_jdesc *gfs2_jd, bool wait);
 extern void gfs2_recover_func(struct work_struct *work);
 extern int __get_log_header(struct gfs2_sbd *sdp,
index 831d7cb..17a8d3b 100644 (file)
@@ -1780,9 +1780,9 @@ static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext,
                        goto next_iter;
                }
                if (ret == -E2BIG) {
-                       n += rbm->bii - initial_bii;
                        rbm->bii = 0;
                        rbm->offset = 0;
+                       n += (rbm->bii - initial_bii);
                        goto res_covered_end_of_rgrp;
                }
                return ret;
index d4b11c9..ca71163 100644 (file)
@@ -45,7 +45,6 @@
 #include "util.h"
 #include "sys.h"
 #include "xattr.h"
-#include "lops.h"
 
 #define args_neq(a1, a2, x) ((a1)->ar_##x != (a2)->ar_##x)
 
index a2fcea5..32920a1 100644 (file)
@@ -383,16 +383,17 @@ hugetlb_vmdelete_list(struct rb_root_cached *root, pgoff_t start, pgoff_t end)
  * truncation is indicated by end of range being LLONG_MAX
  *     In this case, we first scan the range and release found pages.
  *     After releasing pages, hugetlb_unreserve_pages cleans up region/reserv
- *     maps and global counts.
+ *     maps and global counts.  Page faults can not race with truncation
+ *     in this routine.  hugetlb_no_page() prevents page faults in the
+ *     truncated range.  It checks i_size before allocation, and again after
+ *     with the page table lock for the page held.  The same lock must be
+ *     acquired to unmap a page.
  * hole punch is indicated if end is not LLONG_MAX
  *     In the hole punch case we scan the range and release found pages.
  *     Only when releasing a page is the associated region/reserv map
  *     deleted.  The region/reserv map for ranges without associated
- *     pages are not modified.
- *
- * Callers of this routine must hold the i_mmap_rwsem in write mode to prevent
- * races with page faults.
- *
+ *     pages are not modified.  Page faults can race with hole punch.
+ *     This is indicated if we find a mapped page.
  * Note: If the passed end of range value is beyond the end of file, but
  * not LLONG_MAX this routine still performs a hole punch operation.
  */
@@ -422,14 +423,32 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
 
                for (i = 0; i < pagevec_count(&pvec); ++i) {
                        struct page *page = pvec.pages[i];
+                       u32 hash;
 
                        index = page->index;
+                       hash = hugetlb_fault_mutex_hash(h, current->mm,
+                                                       &pseudo_vma,
+                                                       mapping, index, 0);
+                       mutex_lock(&hugetlb_fault_mutex_table[hash]);
+
                        /*
-                        * A mapped page is impossible as callers should unmap
-                        * all references before calling.  And, i_mmap_rwsem
-                        * prevents the creation of additional mappings.
+                        * If page is mapped, it was faulted in after being
+                        * unmapped in caller.  Unmap (again) now after taking
+                        * the fault mutex.  The mutex will prevent faults
+                        * until we finish removing the page.
+                        *
+                        * This race can only happen in the hole punch case.
+                        * Getting here in a truncate operation is a bug.
                         */
-                       VM_BUG_ON(page_mapped(page));
+                       if (unlikely(page_mapped(page))) {
+                               BUG_ON(truncate_op);
+
+                               i_mmap_lock_write(mapping);
+                               hugetlb_vmdelete_list(&mapping->i_mmap,
+                                       index * pages_per_huge_page(h),
+                                       (index + 1) * pages_per_huge_page(h));
+                               i_mmap_unlock_write(mapping);
+                       }
 
                        lock_page(page);
                        /*
@@ -451,6 +470,7 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
                        }
 
                        unlock_page(page);
+                       mutex_unlock(&hugetlb_fault_mutex_table[hash]);
                }
                huge_pagevec_release(&pvec);
                cond_resched();
@@ -462,20 +482,9 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
 
 static void hugetlbfs_evict_inode(struct inode *inode)
 {
-       struct address_space *mapping = inode->i_mapping;
        struct resv_map *resv_map;
 
-       /*
-        * The vfs layer guarantees that there are no other users of this
-        * inode.  Therefore, it would be safe to call remove_inode_hugepages
-        * without holding i_mmap_rwsem.  We acquire and hold here to be
-        * consistent with other callers.  Since there will be no contention
-        * on the semaphore, overhead is negligible.
-        */
-       i_mmap_lock_write(mapping);
        remove_inode_hugepages(inode, 0, LLONG_MAX);
-       i_mmap_unlock_write(mapping);
-
        resv_map = (struct resv_map *)inode->i_mapping->private_data;
        /* root inode doesn't have the resv_map, so we should check it */
        if (resv_map)
@@ -496,8 +505,8 @@ static int hugetlb_vmtruncate(struct inode *inode, loff_t offset)
        i_mmap_lock_write(mapping);
        if (!RB_EMPTY_ROOT(&mapping->i_mmap.rb_root))
                hugetlb_vmdelete_list(&mapping->i_mmap, pgoff, 0);
-       remove_inode_hugepages(inode, offset, LLONG_MAX);
        i_mmap_unlock_write(mapping);
+       remove_inode_hugepages(inode, offset, LLONG_MAX);
        return 0;
 }
 
@@ -531,8 +540,8 @@ static long hugetlbfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
                        hugetlb_vmdelete_list(&mapping->i_mmap,
                                                hole_start >> PAGE_SHIFT,
                                                hole_end  >> PAGE_SHIFT);
-               remove_inode_hugepages(inode, hole_start, hole_end);
                i_mmap_unlock_write(mapping);
+               remove_inode_hugepages(inode, hole_start, hole_end);
                inode_unlock(inode);
        }
 
@@ -615,11 +624,7 @@ static long hugetlbfs_fallocate(struct file *file, int mode, loff_t offset,
                /* addr is the offset within the file (zero based) */
                addr = index * hpage_size;
 
-               /*
-                * fault mutex taken here, protects against fault path
-                * and hole punch.  inode_lock previously taken protects
-                * against truncation.
-                */
+               /* mutex taken here, fault path and hole punch */
                hash = hugetlb_fault_mutex_hash(h, mm, &pseudo_vma, mapping,
                                                index, addr);
                mutex_lock(&hugetlb_fault_mutex_table[hash]);
index 0cd47fe..73432e6 100644 (file)
@@ -730,11 +730,8 @@ static enum lru_status inode_lru_isolate(struct list_head *item,
                return LRU_REMOVED;
        }
 
-       /*
-        * Recently referenced inodes and inodes with many attached pages
-        * get one more pass.
-        */
-       if (inode->i_state & I_REFERENCED || inode->i_data.nrpages > 1) {
+       /* recently referenced inodes get one more pass */
+       if (inode->i_state & I_REFERENCED) {
                inode->i_state &= ~I_REFERENCED;
                spin_unlock(&inode->i_lock);
                return LRU_ROTATE;
index a3088fa..897c602 100644 (file)
@@ -116,6 +116,12 @@ iomap_page_create(struct inode *inode, struct page *page)
        atomic_set(&iop->read_count, 0);
        atomic_set(&iop->write_count, 0);
        bitmap_zero(iop->uptodate, PAGE_SIZE / SECTOR_SIZE);
+
+       /*
+        * migrate_page_move_mapping() assumes that pages with private data have
+        * their count elevated by 1.
+        */
+       get_page(page);
        set_page_private(page, (unsigned long)iop);
        SetPagePrivate(page);
        return iop;
@@ -132,6 +138,7 @@ iomap_page_release(struct page *page)
        WARN_ON_ONCE(atomic_read(&iop->write_count));
        ClearPagePrivate(page);
        set_page_private(page, 0);
+       put_page(page);
        kfree(iop);
 }
 
@@ -569,8 +576,10 @@ iomap_migrate_page(struct address_space *mapping, struct page *newpage,
 
        if (page_has_private(page)) {
                ClearPagePrivate(page);
+               get_page(newpage);
                set_page_private(newpage, page_private(page));
                set_page_private(page, 0);
+               put_page(page);
                SetPagePrivate(newpage);
        }
 
@@ -1804,6 +1813,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
        loff_t pos = iocb->ki_pos, start = pos;
        loff_t end = iocb->ki_pos + count - 1, ret = 0;
        unsigned int flags = IOMAP_DIRECT;
+       bool wait_for_completion = is_sync_kiocb(iocb);
        struct blk_plug plug;
        struct iomap_dio *dio;
 
@@ -1823,7 +1833,6 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
        dio->end_io = end_io;
        dio->error = 0;
        dio->flags = 0;
-       dio->wait_for_completion = is_sync_kiocb(iocb);
 
        dio->submit.iter = iter;
        dio->submit.waiter = current;
@@ -1878,7 +1887,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
                dio_warn_stale_pagecache(iocb->ki_filp);
        ret = 0;
 
-       if (iov_iter_rw(iter) == WRITE && !dio->wait_for_completion &&
+       if (iov_iter_rw(iter) == WRITE && !wait_for_completion &&
            !inode->i_sb->s_dio_done_wq) {
                ret = sb_init_dio_done_wq(inode->i_sb);
                if (ret < 0)
@@ -1894,7 +1903,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
                if (ret <= 0) {
                        /* magic error code to fall back to buffered I/O */
                        if (ret == -ENOTBLK) {
-                               dio->wait_for_completion = true;
+                               wait_for_completion = true;
                                ret = 0;
                        }
                        break;
@@ -1916,8 +1925,24 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
        if (dio->flags & IOMAP_DIO_WRITE_FUA)
                dio->flags &= ~IOMAP_DIO_NEED_SYNC;
 
+       /*
+        * We are about to drop our additional submission reference, which
+        * might be the last reference to the dio.  There are three three
+        * different ways we can progress here:
+        *
+        *  (a) If this is the last reference we will always complete and free
+        *      the dio ourselves.
+        *  (b) If this is not the last reference, and we serve an asynchronous
+        *      iocb, we must never touch the dio after the decrement, the
+        *      I/O completion handler will complete and free it.
+        *  (c) If this is not the last reference, but we serve a synchronous
+        *      iocb, the I/O completion handler will wake us up on the drop
+        *      of the final reference, and we will complete and free it here
+        *      after we got woken by the I/O completion handler.
+        */
+       dio->wait_for_completion = wait_for_completion;
        if (!atomic_dec_and_test(&dio->ref)) {
-               if (!dio->wait_for_completion)
+               if (!wait_for_completion)
                        return -EIOCBQUEUED;
 
                for (;;) {
@@ -1934,9 +1959,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
                __set_current_state(TASK_RUNNING);
        }
 
-       ret = iomap_dio_complete(dio);
-
-       return ret;
+       return iomap_dio_complete(dio);
 
 out_free_dio:
        kfree(dio);
index 46d691b..45b2322 100644 (file)
@@ -133,15 +133,9 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
                                    struct file *file_out, loff_t pos_out,
                                    size_t count, unsigned int flags)
 {
-       ssize_t ret;
-
        if (file_inode(file_in) == file_inode(file_out))
                return -EINVAL;
-retry:
-       ret = nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
-       if (ret == -EAGAIN)
-               goto retry;
-       return ret;
+       return nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
 }
 
 static loff_t nfs4_file_llseek(struct file *filep, loff_t offset, int whence)
index 22ce3c8..0570391 100644 (file)
@@ -1895,6 +1895,11 @@ static int nfs_parse_devname(const char *dev_name,
        size_t len;
        char *end;
 
+       if (unlikely(!dev_name || !*dev_name)) {
+               dfprintk(MOUNT, "NFS: device name not specified\n");
+               return -EINVAL;
+       }
+
        /* Is the host name protected with square brakcets? */
        if (*dev_name == '[') {
                end = strchr(++dev_name, ']');
index 5a0bbf9..d09c9f8 100644 (file)
@@ -238,9 +238,9 @@ out:
 }
 
 /* A writeback failed: mark the page as bad, and invalidate the page cache */
-static void nfs_set_pageerror(struct page *page)
+static void nfs_set_pageerror(struct address_space *mapping)
 {
-       nfs_zap_mapping(page_file_mapping(page)->host, page_file_mapping(page));
+       nfs_zap_mapping(mapping->host, mapping);
 }
 
 /*
@@ -621,11 +621,12 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
        nfs_set_page_writeback(page);
        WARN_ON_ONCE(test_bit(PG_CLEAN, &req->wb_flags));
 
-       ret = 0;
+       ret = req->wb_context->error;
        /* If there is a fatal error that covers this write, just exit */
-       if (nfs_error_is_fatal_on_server(req->wb_context->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;
                /*
@@ -635,9 +636,9 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
                        nfs_context_set_write_error(req->wb_context, ret);
                        if (nfs_error_is_fatal_on_server(ret))
                                goto out_launder;
-               }
+               } else
+                       ret = -EAGAIN;
                nfs_redirty_request(req);
-               ret = -EAGAIN;
        } else
                nfs_add_stats(page_file_mapping(page)->host,
                                NFSIOS_WRITEPAGES, 1);
@@ -993,7 +994,7 @@ static void nfs_write_completion(struct nfs_pgio_header *hdr)
                nfs_list_remove_request(req);
                if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) &&
                    (hdr->good_bytes < bytes)) {
-                       nfs_set_pageerror(req->wb_page);
+                       nfs_set_pageerror(page_file_mapping(req->wb_page));
                        nfs_context_set_write_error(req->wb_context, hdr->error);
                        goto remove_req;
                }
@@ -1347,7 +1348,8 @@ int nfs_updatepage(struct file *file, struct page *page,
                unsigned int offset, unsigned int count)
 {
        struct nfs_open_context *ctx = nfs_file_open_context(file);
-       struct inode    *inode = page_file_mapping(page)->host;
+       struct address_space *mapping = page_file_mapping(page);
+       struct inode    *inode = mapping->host;
        int             status = 0;
 
        nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE);
@@ -1365,7 +1367,7 @@ int nfs_updatepage(struct file *file, struct page *page,
 
        status = nfs_writepage_setup(ctx, page, offset, count);
        if (status < 0)
-               nfs_set_pageerror(page);
+               nfs_set_pageerror(mapping);
        else
                __set_page_dirty_nobuffers(page);
 out:
index b33f978..72a7681 100644 (file)
@@ -1239,8 +1239,8 @@ static __net_init int nfsd_init_net(struct net *net)
        retval = nfsd_idmap_init(net);
        if (retval)
                goto out_idmap_error;
-       nn->nfsd4_lease = 45;   /* default lease time */
-       nn->nfsd4_grace = 45;
+       nn->nfsd4_lease = 90;   /* default lease time */
+       nn->nfsd4_grace = 90;
        nn->somebody_reclaimed = false;
        nn->clverifier_counter = prandom_u32();
        nn->clientid_counter = prandom_u32();
index 9824e32..7dc98e1 100644 (file)
@@ -557,9 +557,11 @@ __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst,
        loff_t cloned;
 
        cloned = vfs_clone_file_range(src, src_pos, dst, dst_pos, count, 0);
+       if (cloned < 0)
+               return nfserrno(cloned);
        if (count && cloned != count)
-               cloned = -EINVAL;
-       return nfserrno(cloned < 0 ? cloned : 0);
+               return nfserrno(-EINVAL);
+       return 0;
 }
 
 ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst,
index 105576d..798f125 100644 (file)
@@ -724,8 +724,10 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname,
                return -EBADF;
 
        /* IN_MASK_ADD and IN_MASK_CREATE don't make sense together */
-       if (unlikely((mask & IN_MASK_ADD) && (mask & IN_MASK_CREATE)))
-               return -EINVAL;
+       if (unlikely((mask & IN_MASK_ADD) && (mask & IN_MASK_CREATE))) {
+               ret = -EINVAL;
+               goto fput_and_out;
+       }
 
        /* verify that this is indeed an inotify instance */
        if (unlikely(f.file->f_op != &inotify_fops)) {
index 8ae1094..e39bac9 100644 (file)
@@ -256,7 +256,7 @@ struct dentry *proc_lookup_de(struct inode *dir, struct dentry *dentry,
                inode = proc_get_inode(dir->i_sb, de);
                if (!inode)
                        return ERR_PTR(-ENOMEM);
-               d_set_d_op(dentry, &proc_misc_dentry_ops);
+               d_set_d_op(dentry, de->proc_dops);
                return d_splice_alias(inode, dentry);
        }
        read_unlock(&proc_subdir_lock);
@@ -429,6 +429,8 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
        INIT_LIST_HEAD(&ent->pde_openers);
        proc_set_user(ent, (*parent)->uid, (*parent)->gid);
 
+       ent->proc_dops = &proc_misc_dentry_ops;
+
 out:
        return ent;
 }
index 5185d7f..95b1419 100644 (file)
@@ -44,6 +44,7 @@ struct proc_dir_entry {
        struct completion *pde_unload_completion;
        const struct inode_operations *proc_iops;
        const struct file_operations *proc_fops;
+       const struct dentry_operations *proc_dops;
        union {
                const struct seq_operations *seq_ops;
                int (*single_show)(struct seq_file *, void *);
index d5e0fcb..a7b1243 100644 (file)
@@ -38,6 +38,22 @@ static struct net *get_proc_net(const struct inode *inode)
        return maybe_get_net(PDE_NET(PDE(inode)));
 }
 
+static int proc_net_d_revalidate(struct dentry *dentry, unsigned int flags)
+{
+       return 0;
+}
+
+static const struct dentry_operations proc_net_dentry_ops = {
+       .d_revalidate   = proc_net_d_revalidate,
+       .d_delete       = always_delete_dentry,
+};
+
+static void pde_force_lookup(struct proc_dir_entry *pde)
+{
+       /* /proc/net/ entries can be changed under us by setns(CLONE_NEWNET) */
+       pde->proc_dops = &proc_net_dentry_ops;
+}
+
 static int seq_open_net(struct inode *inode, struct file *file)
 {
        unsigned int state_size = PDE(inode)->state_size;
@@ -90,6 +106,7 @@ struct proc_dir_entry *proc_create_net_data(const char *name, umode_t mode,
        p = proc_create_reg(name, mode, &parent, data);
        if (!p)
                return NULL;
+       pde_force_lookup(p);
        p->proc_fops = &proc_net_seq_fops;
        p->seq_ops = ops;
        p->state_size = state_size;
@@ -133,6 +150,7 @@ struct proc_dir_entry *proc_create_net_data_write(const char *name, umode_t mode
        p = proc_create_reg(name, mode, &parent, data);
        if (!p)
                return NULL;
+       pde_force_lookup(p);
        p->proc_fops = &proc_net_seq_fops;
        p->seq_ops = ops;
        p->state_size = state_size;
@@ -181,6 +199,7 @@ struct proc_dir_entry *proc_create_net_single(const char *name, umode_t mode,
        p = proc_create_reg(name, mode, &parent, data);
        if (!p)
                return NULL;
+       pde_force_lookup(p);
        p->proc_fops = &proc_net_single_fops;
        p->single_show = show;
        return proc_register(parent, p);
@@ -223,6 +242,7 @@ struct proc_dir_entry *proc_create_net_single_write(const char *name, umode_t mo
        p = proc_create_reg(name, mode, &parent, data);
        if (!p)
                return NULL;
+       pde_force_lookup(p);
        p->proc_fops = &proc_net_single_fops;
        p->single_show = show;
        p->write = write;
index f0ec9ed..85b0ef8 100644 (file)
@@ -423,7 +423,7 @@ struct mem_size_stats {
 };
 
 static void smaps_account(struct mem_size_stats *mss, struct page *page,
-               bool compound, bool young, bool dirty)
+               bool compound, bool young, bool dirty, bool locked)
 {
        int i, nr = compound ? 1 << compound_order(page) : 1;
        unsigned long size = nr * PAGE_SIZE;
@@ -450,24 +450,31 @@ static void smaps_account(struct mem_size_stats *mss, struct page *page,
                else
                        mss->private_clean += size;
                mss->pss += (u64)size << PSS_SHIFT;
+               if (locked)
+                       mss->pss_locked += (u64)size << PSS_SHIFT;
                return;
        }
 
        for (i = 0; i < nr; i++, page++) {
                int mapcount = page_mapcount(page);
+               unsigned long pss = (PAGE_SIZE << PSS_SHIFT);
 
                if (mapcount >= 2) {
                        if (dirty || PageDirty(page))
                                mss->shared_dirty += PAGE_SIZE;
                        else
                                mss->shared_clean += PAGE_SIZE;
-                       mss->pss += (PAGE_SIZE << PSS_SHIFT) / mapcount;
+                       mss->pss += pss / mapcount;
+                       if (locked)
+                               mss->pss_locked += pss / mapcount;
                } else {
                        if (dirty || PageDirty(page))
                                mss->private_dirty += PAGE_SIZE;
                        else
                                mss->private_clean += PAGE_SIZE;
-                       mss->pss += PAGE_SIZE << PSS_SHIFT;
+                       mss->pss += pss;
+                       if (locked)
+                               mss->pss_locked += pss;
                }
        }
 }
@@ -490,6 +497,7 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr,
 {
        struct mem_size_stats *mss = walk->private;
        struct vm_area_struct *vma = walk->vma;
+       bool locked = !!(vma->vm_flags & VM_LOCKED);
        struct page *page = NULL;
 
        if (pte_present(*pte)) {
@@ -532,7 +540,7 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr,
        if (!page)
                return;
 
-       smaps_account(mss, page, false, pte_young(*pte), pte_dirty(*pte));
+       smaps_account(mss, page, false, pte_young(*pte), pte_dirty(*pte), locked);
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -541,6 +549,7 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr,
 {
        struct mem_size_stats *mss = walk->private;
        struct vm_area_struct *vma = walk->vma;
+       bool locked = !!(vma->vm_flags & VM_LOCKED);
        struct page *page;
 
        /* FOLL_DUMP will return -EFAULT on huge zero page */
@@ -555,7 +564,7 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr,
                /* pass */;
        else
                VM_BUG_ON_PAGE(1, page);
-       smaps_account(mss, page, true, pmd_young(*pmd), pmd_dirty(*pmd));
+       smaps_account(mss, page, true, pmd_young(*pmd), pmd_dirty(*pmd), locked);
 }
 #else
 static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr,
@@ -737,11 +746,8 @@ static void smap_gather_stats(struct vm_area_struct *vma,
                }
        }
 #endif
-
        /* mmap_sem is held in m_start */
        walk_page_vma(vma, &smaps_walk);
-       if (vma->vm_flags & VM_LOCKED)
-               mss->pss_locked += mss->pss;
 }
 
 #define SEQ_PUT_DEC(str, val) \
index 96f7d32..898c832 100644 (file)
@@ -128,7 +128,6 @@ ramoops_get_next_prz(struct persistent_ram_zone *przs[], int id,
                     struct pstore_record *record)
 {
        struct persistent_ram_zone *prz;
-       bool update = (record->type == PSTORE_TYPE_DMESG);
 
        /* Give up if we never existed or have hit the end. */
        if (!przs)
@@ -139,7 +138,7 @@ ramoops_get_next_prz(struct persistent_ram_zone *przs[], int id,
                return NULL;
 
        /* Update old/shadowed buffer. */
-       if (update)
+       if (prz->type == PSTORE_TYPE_DMESG)
                persistent_ram_save_old(prz);
 
        if (!persistent_ram_old_size(prz))
@@ -711,18 +710,15 @@ static int ramoops_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct ramoops_platform_data *pdata = dev->platform_data;
+       struct ramoops_platform_data pdata_local;
        struct ramoops_context *cxt = &oops_cxt;
        size_t dump_mem_sz;
        phys_addr_t paddr;
        int err = -EINVAL;
 
        if (dev_of_node(dev) && !pdata) {
-               pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-               if (!pdata) {
-                       pr_err("cannot allocate platform data buffer\n");
-                       err = -ENOMEM;
-                       goto fail_out;
-               }
+               pdata = &pdata_local;
+               memset(pdata, 0, sizeof(*pdata));
 
                err = ramoops_parse_dt(pdev, pdata);
                if (err < 0)
index feeae80..aa85f28 100644 (file)
@@ -43,7 +43,8 @@ int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
        kuid_t uid;
        kgid_t gid;
 
-       BUG_ON(!kobj);
+       if (WARN_ON(!kobj))
+               return -EINVAL;
 
        if (kobj->parent)
                parent = kobj->parent->sd;
index bb71db6..5139845 100644 (file)
@@ -325,7 +325,8 @@ int sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr,
        kuid_t uid;
        kgid_t gid;
 
-       BUG_ON(!kobj || !kobj->sd || !attr);
+       if (WARN_ON(!kobj || !kobj->sd || !attr))
+               return -EINVAL;
 
        kobject_get_ownership(kobj, &uid, &gid);
        return sysfs_add_file_mode_ns(kobj->sd, attr, false, attr->mode,
@@ -537,7 +538,8 @@ int sysfs_create_bin_file(struct kobject *kobj,
        kuid_t uid;
        kgid_t gid;
 
-       BUG_ON(!kobj || !kobj->sd || !attr);
+       if (WARN_ON(!kobj || !kobj->sd || !attr))
+               return -EINVAL;
 
        kobject_get_ownership(kobj, &uid, &gid);
        return sysfs_add_file_mode_ns(kobj->sd, &attr->attr, true,
index 1eb2d63..5703860 100644 (file)
@@ -112,7 +112,8 @@ static int internal_create_group(struct kobject *kobj, int update,
        kgid_t gid;
        int error;
 
-       BUG_ON(!kobj || (!update && !kobj->sd));
+       if (WARN_ON(!kobj || (!update && !kobj->sd)))
+               return -EINVAL;
 
        /* Updates may happen before the object has been instantiated */
        if (unlikely(update && !kobj->sd))
index 215c225..c4deecc 100644 (file)
@@ -23,7 +23,8 @@ static int sysfs_do_create_link_sd(struct kernfs_node *parent,
 {
        struct kernfs_node *kn, *target = NULL;
 
-       BUG_ON(!name || !parent);
+       if (WARN_ON(!name || !parent))
+               return -EINVAL;
 
        /*
         * We don't own @target_kobj and it may be removed at any time.
index 1c8eecf..6acf1bf 100644 (file)
@@ -768,18 +768,23 @@ xrep_findroot_block(
                if (!uuid_equal(&btblock->bb_u.s.bb_uuid,
                                &mp->m_sb.sb_meta_uuid))
                        goto out;
+               /*
+                * Read verifiers can reference b_ops, so we set the pointer
+                * here.  If the verifier fails we'll reset the buffer state
+                * to what it was before we touched the buffer.
+                */
+               bp->b_ops = fab->buf_ops;
                fab->buf_ops->verify_read(bp);
                if (bp->b_error) {
+                       bp->b_ops = NULL;
                        bp->b_error = 0;
                        goto out;
                }
 
                /*
                 * Some read verifiers will (re)set b_ops, so we must be
-                * careful not to blow away any such assignment.
+                * careful not to change b_ops after running the verifier.
                 */
-               if (!bp->b_ops)
-                       bp->b_ops = fab->buf_ops;
        }
 
        /*
index 338b9d9..d9048bc 100644 (file)
@@ -449,6 +449,7 @@ xfs_map_blocks(
        }
 
        wpc->imap = imap;
+       xfs_trim_extent_eof(&wpc->imap, ip);
        trace_xfs_map_blocks_found(ip, offset, count, wpc->io_type, &imap);
        return 0;
 allocate_blocks:
@@ -459,6 +460,7 @@ allocate_blocks:
        ASSERT(whichfork == XFS_COW_FORK || cow_fsb == NULLFILEOFF ||
               imap.br_startoff + imap.br_blockcount <= cow_fsb);
        wpc->imap = imap;
+       xfs_trim_extent_eof(&wpc->imap, ip);
        trace_xfs_map_blocks_alloc(ip, offset, count, wpc->io_type, &imap);
        return 0;
 }
index eedc5e0..4f5f2ff 100644 (file)
@@ -776,10 +776,26 @@ _xfs_buf_read(
 }
 
 /*
+ * Set buffer ops on an unchecked buffer and validate it, if possible.
+ *
  * If the caller passed in an ops structure and the buffer doesn't have ops
  * assigned, set the ops and use them to verify the contents.  If the contents
  * cannot be verified, we'll clear XBF_DONE.  We assume the buffer has no
  * recorded errors and is already in XBF_DONE state.
+ *
+ * Under normal operations, every in-core buffer must have buffer ops assigned
+ * to them when the buffer is read in from disk so that we can validate the
+ * metadata.
+ *
+ * However, there are two scenarios where one can encounter in-core buffers
+ * that don't have buffer ops.  The first is during log recovery of buffers on
+ * a V4 filesystem, though these buffers are purged at the end of recovery.
+ *
+ * The other is online repair, which tries to match arbitrary metadata blocks
+ * with btree types in order to find the root.  If online repair doesn't match
+ * the buffer with /any/ btree type, the buffer remains in memory in DONE state
+ * with no ops, and a subsequent read_buf call from elsewhere will not set the
+ * ops.  This function helps us fix this situation.
  */
 int
 xfs_buf_ensure_ops(
@@ -1536,8 +1552,7 @@ __xfs_buf_submit(
                xfs_buf_ioerror(bp, -EIO);
                bp->b_flags &= ~XBF_DONE;
                xfs_buf_stale(bp);
-               if (bp->b_flags & XBF_ASYNC)
-                       xfs_buf_ioend(bp);
+               xfs_buf_ioend(bp);
                return -EIO;
        }
 
index 5736c94..2d4fc2d 100644 (file)
@@ -1365,6 +1365,13 @@ enum drm_dp_quirk {
         * to 16 bits. So will give a constant value (0x8000) for compatability.
         */
        DP_DPCD_QUIRK_CONSTANT_N,
+       /**
+        * @DP_DPCD_QUIRK_NO_PSR:
+        *
+        * The device does not support PSR even if reports that it supports or
+        * driver still need to implement proper handling for such device.
+        */
+       DP_DPCD_QUIRK_NO_PSR,
 };
 
 /**
index 59f005b..727af08 100644 (file)
@@ -616,7 +616,8 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
                              struct drm_dp_mst_topology_mgr *mgr);
 
 void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr);
-int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr);
+int __must_check
+drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr);
 struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state,
                                                                    struct drm_dp_mst_topology_mgr *mgr);
 int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
index b53be41..04f7ac3 100644 (file)
 #define IMX8MQ_CLK_VPU_G2_ROOT                 241
 
 /* SCCG PLL GATE */
-#define IMX8MQ_SYS1_PLL_OUT                    232
+#define IMX8MQ_SYS1_PLL_OUT                    242
 #define IMX8MQ_SYS2_PLL_OUT                    243
 #define IMX8MQ_SYS3_PLL_OUT                    244
 #define IMX8MQ_DRAM_PLL_OUT                    245
 /* txesc clock */
 #define IMX8MQ_CLK_DSI_IPG_DIV                  256
 
-#define IMX8MQ_CLK_TMU_ROOT                    265
+#define IMX8MQ_CLK_TMU_ROOT                    257
 
 /* Display root clocks */
-#define IMX8MQ_CLK_DISP_AXI_ROOT               266
-#define IMX8MQ_CLK_DISP_APB_ROOT               267
-#define IMX8MQ_CLK_DISP_RTRM_ROOT              268
+#define IMX8MQ_CLK_DISP_AXI_ROOT               258
+#define IMX8MQ_CLK_DISP_APB_ROOT               259
+#define IMX8MQ_CLK_DISP_RTRM_ROOT              260
 
-#define IMX8MQ_CLK_OCOTP_ROOT                  269
+#define IMX8MQ_CLK_OCOTP_ROOT                  261
 
-#define IMX8MQ_CLK_DRAM_ALT_ROOT               270
-#define IMX8MQ_CLK_DRAM_CORE                   271
+#define IMX8MQ_CLK_DRAM_ALT_ROOT               262
+#define IMX8MQ_CLK_DRAM_CORE                   263
 
-#define IMX8MQ_CLK_MU_ROOT                     272
-#define IMX8MQ_VIDEO2_PLL_OUT                  273
+#define IMX8MQ_CLK_MU_ROOT                     264
+#define IMX8MQ_VIDEO2_PLL_OUT                  265
 
-#define IMX8MQ_CLK_CLKO2                       274
+#define IMX8MQ_CLK_CLKO2                       266
 
-#define IMX8MQ_CLK_NAND_USDHC_BUS_RAWNAND_CLK  275
+#define IMX8MQ_CLK_NAND_USDHC_BUS_RAWNAND_CLK  267
 
-#define IMX8MQ_CLK_END                         276
+#define IMX8MQ_CLK_END                         268
 #endif /* __DT_BINDINGS_CLOCK_IMX8MQ_H */
index 7b24fc7..228a5e2 100644 (file)
@@ -71,7 +71,6 @@
 #define MMP2_CLK_CCIC1_MIX             117
 #define MMP2_CLK_CCIC1_PHY             118
 #define MMP2_CLK_CCIC1_SPHY            119
-#define MMP2_CLK_SP                    120
 
 #define MMP2_NR_CLKS                   200
 #endif
index ad6f55d..0f2e0fe 100644 (file)
@@ -1,12 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
 /*
- *
  * Copyright (c) 2016 BayLibre, SAS.
  * Author: Neil Armstrong <narmstrong@baylibre.com>
  *
  * Copyright (c) 2017 Amlogic, inc.
  * Author: Yixun Lan <yixun.lan@amlogic.com>
  *
- * SPDX-License-Identifier: (GPL-2.0+ OR BSD)
  */
 
 #ifndef _DT_BINDINGS_AMLOGIC_MESON_AXG_RESET_H
index 4f31f96..c36c86f 100644 (file)
@@ -100,7 +100,7 @@ enum vgic_irq_config {
 };
 
 struct vgic_irq {
-       spinlock_t irq_lock;            /* Protects the content of the struct */
+       raw_spinlock_t irq_lock;        /* Protects the content of the struct */
        struct list_head lpi_list;      /* Used to link all LPIs together */
        struct list_head ap_list;
 
@@ -256,7 +256,7 @@ struct vgic_dist {
        u64                     propbaser;
 
        /* Protects the lpi_list and the count value below. */
-       spinlock_t              lpi_list_lock;
+       raw_spinlock_t          lpi_list_lock;
        struct list_head        lpi_list_head;
        int                     lpi_list_count;
 
@@ -307,7 +307,7 @@ struct vgic_cpu {
        unsigned int used_lrs;
        struct vgic_irq private_irqs[VGIC_NR_PRIVATE_IRQS];
 
-       spinlock_t ap_list_lock;        /* Protects the ap_list */
+       raw_spinlock_t ap_list_lock;    /* Protects the ap_list */
 
        /*
         * List of IRQs that this VCPU should consider because they are either
index c311571..07e02d6 100644 (file)
@@ -190,6 +190,7 @@ struct backing_dev_info {
        struct radix_tree_root cgwb_tree; /* radix tree of active cgroup wbs */
        struct rb_root cgwb_congested_tree; /* their congested states */
        struct mutex cgwb_release_mutex;  /* protect shutdown of wb structs */
+       struct rw_semaphore wb_switch_rwsem; /* no cgwb switch while syncing */
 #else
        struct bdi_writeback_congested *wb_congested;
 #endif
index 7cca5f8..f3c4351 100644 (file)
@@ -6,6 +6,7 @@
 
 struct bcma_soc {
        struct bcma_bus bus;
+       struct device *dev;
 };
 
 int __init bcma_host_soc_register(struct bcma_soc *soc);
index 5c7e7f8..d66bf5f 100644 (file)
@@ -287,7 +287,7 @@ enum req_opf {
        REQ_OP_DISCARD          = 3,
        /* securely erase sectors */
        REQ_OP_SECURE_ERASE     = 5,
-       /* seset a zone write pointer */
+       /* reset a zone write pointer */
        REQ_OP_ZONE_RESET       = 6,
        /* write the same sector many times */
        REQ_OP_WRITE_SAME       = 7,
index 8804753..7bb2d8d 100644 (file)
@@ -116,7 +116,13 @@ extern void blk_fill_rwbs(char *rwbs, unsigned int op, int bytes);
 
 static inline sector_t blk_rq_trace_sector(struct request *rq)
 {
-       return blk_rq_is_passthrough(rq) ? 0 : blk_rq_pos(rq);
+       /*
+        * Tracing should ignore starting sector for passthrough requests and
+        * requests where starting sector didn't get set.
+        */
+       if (blk_rq_is_passthrough(rq) || blk_rq_pos(rq) == (sector_t)-1)
+               return 0;
+       return blk_rq_pos(rq);
 }
 
 static inline unsigned int blk_rq_trace_nr_sectors(struct request *rq)
index 27b7494..573cca0 100644 (file)
@@ -172,6 +172,7 @@ struct bpf_verifier_state_list {
 #define BPF_ALU_SANITIZE_SRC           1U
 #define BPF_ALU_SANITIZE_DST           2U
 #define BPF_ALU_NEG_VALUE              (1U << 2)
+#define BPF_ALU_NON_POINTER            (1U << 3)
 #define BPF_ALU_SANITIZE               (BPF_ALU_SANITIZE_SRC | \
                                         BPF_ALU_SANITIZE_DST)
 
index f02cee0..d815622 100644 (file)
@@ -3,13 +3,22 @@
 #define _LINUX_BPFILTER_H
 
 #include <uapi/linux/bpfilter.h>
+#include <linux/umh.h>
 
 struct sock;
 int bpfilter_ip_set_sockopt(struct sock *sk, int optname, char __user *optval,
                            unsigned int optlen);
 int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval,
                            int __user *optlen);
-extern int (*bpfilter_process_sockopt)(struct sock *sk, int optname,
-                                      char __user *optval,
-                                      unsigned int optlen, bool is_set);
+struct bpfilter_umh_ops {
+       struct umh_info info;
+       /* since ip_getsockopt() can run in parallel, serialize access to umh */
+       struct mutex lock;
+       int (*sockopt)(struct sock *sk, int optname,
+                      char __user *optval,
+                      unsigned int optlen, bool is_set);
+       int (*start)(void);
+       bool stop;
+};
+extern struct bpfilter_umh_ops bpfilter_ops;
 #endif
index 68bb09c..a420c07 100644 (file)
@@ -35,6 +35,7 @@
 #define CEPH_OPT_NOMSGAUTH       (1<<4) /* don't require msg signing feat */
 #define CEPH_OPT_TCP_NODELAY     (1<<5) /* TCP_NODELAY on TCP sockets */
 #define CEPH_OPT_NOMSGSIGN       (1<<6) /* don't sign msgs */
+#define CEPH_OPT_ABORT_ON_FULL   (1<<7) /* abort w/ ENOSPC when full */
 
 #define CEPH_OPT_DEFAULT   (CEPH_OPT_TCP_NODELAY)
 
@@ -53,7 +54,7 @@ struct ceph_options {
        unsigned long osd_request_timeout;      /* jiffies */
 
        /*
-        * any type that can't be simply compared or doesn't need need
+        * any type that can't be simply compared or doesn't need
         * to be compared should go beyond this point,
         * ceph_compare_options() should be updated accordingly
         */
@@ -281,7 +282,8 @@ extern struct ceph_options *ceph_parse_options(char *options,
                              const char *dev_name, const char *dev_name_end,
                              int (*parse_extra_token)(char *c, void *private),
                              void *private);
-int ceph_print_client_options(struct seq_file *m, struct ceph_client *client);
+int ceph_print_client_options(struct seq_file *m, struct ceph_client *client,
+                             bool show_all);
 extern void ceph_destroy_options(struct ceph_options *opt);
 extern int ceph_compare_options(struct ceph_options *new_opt,
                                struct ceph_client *client);
index 7a2af50..2294f96 100644 (file)
@@ -354,7 +354,6 @@ struct ceph_osd_client {
        struct rb_root         linger_map_checks;
        atomic_t               num_requests;
        atomic_t               num_homeless;
-       bool                   abort_on_full; /* abort w/ ENOSPC when full */
        int                    abort_err;
        struct delayed_work    timeout_work;
        struct delayed_work    osds_timeout_work;
index 39f668d..333a669 100644 (file)
@@ -3,9 +3,8 @@
 #error "Please don't include <linux/compiler-clang.h> directly, include <linux/compiler.h> instead."
 #endif
 
-/* Some compiler specific definitions are overwritten here
- * for Clang compiler
- */
+/* Compiler specific definitions for Clang compiler */
+
 #define uninitialized_var(x) x = *(&(x))
 
 /* same as gcc, this was present in clang-2.6 so we can assume it works
index 5776da4..e857941 100644 (file)
        (typeof(ptr)) (__ptr + (off));                                  \
 })
 
-/* Make the optimizer believe the variable can be manipulated arbitrarily. */
-#define OPTIMIZER_HIDE_VAR(var)                                                \
-       __asm__ ("" : "=r" (var) : "0" (var))
-
 /*
  * A trick to suppress uninitialized variable warning without generating any
  * code
  */
 #define uninitialized_var(x) x = x
 
-#ifdef RETPOLINE
+#ifdef CONFIG_RETPOLINE
 #define __noretpoline __attribute__((__indirect_branch__("keep")))
 #endif
 
index 517bd14..b17f3cd 100644 (file)
@@ -5,9 +5,7 @@
 
 #ifdef __ECC
 
-/* Some compiler specific definitions are overwritten here
- * for Intel ECC compiler
- */
+/* Compiler specific definitions for Intel ECC compiler */
 
 #include <asm/intrinsics.h>
 
index fc5004a..445348f 100644 (file)
@@ -161,7 +161,9 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
 #endif
 
 #ifndef OPTIMIZER_HIDE_VAR
-#define OPTIMIZER_HIDE_VAR(var) barrier()
+/* Make the optimizer believe the variable can be manipulated arbitrarily. */
+#define OPTIMIZER_HIDE_VAR(var)                                                \
+       __asm__ ("" : "=r" (var) : "0" (var))
 #endif
 
 /* Not-quite-unique ID. */
index 19f32b0..6b318ef 100644 (file)
@@ -34,6 +34,7 @@
 #ifndef __has_attribute
 # define __has_attribute(x) __GCC4_has_attribute_##x
 # define __GCC4_has_attribute___assume_aligned__      (__GNUC_MINOR__ >= 9)
+# define __GCC4_has_attribute___copy__                0
 # define __GCC4_has_attribute___designated_init__     0
 # define __GCC4_has_attribute___externally_visible__  1
 # define __GCC4_has_attribute___noclone__             1
 #define __attribute_const__             __attribute__((__const__))
 
 /*
+ * Optional: only supported since gcc >= 9
+ * Optional: not supported by clang
+ * Optional: not supported by icc
+ *
+ *   gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-copy-function-attribute
+ */
+#if __has_attribute(__copy__)
+# define __copy(symbol)                 __attribute__((__copy__(symbol)))
+#else
+# define __copy(symbol)
+#endif
+
+/*
  * Don't. Just don't. See commit 771c035372a0 ("deprecate the '__deprecated'
  * attribute warnings entirely and for good") for more information.
  *
index 218df7f..5041357 100644 (file)
@@ -180,12 +180,10 @@ enum cpuhp_smt_control {
 #if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT)
 extern enum cpuhp_smt_control cpu_smt_control;
 extern void cpu_smt_disable(bool force);
-extern void cpu_smt_check_topology_early(void);
 extern void cpu_smt_check_topology(void);
 #else
 # define cpu_smt_control               (CPU_SMT_ENABLED)
 static inline void cpu_smt_disable(bool force) { }
-static inline void cpu_smt_check_topology_early(void) { }
 static inline void cpu_smt_check_topology(void) { }
 #endif
 
index ef4b70f..60996e6 100644 (file)
@@ -62,9 +62,10 @@ extern const struct qstr slash_name;
 struct dentry_stat_t {
        long nr_dentry;
        long nr_unused;
-       long age_limit;          /* age in seconds */
-       long want_pages;         /* pages requested by system */
-       long dummy[2];
+       long age_limit;         /* age in seconds */
+       long want_pages;        /* pages requested by system */
+       long nr_negative;       /* # of unused negative dentries */
+       long dummy;             /* Reserved for future use */
 };
 extern struct dentry_stat_t dentry_stat;
 
index cef2127..f6ded99 100644 (file)
@@ -717,15 +717,6 @@ static inline unsigned long dma_max_pfn(struct device *dev)
 }
 #endif
 
-/*
- * Please always use dma_alloc_coherent instead as it already zeroes the memory!
- */
-static inline void *dma_zalloc_coherent(struct device *dev, size_t size,
-                                       dma_addr_t *dma_handle, gfp_t flag)
-{
-       return dma_alloc_coherent(dev, size, dma_handle, flag);
-}
-
 static inline int dma_get_cache_alignment(void)
 {
 #ifdef ARCH_DMA_MINALIGN
index 45ff763..28604a8 100644 (file)
@@ -1198,8 +1198,6 @@ static inline bool efi_enabled(int feature)
 extern void efi_reboot(enum reboot_mode reboot_mode, const char *__unused);
 
 extern bool efi_is_table_address(unsigned long phys_addr);
-
-extern int efi_apply_persistent_mem_reservations(void);
 #else
 static inline bool efi_enabled(int feature)
 {
@@ -1218,11 +1216,6 @@ static inline bool efi_is_table_address(unsigned long phys_addr)
 {
        return false;
 }
-
-static inline int efi_apply_persistent_mem_reservations(void)
-{
-       return 0;
-}
 #endif
 
 extern int efi_status_to_err(efi_status_t status);
index 7cdd31a..f52ef0a 100644 (file)
@@ -653,6 +653,7 @@ extern int fb_new_modelist(struct fb_info *info);
 
 extern struct fb_info *registered_fb[FB_MAX];
 extern int num_registered_fb;
+extern bool fb_center_logo;
 extern struct class *fb_class;
 
 #define for_each_registered_fb(i)              \
index ad106d8..e532fcc 100644 (file)
@@ -591,8 +591,8 @@ static inline u8 *bpf_skb_cb(struct sk_buff *skb)
        return qdisc_skb_cb(skb)->data;
 }
 
-static inline u32 bpf_prog_run_save_cb(const struct bpf_prog *prog,
-                                      struct sk_buff *skb)
+static inline u32 __bpf_prog_run_save_cb(const struct bpf_prog *prog,
+                                        struct sk_buff *skb)
 {
        u8 *cb_data = bpf_skb_cb(skb);
        u8 cb_saved[BPF_SKB_CB_LEN];
@@ -611,15 +611,30 @@ static inline u32 bpf_prog_run_save_cb(const struct bpf_prog *prog,
        return res;
 }
 
+static inline u32 bpf_prog_run_save_cb(const struct bpf_prog *prog,
+                                      struct sk_buff *skb)
+{
+       u32 res;
+
+       preempt_disable();
+       res = __bpf_prog_run_save_cb(prog, skb);
+       preempt_enable();
+       return res;
+}
+
 static inline u32 bpf_prog_run_clear_cb(const struct bpf_prog *prog,
                                        struct sk_buff *skb)
 {
        u8 *cb_data = bpf_skb_cb(skb);
+       u32 res;
 
        if (unlikely(prog->cb_access))
                memset(cb_data, 0, BPF_SKB_CB_LEN);
 
-       return BPF_PROG_RUN(prog, skb);
+       preempt_disable();
+       res = BPF_PROG_RUN(prog, skb);
+       preempt_enable();
+       return res;
 }
 
 static __always_inline u32 bpf_prog_run_xdp(const struct bpf_prog *prog,
index 811c777..29d8e2c 100644 (file)
@@ -1479,11 +1479,12 @@ struct super_block {
        struct user_namespace *s_user_ns;
 
        /*
-        * Keep the lru lists last in the structure so they always sit on their
-        * own individual cachelines.
+        * The list_lru structure is essentially just a pointer to a table
+        * of per-node lru lists, each of which has its own spinlock.
+        * There is no need to put them into separate cachelines.
         */
-       struct list_lru         s_dentry_lru ____cacheline_aligned_in_smp;
-       struct list_lru         s_inode_lru ____cacheline_aligned_in_smp;
+       struct list_lru         s_dentry_lru;
+       struct list_lru         s_inode_lru;
        struct rcu_head         rcu;
        struct work_struct      destroy_work;
 
index 8663f21..2d6100e 100644 (file)
 
 #ifdef CONFIG_DEBUG_FS
 
+#include <linux/kfifo.h>
+
 #define HID_DEBUG_BUFSIZE 512
+#define HID_DEBUG_FIFOSIZE 512
 
 void hid_dump_input(struct hid_device *, struct hid_usage *, __s32);
 void hid_dump_report(struct hid_device *, int , u8 *, int);
@@ -37,11 +40,8 @@ void hid_debug_init(void);
 void hid_debug_exit(void);
 void hid_debug_event(struct hid_device *, char *);
 
-
 struct hid_debug_list {
-       char *hid_debug_buf;
-       int head;
-       int tail;
+       DECLARE_KFIFO_PTR(hid_debug_fifo, char);
        struct fasync_struct *fasync;
        struct hid_device *hdev;
        struct list_head node;
@@ -64,4 +64,3 @@ struct hid_debug_list {
 #endif
 
 #endif
-
index d992873..f9707d1 100644 (file)
@@ -430,7 +430,7 @@ struct hid_local {
  */
 
 struct hid_collection {
-       struct hid_collection *parent;
+       int parent_idx; /* device->collection */
        unsigned type;
        unsigned usage;
        unsigned level;
@@ -658,7 +658,6 @@ struct hid_parser {
        unsigned int         *collection_stack;
        unsigned int          collection_stack_ptr;
        unsigned int          collection_stack_size;
-       struct hid_collection *active_collection;
        struct hid_device    *device;
        unsigned int          scan_flags;
 };
index f0885cc..dcb6977 100644 (file)
@@ -1159,8 +1159,9 @@ struct hv_ring_buffer_debug_info {
        u32 bytes_avail_towrite;
 };
 
-void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
-                           struct hv_ring_buffer_debug_info *debug_info);
+
+int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
+                               struct hv_ring_buffer_debug_info *debug_info);
 
 /* Vmbus interface */
 #define vmbus_driver_register(driver)  \
index e7d29ae..971cf76 100644 (file)
@@ -615,6 +615,7 @@ struct ide_drive_s {
 
        /* current sense rq and buffer */
        bool sense_rq_armed;
+       bool sense_rq_active;
        struct request *sense_rq;
        struct request_sense sense_data;
 
@@ -1219,6 +1220,7 @@ extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout);
 extern void ide_timer_expiry(struct timer_list *t);
 extern irqreturn_t ide_intr(int irq, void *dev_id);
 extern blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *, const struct blk_mq_queue_data *);
+extern blk_status_t ide_issue_rq(ide_drive_t *, struct request *, bool);
 extern void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq);
 
 void ide_init_disk(struct gendisk *, ide_drive_t *);
index 6756fea..e44746d 100644 (file)
@@ -54,6 +54,7 @@ static inline bool dev_is_mac_header_xmit(const struct net_device *dev)
        case ARPHRD_IPGRE:
        case ARPHRD_VOID:
        case ARPHRD_NONE:
+       case ARPHRD_RAWIP:
                return false;
        default:
                return true;
index c672f34..4a728db 100644 (file)
@@ -260,6 +260,7 @@ struct irq_affinity {
 /**
  * struct irq_affinity_desc - Interrupt affinity descriptor
  * @mask:      cpumask to hold the affinity assignment
+ * @is_managed: 1 if the interrupt is managed internally
  */
 struct irq_affinity_desc {
        struct cpumask  mask;
index 071b4cb..c848a7c 100644 (file)
 #define GITS_TYPER_PLPIS               (1UL << 0)
 #define GITS_TYPER_VLPIS               (1UL << 1)
 #define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT        4
-#define GITS_TYPER_ITT_ENTRY_SIZE(r)   ((((r) >> GITS_TYPER_ITT_ENTRY_SIZE_SHIFT) & 0x1f) + 1)
+#define GITS_TYPER_ITT_ENTRY_SIZE(r)   ((((r) >> GITS_TYPER_ITT_ENTRY_SIZE_SHIFT) & 0xf) + 1)
 #define GITS_TYPER_IDBITS_SHIFT                8
 #define GITS_TYPER_DEVBITS_SHIFT       13
 #define GITS_TYPER_DEVBITS(r)          ((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1)
index 5440f11..ad60961 100644 (file)
@@ -160,6 +160,7 @@ static inline struct nd_blk_region_desc *to_blk_region_desc(
 }
 
 enum nvdimm_security_state {
+       NVDIMM_SECURITY_ERROR = -1,
        NVDIMM_SECURITY_DISABLED,
        NVDIMM_SECURITY_UNLOCKED,
        NVDIMM_SECURITY_LOCKED,
@@ -234,7 +235,6 @@ static inline struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus,
                        cmd_mask, num_flush, flush_wpq, NULL, NULL);
 }
 
-int nvdimm_security_setup_events(struct nvdimm *nvdimm);
 const struct nd_cmd_desc *nd_cmd_dimm_desc(int cmd);
 const struct nd_cmd_desc *nd_cmd_bus_desc(int cmd);
 u32 nd_cmd_in_size(struct nvdimm *nvdimm, int cmd,
index 64c41cf..859b55b 100644 (file)
@@ -29,9 +29,6 @@ extern unsigned long max_pfn;
  */
 extern unsigned long long max_possible_pfn;
 
-#define INIT_MEMBLOCK_REGIONS  128
-#define INIT_PHYSMEM_REGIONS   4
-
 /**
  * enum memblock_flags - definition of memory region attributes
  * @MEMBLOCK_NONE: no special request
index 07da5c6..368267c 100644 (file)
@@ -21,14 +21,16 @@ struct vmem_altmap;
  * walkers which rely on the fully initialized page->flags and others
  * should use this rather than pfn_valid && pfn_to_page
  */
-#define pfn_to_online_page(pfn)                                \
-({                                                     \
-       struct page *___page = NULL;                    \
-       unsigned long ___nr = pfn_to_section_nr(pfn);   \
-                                                       \
-       if (___nr < NR_MEM_SECTIONS && online_section_nr(___nr))\
-               ___page = pfn_to_page(pfn);             \
-       ___page;                                        \
+#define pfn_to_online_page(pfn)                                           \
+({                                                                \
+       struct page *___page = NULL;                               \
+       unsigned long ___pfn = pfn;                                \
+       unsigned long ___nr = pfn_to_section_nr(___pfn);           \
+                                                                  \
+       if (___nr < NR_MEM_SECTIONS && online_section_nr(___nr) && \
+           pfn_valid_within(___pfn))                              \
+               ___page = pfn_to_page(___pfn);                     \
+       ___page;                                                   \
 })
 
 /*
index 9a9631f..fc91082 100644 (file)
@@ -2791,6 +2791,100 @@ struct ec_response_battery_vendor_param {
 } __packed;
 
 /*****************************************************************************/
+/* Commands for I2S recording on audio codec. */
+
+#define EC_CMD_CODEC_I2S 0x00BC
+
+enum ec_codec_i2s_subcmd {
+       EC_CODEC_SET_SAMPLE_DEPTH = 0x0,
+       EC_CODEC_SET_GAIN = 0x1,
+       EC_CODEC_GET_GAIN = 0x2,
+       EC_CODEC_I2S_ENABLE = 0x3,
+       EC_CODEC_I2S_SET_CONFIG = 0x4,
+       EC_CODEC_I2S_SET_TDM_CONFIG = 0x5,
+       EC_CODEC_I2S_SET_BCLK = 0x6,
+};
+
+enum ec_sample_depth_value {
+       EC_CODEC_SAMPLE_DEPTH_16 = 0,
+       EC_CODEC_SAMPLE_DEPTH_24 = 1,
+};
+
+enum ec_i2s_config {
+       EC_DAI_FMT_I2S = 0,
+       EC_DAI_FMT_RIGHT_J = 1,
+       EC_DAI_FMT_LEFT_J = 2,
+       EC_DAI_FMT_PCM_A = 3,
+       EC_DAI_FMT_PCM_B = 4,
+       EC_DAI_FMT_PCM_TDM = 5,
+};
+
+struct ec_param_codec_i2s {
+       /*
+        * enum ec_codec_i2s_subcmd
+        */
+       uint8_t cmd;
+       union {
+               /*
+                * EC_CODEC_SET_SAMPLE_DEPTH
+                * Value should be one of ec_sample_depth_value.
+                */
+               uint8_t depth;
+
+               /*
+                * EC_CODEC_SET_GAIN
+                * Value should be 0~43 for both channels.
+                */
+               struct ec_param_codec_i2s_set_gain {
+                       uint8_t left;
+                       uint8_t right;
+               } __packed gain;
+
+               /*
+                * EC_CODEC_I2S_ENABLE
+                * 1 to enable, 0 to disable.
+                */
+               uint8_t i2s_enable;
+
+               /*
+                * EC_CODEC_I2S_SET_COFNIG
+                * Value should be one of ec_i2s_config.
+                */
+               uint8_t i2s_config;
+
+               /*
+                * EC_CODEC_I2S_SET_TDM_CONFIG
+                * Value should be one of ec_i2s_config.
+                */
+               struct ec_param_codec_i2s_tdm {
+                       /*
+                        * 0 to 496
+                        */
+                       int16_t ch0_delay;
+                       /*
+                        * -1 to 496
+                        */
+                       int16_t ch1_delay;
+                       uint8_t adjacent_to_ch0;
+                       uint8_t adjacent_to_ch1;
+               } __packed tdm_param;
+
+               /*
+                * EC_CODEC_I2S_SET_BCLK
+                */
+               uint32_t bclk;
+       };
+} __packed;
+
+/*
+ * For subcommand EC_CODEC_GET_GAIN.
+ */
+struct ec_response_codec_gain {
+       uint8_t left;
+       uint8_t right;
+} __packed;
+
+/*****************************************************************************/
 /* System commands */
 
 /*
index ab16ad2..2083fa2 100644 (file)
@@ -41,7 +41,7 @@
 #define TCU_TCSR_PRESCALE_LSB          3
 #define TCU_TCSR_PRESCALE_MASK         0x38
 
-#define TCU_TCSR_PWM_SD                BIT(9)  /* 0: Shutdown abruptly 1: gracefully */
+#define TCU_TCSR_PWM_SD                BIT(9)  /* 0: Shutdown gracefully 1: abruptly */
 #define TCU_TCSR_PWM_INITL_HIGH        BIT(8)  /* Sets the initial output level */
 #define TCU_TCSR_PWM_EN                BIT(7)  /* PWM pin output enable */
 
index fe69c0f..4d5d51a 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/mfd/madera/pdata.h>
+#include <linux/mutex.h>
 #include <linux/notifier.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
@@ -37,6 +38,8 @@ enum madera_type {
 
 #define MADERA_MAX_MICBIAS             4
 
+#define MADERA_MAX_HP_OUTPUT           3
+
 /* Notifier events */
 #define MADERA_NOTIFY_VOICE_TRIGGER    0x1
 #define MADERA_NOTIFY_HPDET            0x2
@@ -183,6 +186,10 @@ struct madera {
        unsigned int num_childbias[MADERA_MAX_MICBIAS];
 
        struct snd_soc_dapm_context *dapm;
+       struct mutex dapm_ptr_lock;
+       unsigned int hp_ena;
+       bool out_clamp[MADERA_MAX_HP_OUTPUT];
+       bool out_shorted[MADERA_MAX_HP_OUTPUT];
 
        struct blocking_notifier_head notifier;
 };
index b9a53e0..4831684 100644 (file)
@@ -78,6 +78,8 @@
 #define STEPCONFIG_YNN         BIT(8)
 #define STEPCONFIG_XNP         BIT(9)
 #define STEPCONFIG_YPN         BIT(10)
+#define STEPCONFIG_RFP(val)    ((val) << 12)
+#define STEPCONFIG_RFP_VREFP   (0x3 << 12)
 #define STEPCONFIG_INM_MASK    (0xF << 15)
 #define STEPCONFIG_INM(val)    ((val) << 15)
 #define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8)
@@ -86,6 +88,8 @@
 #define STEPCONFIG_INP_AN4     STEPCONFIG_INP(4)
 #define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8)
 #define STEPCONFIG_FIFO1       BIT(26)
+#define STEPCONFIG_RFM(val)    ((val) << 23)
+#define STEPCONFIG_RFM_VREFN   (0x3 << 23)
 
 /* Delay register */
 #define STEPDELAY_OPEN_MASK    (0x3FFFF << 0)
index e2687a3..739b7bf 100644 (file)
@@ -79,7 +79,7 @@
 /* Some controllers have a CBSY bit */
 #define TMIO_MMC_HAVE_CBSY             BIT(11)
 
-/* Some controllers that support HS400 use use 4 taps while others use 8. */
+/* Some controllers that support HS400 use 4 taps while others use 8. */
 #define TMIO_MMC_HAVE_4TAP_HS400       BIT(13)
 
 int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base);
index de73778..8ef3300 100644 (file)
@@ -308,6 +308,7 @@ struct mmc_card {
        unsigned int    nr_parts;
 
        unsigned int            bouncesz;       /* Bounce buffer size */
+       struct workqueue_struct *complete_wq;   /* Private workqueue */
 };
 
 static inline bool mmc_large_sector(struct mmc_card *card)
index cc4a507..842f918 100644 (file)
@@ -520,6 +520,12 @@ enum pgdat_flags {
        PGDAT_RECLAIM_LOCKED,           /* prevents concurrent reclaim */
 };
 
+enum zone_flags {
+       ZONE_BOOSTED_WATERMARK,         /* zone recently boosted watermarks.
+                                        * Cleared when kswapd is woken.
+                                        */
+};
+
 static inline unsigned long zone_managed_pages(struct zone *zone)
 {
        return (unsigned long)atomic_long_read(&zone->managed_pages);
index 9a21fe3..f5bc4c0 100644 (file)
@@ -129,13 +129,13 @@ extern void cleanup_module(void);
 #define module_init(initfn)                                    \
        static inline initcall_t __maybe_unused __inittest(void)                \
        { return initfn; }                                      \
-       int init_module(void) __attribute__((alias(#initfn)));
+       int init_module(void) __copy(initfn) __attribute__((alias(#initfn)));
 
 /* This is only required if you want to be unloadable. */
 #define module_exit(exitfn)                                    \
        static inline exitcall_t __maybe_unused __exittest(void)                \
        { return exitfn; }                                      \
-       void cleanup_module(void) __attribute__((alias(#exitfn)));
+       void cleanup_module(void) __copy(exitfn) __attribute__((alias(#exitfn)));
 
 #endif
 
@@ -828,7 +828,7 @@ static inline void module_bug_finalize(const Elf_Ehdr *hdr,
 static inline void module_bug_cleanup(struct module *mod) {}
 #endif /* CONFIG_GENERIC_BUG */
 
-#ifdef RETPOLINE
+#ifdef CONFIG_RETPOLINE
 extern bool retpoline_module_ok(bool has_retpoline);
 #else
 static inline bool retpoline_module_ok(bool has_retpoline)
index 1377d08..86dbb3e 100644 (file)
@@ -1483,6 +1483,7 @@ struct net_device_ops {
  * @IFF_NO_RX_HANDLER: device doesn't support the rx_handler hook
  * @IFF_FAILOVER: device is a failover master device
  * @IFF_FAILOVER_SLAVE: device is lower dev of a failover master device
+ * @IFF_L3MDEV_RX_HANDLER: only invoke the rx handler of L3 master device
  */
 enum netdev_priv_flags {
        IFF_802_1Q_VLAN                 = 1<<0,
@@ -1514,6 +1515,7 @@ enum netdev_priv_flags {
        IFF_NO_RX_HANDLER               = 1<<26,
        IFF_FAILOVER                    = 1<<27,
        IFF_FAILOVER_SLAVE              = 1<<28,
+       IFF_L3MDEV_RX_HANDLER           = 1<<29,
 };
 
 #define IFF_802_1Q_VLAN                        IFF_802_1Q_VLAN
@@ -1544,6 +1546,7 @@ enum netdev_priv_flags {
 #define IFF_NO_RX_HANDLER              IFF_NO_RX_HANDLER
 #define IFF_FAILOVER                   IFF_FAILOVER
 #define IFF_FAILOVER_SLAVE             IFF_FAILOVER_SLAVE
+#define IFF_L3MDEV_RX_HANDLER          IFF_L3MDEV_RX_HANDLER
 
 /**
  *     struct net_device - The DEVICE structure.
@@ -4549,6 +4552,11 @@ static inline bool netif_supports_nofcs(struct net_device *dev)
        return dev->priv_flags & IFF_SUPP_NOFCS;
 }
 
+static inline bool netif_has_l3_rx_handler(const struct net_device *dev)
+{
+       return dev->priv_flags & IFF_L3MDEV_RX_HANDLER;
+}
+
 static inline bool netif_is_l3_master(const struct net_device *dev)
 {
        return dev->priv_flags & IFF_L3MDEV_MASTER;
index fe472e5..e240992 100644 (file)
@@ -50,7 +50,6 @@ struct of_irq_controller;
 
 struct device_node {
        const char *name;
-       const char *type;
        phandle phandle;
        const char *full_name;
        struct fwnode_handle fwnode;
index cb1adf0..249d4d7 100644 (file)
@@ -24,7 +24,7 @@ static inline void *
 pci_zalloc_consistent(struct pci_dev *hwdev, size_t size,
                      dma_addr_t *dma_handle)
 {
-       return dma_zalloc_coherent(&hwdev->dev, size, dma_handle, GFP_ATOMIC);
+       return dma_alloc_coherent(&hwdev->dev, size, dma_handle, GFP_ATOMIC);
 }
 
 static inline void
index 1d5c551..e1a0517 100644 (file)
@@ -447,6 +447,11 @@ struct pmu {
         * Filter events for PMU-specific reasons.
         */
        int (*filter_match)             (struct perf_event *event); /* optional */
+
+       /*
+        * Check period value for PERF_EVENT_IOC_PERIOD ioctl.
+        */
+       int (*check_period)             (struct perf_event *event, u64 value); /* optional */
 };
 
 enum perf_addr_filter_action_t {
index 3b051f7..127fcc9 100644 (file)
@@ -48,6 +48,7 @@ extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_features) __ro_after_init;
 extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_fibre_features) __ro_after_init;
 extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_all_ports_features) __ro_after_init;
 extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_features) __ro_after_init;
+extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_fec_features) __ro_after_init;
 extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) __ro_after_init;
 
 #define PHY_BASIC_FEATURES ((unsigned long *)&phy_basic_features)
@@ -56,6 +57,7 @@ extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) __ro_after_ini
 #define PHY_GBIT_FIBRE_FEATURES ((unsigned long *)&phy_gbit_fibre_features)
 #define PHY_GBIT_ALL_PORTS_FEATURES ((unsigned long *)&phy_gbit_all_ports_features)
 #define PHY_10GBIT_FEATURES ((unsigned long *)&phy_10gbit_features)
+#define PHY_10GBIT_FEC_FEATURES ((unsigned long *)&phy_10gbit_fec_features)
 #define PHY_10GBIT_FULL_FEATURES ((unsigned long *)&phy_10gbit_full_features)
 
 extern const int phy_10_100_features_array[4];
@@ -467,8 +469,8 @@ struct phy_device {
  *   only works for PHYs with IDs which match this field
  * name: The friendly name of this PHY type
  * phy_id_mask: Defines the important bits of the phy_id
- * features: A list of features (speed, duplex, etc) supported
- *   by this PHY
+ * features: A mandatory list of features (speed, duplex, etc)
+ *   supported by this PHY
  * flags: A bitfield defining certain other features this PHY
  *   supports (like interrupts)
  *
@@ -672,26 +674,13 @@ phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
 size_t phy_speeds(unsigned int *speeds, size_t size,
                  unsigned long *mask);
 
-static inline bool __phy_is_started(struct phy_device *phydev)
-{
-       WARN_ON(!mutex_is_locked(&phydev->lock));
-
-       return phydev->state >= PHY_UP;
-}
-
 /**
  * phy_is_started - Convenience function to check whether PHY is started
  * @phydev: The phy_device struct
  */
 static inline bool phy_is_started(struct phy_device *phydev)
 {
-       bool started;
-
-       mutex_lock(&phydev->lock);
-       started = __phy_is_started(phydev);
-       mutex_unlock(&phydev->lock);
-
-       return started;
+       return phydev->state >= PHY_UP;
 }
 
 void phy_resolve_aneg_linkmode(struct phy_device *phydev);
index e8e118d..3f350e2 100644 (file)
@@ -42,6 +42,7 @@ enum phy_mode {
        PHY_MODE_PCIE,
        PHY_MODE_ETHERNET,
        PHY_MODE_MIPI_DPHY,
+       PHY_MODE_SATA
 };
 
 /**
index 0a2a88e..b895f4e 100644 (file)
@@ -108,6 +108,7 @@ void dev_pm_opp_put(struct dev_pm_opp *opp);
 int dev_pm_opp_add(struct device *dev, unsigned long freq,
                   unsigned long u_volt);
 void dev_pm_opp_remove(struct device *dev, unsigned long freq);
+void dev_pm_opp_remove_all_dynamic(struct device *dev);
 
 int dev_pm_opp_enable(struct device *dev, unsigned long freq);
 
@@ -217,6 +218,10 @@ static inline void dev_pm_opp_remove(struct device *dev, unsigned long freq)
 {
 }
 
+static inline void dev_pm_opp_remove_all_dynamic(struct device *dev)
+{
+}
+
 static inline int dev_pm_opp_enable(struct device *dev, unsigned long freq)
 {
        return 0;
index 54af4ee..fed5be7 100644 (file)
@@ -105,7 +105,7 @@ static inline bool pm_runtime_callbacks_present(struct device *dev)
 
 static inline void pm_runtime_mark_last_busy(struct device *dev)
 {
-       WRITE_ONCE(dev->power.last_busy, ktime_to_ns(ktime_get()));
+       WRITE_ONCE(dev->power.last_busy, ktime_get_mono_fast_ns());
 }
 
 static inline bool pm_runtime_is_irq_safe(struct device *dev)
index 1637385..d0aecc0 100644 (file)
@@ -13,6 +13,7 @@
 #ifndef __QCOM_SCM_H
 #define __QCOM_SCM_H
 
+#include <linux/err.h>
 #include <linux/types.h>
 #include <linux/cpumask.h>
 
index 59ddf9a..2dd0a9e 100644 (file)
@@ -663,6 +663,37 @@ out:
 static inline void qed_chain_set_prod(struct qed_chain *p_chain,
                                      u32 prod_idx, void *p_prod_elem)
 {
+       if (p_chain->mode == QED_CHAIN_MODE_PBL) {
+               u32 cur_prod, page_mask, page_cnt, page_diff;
+
+               cur_prod = is_chain_u16(p_chain) ? p_chain->u.chain16.prod_idx :
+                          p_chain->u.chain32.prod_idx;
+
+               /* Assume that number of elements in a page is power of 2 */
+               page_mask = ~p_chain->elem_per_page_mask;
+
+               /* Use "cur_prod - 1" and "prod_idx - 1" since producer index
+                * reaches the first element of next page before the page index
+                * is incremented. See qed_chain_produce().
+                * Index wrap around is not a problem because the difference
+                * between current and given producer indices is always
+                * positive and lower than the chain's capacity.
+                */
+               page_diff = (((cur_prod - 1) & page_mask) -
+                            ((prod_idx - 1) & page_mask)) /
+                           p_chain->elem_per_page;
+
+               page_cnt = qed_chain_get_page_cnt(p_chain);
+               if (is_chain_u16(p_chain))
+                       p_chain->pbl.c.u16.prod_page_idx =
+                               (p_chain->pbl.c.u16.prod_page_idx -
+                                page_diff + page_cnt) % page_cnt;
+               else
+                       p_chain->pbl.c.u32.prod_page_idx =
+                               (p_chain->pbl.c.u32.prod_page_idx -
+                                page_diff + page_cnt) % page_cnt;
+       }
+
        if (is_chain_u16(p_chain))
                p_chain->u.chain16.prod_idx = (u16) prod_idx;
        else
index 29af6d6..c1901b6 100644 (file)
@@ -32,6 +32,8 @@ struct reset_control *devm_reset_control_array_get(struct device *dev,
 struct reset_control *of_reset_control_array_get(struct device_node *np,
                                                 bool shared, bool optional);
 
+int reset_control_get_count(struct device *dev);
+
 #else
 
 static inline int reset_control_reset(struct reset_control *rstc)
@@ -97,6 +99,11 @@ of_reset_control_array_get(struct device_node *np, bool shared, bool optional)
        return optional ? NULL : ERR_PTR(-ENOTSUPP);
 }
 
+static inline int reset_control_get_count(struct device *dev)
+{
+       return -ENOENT;
+}
+
 #endif /* CONFIG_RESET_CONTROLLER */
 
 static inline int __must_check device_reset(struct device *dev)
@@ -138,7 +145,7 @@ __must_check reset_control_get_exclusive(struct device *dev, const char *id)
  *
  * Returns a struct reset_control or IS_ERR() condition containing errno.
  * This function is intended for use with reset-controls which are shared
- * between hardware-blocks.
+ * between hardware blocks.
  *
  * When a reset-control is shared, the behavior of reset_control_assert /
  * deassert is changed, the reset-core will keep track of a deassert_count
@@ -187,7 +194,7 @@ static inline struct reset_control *of_reset_control_get_exclusive(
 }
 
 /**
- * of_reset_control_get_shared - Lookup and obtain an shared reference
+ * of_reset_control_get_shared - Lookup and obtain a shared reference
  *                               to a reset controller.
  * @node: device to be reset by the controller
  * @id: reset line name
@@ -229,7 +236,7 @@ static inline struct reset_control *of_reset_control_get_exclusive_by_index(
 }
 
 /**
- * of_reset_control_get_shared_by_index - Lookup and obtain an shared
+ * of_reset_control_get_shared_by_index - Lookup and obtain a shared
  *                                        reference to a reset controller
  *                                        by index.
  * @node: device to be reset by the controller
@@ -322,7 +329,7 @@ devm_reset_control_get_exclusive_by_index(struct device *dev, int index)
 
 /**
  * devm_reset_control_get_shared_by_index - resource managed
- * reset_control_get_shared
+ *                                          reset_control_get_shared
  * @dev: device to be reset by the controller
  * @index: index of the reset controller
  *
index 89541d2..bba3afb 100644 (file)
@@ -995,7 +995,7 @@ struct task_struct {
        /* cg_list protected by css_set_lock and tsk->alloc_lock: */
        struct list_head                cg_list;
 #endif
-#ifdef CONFIG_RESCTRL
+#ifdef CONFIG_X86_CPU_RESCTRL
        u32                             closid;
        u32                             rmid;
 #endif
@@ -1406,6 +1406,7 @@ extern struct pid *cad_pid;
 #define PF_RANDOMIZE           0x00400000      /* Randomize virtual address space */
 #define PF_SWAPWRITE           0x00800000      /* Allowed to write to swap */
 #define PF_MEMSTALL            0x01000000      /* Stalled due to lack of memory */
+#define PF_UMH                 0x02000000      /* I'm an Usermodehelper process */
 #define PF_NO_SETAFFINITY      0x04000000      /* Userland is not allowed to meddle with cpus_allowed */
 #define PF_MCE_EARLY           0x08000000      /* Early kill for mce process policy */
 #define PF_MUTEX_TESTER                0x20000000      /* Thread belongs to the rt mutex tester */
@@ -1904,6 +1905,14 @@ static inline void rseq_execve(struct task_struct *t)
 
 #endif
 
+void __exit_umh(struct task_struct *tsk);
+
+static inline void exit_umh(struct task_struct *tsk)
+{
+       if (unlikely(tsk->flags & PF_UMH))
+               __exit_umh(tsk);
+}
+
 #ifdef CONFIG_DEBUG_RSEQ
 
 void rseq_syscall(struct pt_regs *regs);
index ec912d0..ecdc654 100644 (file)
@@ -71,6 +71,7 @@ static inline int get_dumpable(struct mm_struct *mm)
 #define MMF_HUGE_ZERO_PAGE     23      /* mm has ever used the global huge zero page */
 #define MMF_DISABLE_THP                24      /* disable THP for all VMAs */
 #define MMF_OOM_VICTIM         25      /* mm is the oom victim */
+#define MMF_OOM_REAP_QUEUED    26      /* mm was queued for oom_reaper */
 #define MMF_DISABLE_THP_MASK   (1 << MMF_DISABLE_THP)
 
 #define MMF_INIT_MASK          (MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK |\
index 10b19a1..545f371 100644 (file)
  * called near the end of a function. Otherwise, the list can be
  * re-initialized for later re-use by wake_q_init().
  *
- * Note that this can cause spurious wakeups. schedule() callers
+ * NOTE that this can cause spurious wakeups. schedule() callers
  * must ensure the call is done inside a loop, confirming that the
  * wakeup condition has in fact occurred.
+ *
+ * NOTE that there is no guarantee the wakeup will happen any later than the
+ * wake_q_add() location. Therefore task must be ready to be woken at the
+ * location of the wake_q_add().
  */
 
 #include <linux/sched.h>
index cc7e2c1..9702016 100644 (file)
@@ -392,7 +392,7 @@ extern bool unhandled_signal(struct task_struct *tsk, int sig);
 #endif
 
 #define siginmask(sig, mask) \
-       ((sig) < SIGRTMIN && (rt_sigmask(sig) & (mask)))
+       ((sig) > 0 && (sig) < SIGRTMIN && (rt_sigmask(sig) & (mask)))
 
 #define SIG_KERNEL_ONLY_MASK (\
        rt_sigmask(SIGKILL)   |  rt_sigmask(SIGSTOP))
index 93f56fd..95d25b0 100644 (file)
@@ -3218,6 +3218,7 @@ int pskb_trim_rcsum_slow(struct sk_buff *skb, unsigned int len);
  *
  *     This is exactly the same as pskb_trim except that it ensures the
  *     checksum of received packets are still valid after the operation.
+ *     It can change skb pointers.
  */
 
 static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
index 7ddfc65..4335bd7 100644 (file)
@@ -184,6 +184,7 @@ struct plat_stmmacenet_data {
        struct clk *pclk;
        struct clk *clk_ptp_ref;
        unsigned int clk_ptp_rate;
+       unsigned int clk_ref_rate;
        struct reset_control *stmmac_rst;
        struct stmmac_axi *axi;
        int has_gmac4;
index 235f51b..0c08de3 100644 (file)
@@ -47,6 +47,8 @@ struct umh_info {
        const char *cmdline;
        struct file *pipe_to_umh;
        struct file *pipe_from_umh;
+       struct list_head list;
+       void (*cleanup)(struct umh_info *info);
        pid_t pid;
 };
 int fork_usermode_blob(void *data, size_t len, struct umh_info *info);
index 32baf8e..987b649 100644 (file)
@@ -12,6 +12,11 @@ struct irq_affinity;
 
 /**
  * virtio_config_ops - operations for configuring a virtio device
+ * Note: Do not assume that a transport implements all of the operations
+ *       getting/setting a value as a simple read/write! Generally speaking,
+ *       any of @get/@set, @get_status/@set_status, or @get_features/
+ *       @finalize_features are NOT safe to be called from an atomic
+ *       context.
  * @get: read the value of a configuration field
  *     vdev: the virtio_device
  *     offset: the offset of the configuration field
@@ -22,7 +27,7 @@ struct irq_affinity;
  *     offset: the offset of the configuration field
  *     buf: the buffer to read the field value from.
  *     len: the length of the buffer
- * @generation: config generation counter
+ * @generation: config generation counter (optional)
  *     vdev: the virtio_device
  *     Returns the config generation counter
  * @get_status: read the status byte
@@ -48,17 +53,17 @@ struct irq_affinity;
  * @del_vqs: free virtqueues found by find_vqs().
  * @get_features: get the array of feature bits for this device.
  *     vdev: the virtio_device
- *     Returns the first 32 feature bits (all we currently need).
+ *     Returns the first 64 feature bits (all we currently need).
  * @finalize_features: confirm what device features we'll be using.
  *     vdev: the virtio_device
  *     This gives the final feature bits for the device: it can change
  *     the dev->feature bits if it wants.
  *     Returns 0 on success or error status
- * @bus_name: return the bus name associated with the device
+ * @bus_name: return the bus name associated with the device (optional)
  *     vdev: the virtio_device
  *      This returns a pointer to the bus name a la pci_name from which
  *      the caller can then copy.
- * @set_vq_affinity: set the affinity for a virtqueue.
+ * @set_vq_affinity: set the affinity for a virtqueue (optional).
  * @get_vq_affinity: get the affinity for a virtqueue (optional).
  */
 typedef void vq_callback_t(struct virtqueue *);
index f492e21..5d9d318 100644 (file)
@@ -176,7 +176,8 @@ static inline bool xa_is_internal(const void *entry)
  */
 static inline bool xa_is_err(const void *entry)
 {
-       return unlikely(xa_is_internal(entry));
+       return unlikely(xa_is_internal(entry) &&
+                       entry >= xa_mk_internal(-MAX_ERRNO));
 }
 
 /**
@@ -286,7 +287,6 @@ struct xarray {
  */
 #define DEFINE_XARRAY_ALLOC(name) DEFINE_XARRAY_FLAGS(name, XA_FLAGS_ALLOC)
 
-void xa_init_flags(struct xarray *, gfp_t flags);
 void *xa_load(struct xarray *, unsigned long index);
 void *xa_store(struct xarray *, unsigned long index, void *entry, gfp_t);
 void *xa_erase(struct xarray *, unsigned long index);
@@ -304,6 +304,24 @@ unsigned int xa_extract(struct xarray *, void **dst, unsigned long start,
 void xa_destroy(struct xarray *);
 
 /**
+ * xa_init_flags() - Initialise an empty XArray with flags.
+ * @xa: XArray.
+ * @flags: XA_FLAG values.
+ *
+ * If you need to initialise an XArray with special flags (eg you need
+ * to take the lock from interrupt context), use this function instead
+ * of xa_init().
+ *
+ * Context: Any context.
+ */
+static inline void xa_init_flags(struct xarray *xa, gfp_t flags)
+{
+       spin_lock_init(&xa->xa_lock);
+       xa->xa_flags = flags;
+       xa->xa_head = NULL;
+}
+
+/**
  * xa_init() - Initialise an empty XArray.
  * @xa: XArray.
  *
@@ -342,20 +360,45 @@ static inline bool xa_marked(const struct xarray *xa, xa_mark_t mark)
 }
 
 /**
- * xa_for_each() - Iterate over a portion of an XArray.
+ * xa_for_each_start() - Iterate over a portion of an XArray.
  * @xa: XArray.
+ * @index: Index of @entry.
  * @entry: Entry retrieved from array.
+ * @start: First index to retrieve from array.
+ *
+ * During the iteration, @entry will have the value of the entry stored
+ * in @xa at @index.  You may modify @index during the iteration if you
+ * want to skip or reprocess indices.  It is safe to modify the array
+ * during the iteration.  At the end of the iteration, @entry will be set
+ * to NULL and @index will have a value less than or equal to max.
+ *
+ * xa_for_each_start() is O(n.log(n)) while xas_for_each() is O(n).  You have
+ * to handle your own locking with xas_for_each(), and if you have to unlock
+ * after each iteration, it will also end up being O(n.log(n)).
+ * xa_for_each_start() will spin if it hits a retry entry; if you intend to
+ * see retry entries, you should use the xas_for_each() iterator instead.
+ * The xas_for_each() iterator will expand into more inline code than
+ * xa_for_each_start().
+ *
+ * Context: Any context.  Takes and releases the RCU lock.
+ */
+#define xa_for_each_start(xa, index, entry, start)                     \
+       for (index = start,                                             \
+            entry = xa_find(xa, &index, ULONG_MAX, XA_PRESENT);        \
+            entry;                                                     \
+            entry = xa_find_after(xa, &index, ULONG_MAX, XA_PRESENT))
+
+/**
+ * xa_for_each() - Iterate over present entries in an XArray.
+ * @xa: XArray.
  * @index: Index of @entry.
- * @max: Maximum index to retrieve from array.
- * @filter: Selection criterion.
+ * @entry: Entry retrieved from array.
  *
- * Initialise @index to the lowest index you want to retrieve from the
- * array.  During the iteration, @entry will have the value of the entry
- * stored in @xa at @index.  The iteration will skip all entries in the
- * array which do not match @filter.  You may modify @index during the
- * iteration if you want to skip or reprocess indices.  It is safe to modify
- * the array during the iteration.  At the end of the iteration, @entry will
- * be set to NULL and @index will have a value less than or equal to max.
+ * During the iteration, @entry will have the value of the entry stored
+ * in @xa at @index.  You may modify @index during the iteration if you want
+ * to skip or reprocess indices.  It is safe to modify the array during the
+ * iteration.  At the end of the iteration, @entry will be set to NULL and
+ * @index will have a value less than or equal to max.
  *
  * xa_for_each() is O(n.log(n)) while xas_for_each() is O(n).  You have
  * to handle your own locking with xas_for_each(), and if you have to unlock
@@ -366,9 +409,36 @@ static inline bool xa_marked(const struct xarray *xa, xa_mark_t mark)
  *
  * Context: Any context.  Takes and releases the RCU lock.
  */
-#define xa_for_each(xa, entry, index, max, filter) \
-       for (entry = xa_find(xa, &index, max, filter); entry; \
-            entry = xa_find_after(xa, &index, max, filter))
+#define xa_for_each(xa, index, entry) \
+       xa_for_each_start(xa, index, entry, 0)
+
+/**
+ * xa_for_each_marked() - Iterate over marked entries in an XArray.
+ * @xa: XArray.
+ * @index: Index of @entry.
+ * @entry: Entry retrieved from array.
+ * @filter: Selection criterion.
+ *
+ * During the iteration, @entry will have the value of the entry stored
+ * in @xa at @index.  The iteration will skip all entries in the array
+ * which do not match @filter.  You may modify @index during the iteration
+ * if you want to skip or reprocess indices.  It is safe to modify the array
+ * during the iteration.  At the end of the iteration, @entry will be set to
+ * NULL and @index will have a value less than or equal to max.
+ *
+ * xa_for_each_marked() is O(n.log(n)) while xas_for_each_marked() is O(n).
+ * You have to handle your own locking with xas_for_each(), and if you have
+ * to unlock after each iteration, it will also end up being O(n.log(n)).
+ * xa_for_each_marked() will spin if it hits a retry entry; if you intend to
+ * see retry entries, you should use the xas_for_each_marked() iterator
+ * instead.  The xas_for_each_marked() iterator will expand into more inline
+ * code than xa_for_each_marked().
+ *
+ * Context: Any context.  Takes and releases the RCU lock.
+ */
+#define xa_for_each_marked(xa, index, entry, filter) \
+       for (index = 0, entry = xa_find(xa, &index, ULONG_MAX, filter); \
+            entry; entry = xa_find_after(xa, &index, ULONG_MAX, filter))
 
 #define xa_trylock(xa)         spin_trylock(&(xa)->xa_lock)
 #define xa_lock(xa)            spin_lock(&(xa)->xa_lock)
@@ -393,40 +463,13 @@ void *__xa_erase(struct xarray *, unsigned long index);
 void *__xa_store(struct xarray *, unsigned long index, void *entry, gfp_t);
 void *__xa_cmpxchg(struct xarray *, unsigned long index, void *old,
                void *entry, gfp_t);
+int __xa_insert(struct xarray *, unsigned long index, void *entry, gfp_t);
 int __xa_alloc(struct xarray *, u32 *id, u32 max, void *entry, gfp_t);
 int __xa_reserve(struct xarray *, unsigned long index, gfp_t);
 void __xa_set_mark(struct xarray *, unsigned long index, xa_mark_t);
 void __xa_clear_mark(struct xarray *, unsigned long index, xa_mark_t);
 
 /**
- * __xa_insert() - Store this entry in the XArray unless another entry is
- *                     already present.
- * @xa: XArray.
- * @index: Index into array.
- * @entry: New entry.
- * @gfp: Memory allocation flags.
- *
- * If you would rather see the existing entry in the array, use __xa_cmpxchg().
- * This function is for users who don't care what the entry is, only that
- * one is present.
- *
- * Context: Any context.  Expects xa_lock to be held on entry.  May
- *         release and reacquire xa_lock if the @gfp flags permit.
- * Return: 0 if the store succeeded.  -EEXIST if another entry was present.
- * -ENOMEM if memory could not be allocated.
- */
-static inline int __xa_insert(struct xarray *xa, unsigned long index,
-               void *entry, gfp_t gfp)
-{
-       void *curr = __xa_cmpxchg(xa, index, NULL, entry, gfp);
-       if (!curr)
-               return 0;
-       if (xa_is_err(curr))
-               return xa_err(curr);
-       return -EEXIST;
-}
-
-/**
  * xa_store_bh() - Store this entry in the XArray.
  * @xa: XArray.
  * @index: Index into array.
@@ -453,7 +496,7 @@ static inline void *xa_store_bh(struct xarray *xa, unsigned long index,
 }
 
 /**
- * xa_store_irq() - Erase this entry from the XArray.
+ * xa_store_irq() - Store this entry in the XArray.
  * @xa: XArray.
  * @index: Index into array.
  * @entry: New entry.
@@ -615,24 +658,83 @@ static inline void *xa_cmpxchg_irq(struct xarray *xa, unsigned long index,
  * @entry: New entry.
  * @gfp: Memory allocation flags.
  *
- * If you would rather see the existing entry in the array, use xa_cmpxchg().
- * This function is for users who don't care what the entry is, only that
- * one is present.
+ * Inserting a NULL entry will store a reserved entry (like xa_reserve())
+ * if no entry is present.  Inserting will fail if a reserved entry is
+ * present, even though loading from this index will return NULL.
  *
- * Context: Process context.  Takes and releases the xa_lock.
- *         May sleep if the @gfp flags permit.
+ * Context: Any context.  Takes and releases the xa_lock.  May sleep if
+ * the @gfp flags permit.
  * Return: 0 if the store succeeded.  -EEXIST if another entry was present.
  * -ENOMEM if memory could not be allocated.
  */
 static inline int xa_insert(struct xarray *xa, unsigned long index,
                void *entry, gfp_t gfp)
 {
-       void *curr = xa_cmpxchg(xa, index, NULL, entry, gfp);
-       if (!curr)
-               return 0;
-       if (xa_is_err(curr))
-               return xa_err(curr);
-       return -EEXIST;
+       int err;
+
+       xa_lock(xa);
+       err = __xa_insert(xa, index, entry, gfp);
+       xa_unlock(xa);
+
+       return err;
+}
+
+/**
+ * xa_insert_bh() - Store this entry in the XArray unless another entry is
+ *                     already present.
+ * @xa: XArray.
+ * @index: Index into array.
+ * @entry: New entry.
+ * @gfp: Memory allocation flags.
+ *
+ * Inserting a NULL entry will store a reserved entry (like xa_reserve())
+ * if no entry is present.  Inserting will fail if a reserved entry is
+ * present, even though loading from this index will return NULL.
+ *
+ * Context: Any context.  Takes and releases the xa_lock while
+ * disabling softirqs.  May sleep if the @gfp flags permit.
+ * Return: 0 if the store succeeded.  -EEXIST if another entry was present.
+ * -ENOMEM if memory could not be allocated.
+ */
+static inline int xa_insert_bh(struct xarray *xa, unsigned long index,
+               void *entry, gfp_t gfp)
+{
+       int err;
+
+       xa_lock_bh(xa);
+       err = __xa_insert(xa, index, entry, gfp);
+       xa_unlock_bh(xa);
+
+       return err;
+}
+
+/**
+ * xa_insert_irq() - Store this entry in the XArray unless another entry is
+ *                     already present.
+ * @xa: XArray.
+ * @index: Index into array.
+ * @entry: New entry.
+ * @gfp: Memory allocation flags.
+ *
+ * Inserting a NULL entry will store a reserved entry (like xa_reserve())
+ * if no entry is present.  Inserting will fail if a reserved entry is
+ * present, even though loading from this index will return NULL.
+ *
+ * Context: Process context.  Takes and releases the xa_lock while
+ * disabling interrupts.  May sleep if the @gfp flags permit.
+ * Return: 0 if the store succeeded.  -EEXIST if another entry was present.
+ * -ENOMEM if memory could not be allocated.
+ */
+static inline int xa_insert_irq(struct xarray *xa, unsigned long index,
+               void *entry, gfp_t gfp)
+{
+       int err;
+
+       xa_lock_irq(xa);
+       err = __xa_insert(xa, index, entry, gfp);
+       xa_unlock_irq(xa);
+
+       return err;
 }
 
 /**
@@ -970,8 +1072,8 @@ static inline bool xa_is_sibling(const void *entry)
                (entry < xa_mk_sibling(XA_CHUNK_SIZE - 1));
 }
 
-#define XA_ZERO_ENTRY          xa_mk_internal(256)
-#define XA_RETRY_ENTRY         xa_mk_internal(257)
+#define XA_RETRY_ENTRY         xa_mk_internal(256)
+#define XA_ZERO_ENTRY          xa_mk_internal(257)
 
 /**
  * xa_is_zero() - Is the entry a zero entry?
@@ -996,6 +1098,17 @@ static inline bool xa_is_retry(const void *entry)
 }
 
 /**
+ * xa_is_advanced() - Is the entry only permitted for the advanced API?
+ * @entry: Entry to be stored in the XArray.
+ *
+ * Return: %true if the entry cannot be stored by the normal API.
+ */
+static inline bool xa_is_advanced(const void *entry)
+{
+       return xa_is_internal(entry) && (entry <= XA_RETRY_ENTRY);
+}
+
+/**
  * typedef xa_update_node_t - A callback function from the XArray.
  * @node: The node which is being processed
  *
index 1adefe4..2bfb87e 100644 (file)
@@ -21,18 +21,6 @@ struct socket;
 struct rxrpc_call;
 
 /*
- * Call completion condition (state == RXRPC_CALL_COMPLETE).
- */
-enum rxrpc_call_completion {
-       RXRPC_CALL_SUCCEEDED,           /* - Normal termination */
-       RXRPC_CALL_REMOTELY_ABORTED,    /* - call aborted by peer */
-       RXRPC_CALL_LOCALLY_ABORTED,     /* - call aborted locally on error or close */
-       RXRPC_CALL_LOCAL_ERROR,         /* - call failed due to local error */
-       RXRPC_CALL_NETWORK_ERROR,       /* - call terminated by network error */
-       NR__RXRPC_CALL_COMPLETIONS
-};
-
-/*
  * Debug ID counter for tracing.
  */
 extern atomic_t rxrpc_debug_id;
@@ -73,10 +61,6 @@ int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t,
                               rxrpc_user_attach_call_t, unsigned long, gfp_t,
                               unsigned int);
 void rxrpc_kernel_set_tx_length(struct socket *, struct rxrpc_call *, s64);
-int rxrpc_kernel_retry_call(struct socket *, struct rxrpc_call *,
-                           struct sockaddr_rxrpc *, struct key *);
-int rxrpc_kernel_check_call(struct socket *, struct rxrpc_call *,
-                           enum rxrpc_call_completion *, u32 *);
 u32 rxrpc_kernel_check_life(const struct socket *, const struct rxrpc_call *);
 void rxrpc_kernel_probe_life(struct socket *, struct rxrpc_call *);
 u32 rxrpc_kernel_get_epoch(struct socket *, struct rxrpc_call *);
index 3f9aea8..8b7eb46 100644 (file)
@@ -201,6 +201,18 @@ static inline void ax25_hold_route(ax25_route *ax25_rt)
 
 void __ax25_put_route(ax25_route *ax25_rt);
 
+extern rwlock_t ax25_route_lock;
+
+static inline void ax25_route_lock_use(void)
+{
+       read_lock(&ax25_route_lock);
+}
+
+static inline void ax25_route_lock_unuse(void)
+{
+       read_unlock(&ax25_route_lock);
+}
+
 static inline void ax25_put_route(ax25_route *ax25_rt)
 {
        if (refcount_dec_and_test(&ax25_rt->refcount))
index 00b5e78..74ff688 100644 (file)
@@ -39,6 +39,7 @@ struct inet_peer {
 
        u32                     metrics[RTAX_MAX];
        u32                     rate_tokens;    /* rate limiting for ICMP */
+       u32                     n_redirects;
        unsigned long           rate_last;
        /*
         * Once inet_peer is queued for deletion (refcnt == 0), following field
index c596976..9c8214d 100644 (file)
@@ -241,7 +241,7 @@ int fib_table_delete(struct net *, struct fib_table *, struct fib_config *,
                     struct netlink_ext_ack *extack);
 int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
                   struct netlink_callback *cb, struct fib_dump_filter *filter);
-int fib_table_flush(struct net *net, struct fib_table *table);
+int fib_table_flush(struct net *net, struct fib_table *table, bool flush_all);
 struct fib_table *fib_trie_unmerge(struct fib_table *main_tb);
 void fib_table_flush_external(struct fib_table *table);
 void fib_free_table(struct fib_table *tb);
index 78fa0ac..5175fd6 100644 (file)
@@ -153,7 +153,8 @@ struct sk_buff *l3mdev_l3_rcv(struct sk_buff *skb, u16 proto)
 
        if (netif_is_l3_slave(skb->dev))
                master = netdev_master_upper_dev_get_rcu(skb->dev);
-       else if (netif_is_l3_master(skb->dev))
+       else if (netif_is_l3_master(skb->dev) ||
+                netif_has_l3_rx_handler(skb->dev))
                master = skb->dev;
 
        if (master && master->l3mdev_ops->l3mdev_l3_rcv)
index 7d5cda7..3e370cb 100644 (file)
@@ -84,7 +84,6 @@ struct flow_offload {
 struct nf_flow_route {
        struct {
                struct dst_entry        *dst;
-               int                     ifindex;
        } tuple[FLOW_OFFLOAD_DIR_MAX];
 };
 
index 841835a..b4984bb 100644 (file)
@@ -469,9 +469,7 @@ struct nft_set_binding {
 int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
                       struct nft_set_binding *binding);
 void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
-                         struct nft_set_binding *binding);
-void nf_tables_rebind_set(const struct nft_ctx *ctx, struct nft_set *set,
-                         struct nft_set_binding *binding);
+                         struct nft_set_binding *binding, bool commit);
 void nf_tables_destroy_set(const struct nft_ctx *ctx, struct nft_set *set);
 
 /**
@@ -721,6 +719,13 @@ struct nft_expr_type {
 #define NFT_EXPR_STATEFUL              0x1
 #define NFT_EXPR_GC                    0x2
 
+enum nft_trans_phase {
+       NFT_TRANS_PREPARE,
+       NFT_TRANS_ABORT,
+       NFT_TRANS_COMMIT,
+       NFT_TRANS_RELEASE
+};
+
 /**
  *     struct nft_expr_ops - nf_tables expression operations
  *
@@ -750,7 +755,8 @@ struct nft_expr_ops {
        void                            (*activate)(const struct nft_ctx *ctx,
                                                    const struct nft_expr *expr);
        void                            (*deactivate)(const struct nft_ctx *ctx,
-                                                     const struct nft_expr *expr);
+                                                     const struct nft_expr *expr,
+                                                     enum nft_trans_phase phase);
        void                            (*destroy)(const struct nft_ctx *ctx,
                                                   const struct nft_expr *expr);
        void                            (*destroy_clone)(const struct nft_ctx *ctx,
@@ -1323,12 +1329,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;
index 2b229f7..f43f935 100644 (file)
@@ -1277,7 +1277,7 @@ static inline void sk_sockets_allocated_inc(struct sock *sk)
        percpu_counter_inc(sk->sk_prot->sockets_allocated);
 }
 
-static inline int
+static inline u64
 sk_sockets_allocated_read_positive(struct sock *sk)
 {
        return percpu_counter_read_positive(sk->sk_prot->sockets_allocated);
index 2a6ac8d..1486b60 100644 (file)
@@ -120,6 +120,8 @@ struct tls_rec {
        struct scatterlist sg_aead_out[2];
 
        char aad_space[TLS_AAD_SPACE_SIZE];
+       u8 iv_data[TLS_CIPHER_AES_GCM_128_IV_SIZE +
+                  TLS_CIPHER_AES_GCM_128_SALT_SIZE];
        struct aead_request aead_req;
        u8 aead_req_ctx[];
 };
index a3ceed3..80debf5 100644 (file)
@@ -2579,9 +2579,10 @@ struct ib_device {
 
        const struct uapi_definition   *driver_def;
        enum rdma_driver_id             driver_id;
+
        /*
-        * Provides synchronization between device unregistration and netlink
-        * commands on a device. To be used only by core.
+        * Positive refcount indicates that the device is currently
+        * registered and cannot be unregistered.
         */
        refcount_t refcount;
        struct completion unreg_completion;
@@ -3926,6 +3927,25 @@ static inline bool ib_access_writable(int access_flags)
 int ib_check_mr_status(struct ib_mr *mr, u32 check_mask,
                       struct ib_mr_status *mr_status);
 
+/**
+ * ib_device_try_get: Hold a registration lock
+ * device: The device to lock
+ *
+ * A device under an active registration lock cannot become unregistered. It
+ * is only possible to obtain a registration lock on a device that is fully
+ * registered, otherwise this function returns false.
+ *
+ * The registration lock is only necessary for actions which require the
+ * device to still be registered. Uses that only require the device pointer to
+ * be valid should use get_device(&ibdev->dev) to hold the memory.
+ *
+ */
+static inline bool ib_device_try_get(struct ib_device *dev)
+{
+       return refcount_inc_not_zero(&dev->refcount);
+}
+
+void ib_device_put(struct ib_device *device);
 struct net_device *ib_get_net_dev_by_params(struct ib_device *dev, u8 port,
                                            u16 pkey, const union ib_gid *gid,
                                            const struct sockaddr *addr);
index 0cdc399..c5188ff 100644 (file)
@@ -173,7 +173,11 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream)
        if (snd_BUG_ON(!stream))
                return;
 
-       stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+       if (stream->direction == SND_COMPRESS_PLAYBACK)
+               stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+       else
+               stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
+
        wake_up(&stream->runtime->sleep);
 }
 
index 7fa48b1..cc7c8d4 100644 (file)
@@ -68,6 +68,7 @@ struct hda_bus {
        unsigned int response_reset:1;  /* controller was reset */
        unsigned int in_reset:1;        /* during reset operation */
        unsigned int no_response_fallback:1; /* don't fallback at RIRB error */
+       unsigned int bus_probing :1;    /* during probing process */
 
        int primary_dig_out_type;       /* primary digital out PCM type */
        unsigned int mixer_assigned;    /* codec addr for mixer name */
index 8ec1de8..e665f11 100644 (file)
@@ -985,6 +985,12 @@ struct snd_soc_dai_link {
        /* Do not create a PCM for this DAI link (Backend link) */
        unsigned int ignore:1;
 
+       /*
+        * This driver uses legacy platform naming. Set by the core, machine
+        * drivers should not modify this value.
+        */
+       unsigned int legacy_platform:1;
+
        struct list_head list; /* DAI link list of the soc card */
        struct snd_soc_dobj dobj; /* For topology */
 };
index 33d2918..e3f005e 100644 (file)
@@ -25,6 +25,7 @@
 enum afs_call_trace {
        afs_call_trace_alloc,
        afs_call_trace_free,
+       afs_call_trace_get,
        afs_call_trace_put,
        afs_call_trace_wake,
        afs_call_trace_work,
@@ -159,6 +160,7 @@ enum afs_file_error {
 #define afs_call_traces \
        EM(afs_call_trace_alloc,                "ALLOC") \
        EM(afs_call_trace_free,                 "FREE ") \
+       EM(afs_call_trace_get,                  "GET  ") \
        EM(afs_call_trace_put,                  "PUT  ") \
        EM(afs_call_trace_wake,                 "WAKE ") \
        E_(afs_call_trace_work,                 "WORK ")
similarity index 83%
rename from include/uapi/linux/android/binder_ctl.h
rename to include/uapi/linux/android/binderfs.h
index 65b2efd..8741047 100644 (file)
@@ -4,8 +4,8 @@
  *
  */
 
-#ifndef _UAPI_LINUX_BINDER_CTL_H
-#define _UAPI_LINUX_BINDER_CTL_H
+#ifndef _UAPI_LINUX_BINDERFS_H
+#define _UAPI_LINUX_BINDERFS_H
 
 #include <linux/android/binder.h>
 #include <linux/types.h>
@@ -22,8 +22,8 @@
  */
 struct binderfs_device {
        char name[BINDERFS_MAX_NAME + 1];
-       __u8 major;
-       __u8 minor;
+       __u32 major;
+       __u32 minor;
 };
 
 /**
@@ -31,5 +31,5 @@ struct binderfs_device {
  */
 #define BINDER_CTL_ADD _IOWR('b', 1, struct binderfs_device)
 
-#endif /* _UAPI_LINUX_BINDER_CTL_H */
+#endif /* _UAPI_LINUX_BINDERFS_H */
 
index 36a7e3f..f28acd9 100644 (file)
@@ -400,6 +400,8 @@ enum {
 /* do not define AUDIT_ARCH_PPCLE since it is not supported by audit */
 #define AUDIT_ARCH_PPC64       (EM_PPC64|__AUDIT_ARCH_64BIT)
 #define AUDIT_ARCH_PPC64LE     (EM_PPC64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
+#define AUDIT_ARCH_RISCV32     (EM_RISCV|__AUDIT_ARCH_LE)
+#define AUDIT_ARCH_RISCV64     (EM_RISCV|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
 #define AUDIT_ARCH_S390                (EM_S390)
 #define AUDIT_ARCH_S390X       (EM_S390|__AUDIT_ARCH_64BIT)
 #define AUDIT_ARCH_SH          (EM_SH)
index 6fa38d0..498eec8 100644 (file)
@@ -138,6 +138,7 @@ struct blk_zone_range {
  * @BLKRESETZONE: Reset the write pointer of the zones in the specified
  *                sector range. The sector range must be zone aligned.
  * @BLKGETZONESZ: Get the device zone size in number of 512 B sectors.
+ * @BLKGETNRZONES: Get the total number of zones of the device.
  */
 #define BLKREPORTZONE  _IOWR(0x12, 130, struct blk_zone_report)
 #define BLKRESETZONE   _IOW(0x12, 131, struct blk_zone_range)
index f6052e7..a55cb8b 100644 (file)
@@ -268,7 +268,7 @@ struct sockaddr_in {
 #define        IN_MULTICAST(a)         IN_CLASSD(a)
 #define        IN_MULTICAST_NET        0xe0000000
 
-#define        IN_BADCLASS(a)          ((((long int) (a) ) == 0xffffffff)
+#define        IN_BADCLASS(a)          (((long int) (a) ) == (long int)0xffffffff)
 #define        IN_EXPERIMENTAL(a)      IN_BADCLASS((a))
 
 #define        IN_CLASSE(a)            ((((long int) (a)) & 0xf0000000) == 0xf0000000)
index 14565d7..e8baca8 100644 (file)
@@ -137,15 +137,21 @@ enum {
        INET_DIAG_TCLASS,
        INET_DIAG_SKMEMINFO,
        INET_DIAG_SHUTDOWN,
-       INET_DIAG_DCTCPINFO,
-       INET_DIAG_PROTOCOL,  /* response attribute only */
+
+       /*
+        * Next extenstions cannot be requested in struct inet_diag_req_v2:
+        * its field idiag_ext has only 8 bits.
+        */
+
+       INET_DIAG_DCTCPINFO,    /* request as INET_DIAG_VEGASINFO */
+       INET_DIAG_PROTOCOL,     /* response attribute only */
        INET_DIAG_SKV6ONLY,
        INET_DIAG_LOCALS,
        INET_DIAG_PEERS,
        INET_DIAG_PAD,
-       INET_DIAG_MARK,
-       INET_DIAG_BBRINFO,
-       INET_DIAG_CLASS_ID,
+       INET_DIAG_MARK,         /* only with CAP_NET_ADMIN */
+       INET_DIAG_BBRINFO,      /* request as INET_DIAG_VEGASINFO */
+       INET_DIAG_CLASS_ID,     /* request as INET_DIAG_TCLASS */
        INET_DIAG_MD5SIG,
        __INET_DIAG_MAX,
 };
index fb78f6f..f056b2a 100644 (file)
  */
 
 struct input_event {
-#if (__BITS_PER_LONG != 32 || !defined(__USE_TIME_BITS64)) && !defined(__KERNEL)
+#if (__BITS_PER_LONG != 32 || !defined(__USE_TIME_BITS64)) && !defined(__KERNEL__)
        struct timeval time;
 #define input_event_sec time.tv_sec
 #define input_event_usec time.tv_usec
 #else
        __kernel_ulong_t __sec;
+#if defined(__sparc__) && defined(__arch64__)
+       unsigned int __usec;
+#else
        __kernel_ulong_t __usec;
+#endif
 #define input_event_sec  __sec
 #define input_event_usec __usec
 #endif
index d73d839..1bc794a 100644 (file)
@@ -147,7 +147,7 @@ struct ptp_pin_desc {
 #define PTP_SYS_OFFSET_PRECISE \
        _IOWR(PTP_CLK_MAGIC, 8, struct ptp_sys_offset_precise)
 #define PTP_SYS_OFFSET_EXTENDED \
-       _IOW(PTP_CLK_MAGIC, 9, struct ptp_sys_offset_extended)
+       _IOWR(PTP_CLK_MAGIC, 9, struct ptp_sys_offset_extended)
 
 struct ptp_extts_event {
        struct ptp_clock_time t; /* Time event occured. */
index 1196e1c..ff8e7dc 100644 (file)
 #define VIRTIO_F_RING_PACKED           34
 
 /*
+ * This feature indicates that memory accesses by the driver and the
+ * device are ordered in a way described by the platform.
+ */
+#define VIRTIO_F_ORDER_PLATFORM                36
+
+/*
  * Does the device support Single Root I/O Virtualization?
  */
 #define VIRTIO_F_SR_IOV                        37
index 2414f8a..4c4e24c 100644 (file)
@@ -213,14 +213,4 @@ struct vring_packed_desc {
        __le16 flags;
 };
 
-struct vring_packed {
-       unsigned int num;
-
-       struct vring_packed_desc *desc;
-
-       struct vring_packed_desc_event *driver;
-
-       struct vring_packed_desc_event *device;
-};
-
 #endif /* _UAPI_LINUX_VIRTIO_RING_H */
index ef3c7ec..eb76b38 100644 (file)
@@ -52,6 +52,11 @@ struct hns_roce_ib_create_srq {
        __aligned_u64 que_addr;
 };
 
+struct hns_roce_ib_create_srq_resp {
+       __u32   srqn;
+       __u32   reserved;
+};
+
 struct hns_roce_ib_create_qp {
        __aligned_u64 buf_addr;
        __aligned_u64 db_addr;
index d13fd49..6e73f02 100644 (file)
@@ -78,6 +78,7 @@ enum pvrdma_wr_opcode {
        PVRDMA_WR_MASKED_ATOMIC_FETCH_AND_ADD,
        PVRDMA_WR_BIND_MW,
        PVRDMA_WR_REG_SIG_MR,
+       PVRDMA_WR_ERROR,
 };
 
 enum pvrdma_wc_status {
index 59a2607..2ca9164 100644 (file)
@@ -1,17 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_ARM_XEN_PAGE_COHERENT_H
-#define _ASM_ARM_XEN_PAGE_COHERENT_H
-
-#include <asm/page.h>
-#include <asm/dma-mapping.h>
-#include <linux/dma-mapping.h>
-
-static inline const struct dma_map_ops *xen_get_dma_ops(struct device *dev)
-{
-       if (dev && dev->archdata.dev_dma_ops)
-               return dev->archdata.dev_dma_ops;
-       return get_arch_dma_ops(NULL);
-}
+#ifndef _XEN_ARM_PAGE_COHERENT_H
+#define _XEN_ARM_PAGE_COHERENT_H
 
 void __xen_dma_map_page(struct device *hwdev, struct page *page,
             dma_addr_t dev_addr, unsigned long offset, size_t size,
@@ -21,87 +10,7 @@ void __xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
                unsigned long attrs);
 void __xen_dma_sync_single_for_cpu(struct device *hwdev,
                dma_addr_t handle, size_t size, enum dma_data_direction dir);
-
 void __xen_dma_sync_single_for_device(struct device *hwdev,
                dma_addr_t handle, size_t size, enum dma_data_direction dir);
 
-static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
-               dma_addr_t *dma_handle, gfp_t flags, unsigned long attrs)
-{
-       return xen_get_dma_ops(hwdev)->alloc(hwdev, size, dma_handle, flags, attrs);
-}
-
-static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
-               void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs)
-{
-       xen_get_dma_ops(hwdev)->free(hwdev, size, cpu_addr, dma_handle, attrs);
-}
-
-static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
-            dma_addr_t dev_addr, unsigned long offset, size_t size,
-            enum dma_data_direction dir, unsigned long attrs)
-{
-       unsigned long page_pfn = page_to_xen_pfn(page);
-       unsigned long dev_pfn = XEN_PFN_DOWN(dev_addr);
-       unsigned long compound_pages =
-               (1<<compound_order(page)) * XEN_PFN_PER_PAGE;
-       bool local = (page_pfn <= dev_pfn) &&
-               (dev_pfn - page_pfn < compound_pages);
-
-       /*
-        * Dom0 is mapped 1:1, while the Linux page can span across
-        * multiple Xen pages, it's not possible for it to contain a
-        * mix of local and foreign Xen pages. So if the first xen_pfn
-        * == mfn the page is local otherwise it's a foreign page
-        * grant-mapped in dom0. If the page is local we can safely
-        * call the native dma_ops function, otherwise we call the xen
-        * specific function.
-        */
-       if (local)
-               xen_get_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
-       else
-               __xen_dma_map_page(hwdev, page, dev_addr, offset, size, dir, attrs);
-}
-
-static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
-               size_t size, enum dma_data_direction dir, unsigned long attrs)
-{
-       unsigned long pfn = PFN_DOWN(handle);
-       /*
-        * Dom0 is mapped 1:1, while the Linux page can be spanned accross
-        * multiple Xen page, it's not possible to have a mix of local and
-        * foreign Xen page. Dom0 is mapped 1:1, so calling pfn_valid on a
-        * foreign mfn will always return false. If the page is local we can
-        * safely call the native dma_ops function, otherwise we call the xen
-        * specific function.
-        */
-       if (pfn_valid(pfn)) {
-               if (xen_get_dma_ops(hwdev)->unmap_page)
-                       xen_get_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs);
-       } else
-               __xen_dma_unmap_page(hwdev, handle, size, dir, attrs);
-}
-
-static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
-               dma_addr_t handle, size_t size, enum dma_data_direction dir)
-{
-       unsigned long pfn = PFN_DOWN(handle);
-       if (pfn_valid(pfn)) {
-               if (xen_get_dma_ops(hwdev)->sync_single_for_cpu)
-                       xen_get_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir);
-       } else
-               __xen_dma_sync_single_for_cpu(hwdev, handle, size, dir);
-}
-
-static inline void xen_dma_sync_single_for_device(struct device *hwdev,
-               dma_addr_t handle, size_t size, enum dma_data_direction dir)
-{
-       unsigned long pfn = PFN_DOWN(handle);
-       if (pfn_valid(pfn)) {
-               if (xen_get_dma_ops(hwdev)->sync_single_for_device)
-                       xen_get_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir);
-       } else
-               __xen_dma_sync_single_for_device(hwdev, handle, size, dir);
-}
-
-#endif /* _ASM_ARM_XEN_PAGE_COHERENT_H */
+#endif /* _XEN_ARM_PAGE_COHERENT_H */
index d47cb77..c9386a3 100644 (file)
@@ -512,6 +512,17 @@ config PSI_DEFAULT_DISABLED
          per default but can be enabled through passing psi=1 on the
          kernel commandline during boot.
 
+         This feature adds some code to the task wakeup and sleep
+         paths of the scheduler. The overhead is too low to affect
+         common scheduling-intense workloads in practice (such as
+         webservers, memcache), but it does show up in artificial
+         scheduler stress tests, such as hackbench.
+
+         If you are paranoid and not sure what the kernel will be
+         used for, say Y.
+
+         Say N if unsure.
+
 endmenu # "CPU/Task time and stats accounting"
 
 config CPU_ISOLATION
@@ -825,7 +836,7 @@ config CGROUP_PIDS
          PIDs controller is designed to stop this from happening.
 
          It should be noted that organisational operations (such as attaching
-         to a cgroup hierarchy will *not* be blocked by the PIDs controller),
+         to a cgroup hierarchy) will *not* be blocked by the PIDs controller,
          since the PIDs limit only affects a process's ability to fork, not to
          attach to a cgroup.
 
@@ -1124,6 +1135,7 @@ config LD_DEAD_CODE_DATA_ELIMINATION
        bool "Dead code and data elimination (EXPERIMENTAL)"
        depends on HAVE_LD_DEAD_CODE_DATA_ELIMINATION
        depends on EXPERT
+       depends on !(FUNCTION_TRACER && CC_IS_GCC && GCC_VERSION < 40800)
        depends on $(cc-option,-ffunction-sections -fdata-sections)
        depends on $(ld-option,--gc-sections)
        help
index e2e80ca..c86a1c8 100644 (file)
@@ -695,7 +695,6 @@ asmlinkage __visible void __init start_kernel(void)
                initrd_start = 0;
        }
 #endif
-       page_ext_init();
        kmemleak_init();
        setup_per_cpu_pageset();
        numa_policy_init();
@@ -1131,6 +1130,8 @@ static noinline void __init kernel_init_freeable(void)
        sched_init_smp();
 
        page_alloc_init_late();
+       /* Initialize page ext after all struct pages are initialized. */
+       page_ext_init();
 
        do_basic_setup();
 
index 715f9fc..c57bd10 100644 (file)
@@ -467,7 +467,7 @@ static const struct btf_kind_operations *btf_type_ops(const struct btf_type *t)
        return kind_ops[BTF_INFO_KIND(t->info)];
 }
 
-bool btf_name_offset_valid(const struct btf *btf, u32 offset)
+static bool btf_name_offset_valid(const struct btf *btf, u32 offset)
 {
        return BTF_STR_OFFSET_VALID(offset) &&
                offset < btf->hdr.str_len;
@@ -1219,8 +1219,6 @@ static void btf_bitfield_seq_show(void *data, u8 bits_offset,
        u8 nr_copy_bits;
        u64 print_num;
 
-       data += BITS_ROUNDDOWN_BYTES(bits_offset);
-       bits_offset = BITS_PER_BYTE_MASKED(bits_offset);
        nr_copy_bits = nr_bits + bits_offset;
        nr_copy_bytes = BITS_ROUNDUP_BYTES(nr_copy_bits);
 
@@ -1255,7 +1253,9 @@ static void btf_int_bits_seq_show(const struct btf *btf,
         * BTF_INT_OFFSET() cannot exceed 64 bits.
         */
        total_bits_offset = bits_offset + BTF_INT_OFFSET(int_data);
-       btf_bitfield_seq_show(data, total_bits_offset, nr_bits, m);
+       data += BITS_ROUNDDOWN_BYTES(total_bits_offset);
+       bits_offset = BITS_PER_BYTE_MASKED(total_bits_offset);
+       btf_bitfield_seq_show(data, bits_offset, nr_bits, m);
 }
 
 static void btf_int_seq_show(const struct btf *btf, const struct btf_type *t,
@@ -1459,7 +1459,8 @@ static int btf_modifier_resolve(struct btf_verifier_env *env,
 
                /* "typedef void new_void", "const void"...etc */
                if (!btf_type_is_void(next_type) &&
-                   !btf_type_is_fwd(next_type)) {
+                   !btf_type_is_fwd(next_type) &&
+                   !btf_type_is_func_proto(next_type)) {
                        btf_verifier_log_type(env, v->t, "Invalid type_id");
                        return -EINVAL;
                }
@@ -2001,12 +2002,12 @@ static void btf_struct_seq_show(const struct btf *btf, const struct btf_type *t,
 
                member_offset = btf_member_bit_offset(t, member);
                bitfield_size = btf_member_bitfield_size(t, member);
+               bytes_offset = BITS_ROUNDDOWN_BYTES(member_offset);
+               bits8_offset = BITS_PER_BYTE_MASKED(member_offset);
                if (bitfield_size) {
-                       btf_bitfield_seq_show(data, member_offset,
+                       btf_bitfield_seq_show(data + bytes_offset, bits8_offset,
                                              bitfield_size, m);
                } else {
-                       bytes_offset = BITS_ROUNDDOWN_BYTES(member_offset);
-                       bits8_offset = BITS_PER_BYTE_MASKED(member_offset);
                        ops = btf_type_ops(member_type);
                        ops->seq_show(btf, member_type, member->type,
                                      data + bytes_offset, bits8_offset, m);
index 9425c2f..d17d055 100644 (file)
@@ -572,7 +572,7 @@ int __cgroup_bpf_run_filter_skb(struct sock *sk,
        bpf_compute_and_save_data_end(skb, &saved_data_end);
 
        ret = BPF_PROG_RUN_ARRAY(cgrp->bpf.effective[type], skb,
-                                bpf_prog_run_save_cb);
+                                __bpf_prog_run_save_cb);
        bpf_restore_data_end(skb, saved_data_end);
        __skb_pull(skb, offset);
        skb->sk = save_sk;
@@ -718,6 +718,7 @@ cgroup_dev_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
        case BPF_FUNC_trace_printk:
                if (capable(CAP_SYS_ADMIN))
                        return bpf_get_trace_printk_proto();
+               /* fall through */
        default:
                return NULL;
        }
index 4b7c767..f927411 100644 (file)
@@ -686,7 +686,7 @@ static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l)
        }
 
        if (htab_is_prealloc(htab)) {
-               pcpu_freelist_push(&htab->freelist, &l->fnode);
+               __pcpu_freelist_push(&htab->freelist, &l->fnode);
        } else {
                atomic_dec(&htab->count);
                l->htab = htab;
@@ -748,7 +748,7 @@ static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key,
                } else {
                        struct pcpu_freelist_node *l;
 
-                       l = pcpu_freelist_pop(&htab->freelist);
+                       l = __pcpu_freelist_pop(&htab->freelist);
                        if (!l)
                                return ERR_PTR(-E2BIG);
                        l_new = container_of(l, struct htab_elem, fnode);
index 99d243e..52378d3 100644 (file)
@@ -12,6 +12,7 @@
 struct bpf_map *bpf_map_meta_alloc(int inner_map_ufd)
 {
        struct bpf_map *inner_map, *inner_map_meta;
+       u32 inner_map_meta_size;
        struct fd f;
 
        f = fdget(inner_map_ufd);
@@ -36,7 +37,12 @@ struct bpf_map *bpf_map_meta_alloc(int inner_map_ufd)
                return ERR_PTR(-EINVAL);
        }
 
-       inner_map_meta = kzalloc(sizeof(*inner_map_meta), GFP_USER);
+       inner_map_meta_size = sizeof(*inner_map_meta);
+       /* In some cases verifier needs to access beyond just base map. */
+       if (inner_map->ops == &array_map_ops)
+               inner_map_meta_size = sizeof(struct bpf_array);
+
+       inner_map_meta = kzalloc(inner_map_meta_size, GFP_USER);
        if (!inner_map_meta) {
                fdput(f);
                return ERR_PTR(-ENOMEM);
@@ -46,9 +52,16 @@ struct bpf_map *bpf_map_meta_alloc(int inner_map_ufd)
        inner_map_meta->key_size = inner_map->key_size;
        inner_map_meta->value_size = inner_map->value_size;
        inner_map_meta->map_flags = inner_map->map_flags;
-       inner_map_meta->ops = inner_map->ops;
        inner_map_meta->max_entries = inner_map->max_entries;
 
+       /* Misc members not needed in bpf_map_meta_equal() check. */
+       inner_map_meta->ops = inner_map->ops;
+       if (inner_map->ops == &array_map_ops) {
+               inner_map_meta->unpriv_array = inner_map->unpriv_array;
+               container_of(inner_map_meta, struct bpf_array, map)->index_mask =
+                    container_of(inner_map, struct bpf_array, map)->index_mask;
+       }
+
        fdput(f);
        return inner_map_meta;
 }
index 673fa6f..0c1b4ba 100644 (file)
@@ -28,8 +28,8 @@ void pcpu_freelist_destroy(struct pcpu_freelist *s)
        free_percpu(s->freelist);
 }
 
-static inline void __pcpu_freelist_push(struct pcpu_freelist_head *head,
-                                       struct pcpu_freelist_node *node)
+static inline void ___pcpu_freelist_push(struct pcpu_freelist_head *head,
+                                        struct pcpu_freelist_node *node)
 {
        raw_spin_lock(&head->lock);
        node->next = head->first;
@@ -37,12 +37,22 @@ static inline void __pcpu_freelist_push(struct pcpu_freelist_head *head,
        raw_spin_unlock(&head->lock);
 }
 
-void pcpu_freelist_push(struct pcpu_freelist *s,
+void __pcpu_freelist_push(struct pcpu_freelist *s,
                        struct pcpu_freelist_node *node)
 {
        struct pcpu_freelist_head *head = this_cpu_ptr(s->freelist);
 
-       __pcpu_freelist_push(head, node);
+       ___pcpu_freelist_push(head, node);
+}
+
+void pcpu_freelist_push(struct pcpu_freelist *s,
+                       struct pcpu_freelist_node *node)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       __pcpu_freelist_push(s, node);
+       local_irq_restore(flags);
 }
 
 void pcpu_freelist_populate(struct pcpu_freelist *s, void *buf, u32 elem_size,
@@ -63,7 +73,7 @@ void pcpu_freelist_populate(struct pcpu_freelist *s, void *buf, u32 elem_size,
        for_each_possible_cpu(cpu) {
 again:
                head = per_cpu_ptr(s->freelist, cpu);
-               __pcpu_freelist_push(head, buf);
+               ___pcpu_freelist_push(head, buf);
                i++;
                buf += elem_size;
                if (i == nr_elems)
@@ -74,14 +84,12 @@ again:
        local_irq_restore(flags);
 }
 
-struct pcpu_freelist_node *pcpu_freelist_pop(struct pcpu_freelist *s)
+struct pcpu_freelist_node *__pcpu_freelist_pop(struct pcpu_freelist *s)
 {
        struct pcpu_freelist_head *head;
        struct pcpu_freelist_node *node;
-       unsigned long flags;
        int orig_cpu, cpu;
 
-       local_irq_save(flags);
        orig_cpu = cpu = raw_smp_processor_id();
        while (1) {
                head = per_cpu_ptr(s->freelist, cpu);
@@ -89,16 +97,25 @@ struct pcpu_freelist_node *pcpu_freelist_pop(struct pcpu_freelist *s)
                node = head->first;
                if (node) {
                        head->first = node->next;
-                       raw_spin_unlock_irqrestore(&head->lock, flags);
+                       raw_spin_unlock(&head->lock);
                        return node;
                }
                raw_spin_unlock(&head->lock);
                cpu = cpumask_next(cpu, cpu_possible_mask);
                if (cpu >= nr_cpu_ids)
                        cpu = 0;
-               if (cpu == orig_cpu) {
-                       local_irq_restore(flags);
+               if (cpu == orig_cpu)
                        return NULL;
-               }
        }
 }
+
+struct pcpu_freelist_node *pcpu_freelist_pop(struct pcpu_freelist *s)
+{
+       struct pcpu_freelist_node *ret;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       ret = __pcpu_freelist_pop(s);
+       local_irq_restore(flags);
+       return ret;
+}
index 3049aae..c396011 100644 (file)
@@ -22,8 +22,12 @@ struct pcpu_freelist_node {
        struct pcpu_freelist_node *next;
 };
 
+/* pcpu_freelist_* do spin_lock_irqsave. */
 void pcpu_freelist_push(struct pcpu_freelist *, struct pcpu_freelist_node *);
 struct pcpu_freelist_node *pcpu_freelist_pop(struct pcpu_freelist *);
+/* __pcpu_freelist_* do spin_lock only. caller must disable irqs. */
+void __pcpu_freelist_push(struct pcpu_freelist *, struct pcpu_freelist_node *);
+struct pcpu_freelist_node *__pcpu_freelist_pop(struct pcpu_freelist *);
 void pcpu_freelist_populate(struct pcpu_freelist *s, void *buf, u32 elem_size,
                            u32 nr_elems);
 int pcpu_freelist_init(struct pcpu_freelist *);
index 90daf28..d43b145 100644 (file)
@@ -180,11 +180,14 @@ static inline int stack_map_parse_build_id(void *page_addr,
 
                if (nhdr->n_type == BPF_BUILD_ID &&
                    nhdr->n_namesz == sizeof("GNU") &&
-                   nhdr->n_descsz == BPF_BUILD_ID_SIZE) {
+                   nhdr->n_descsz > 0 &&
+                   nhdr->n_descsz <= BPF_BUILD_ID_SIZE) {
                        memcpy(build_id,
                               note_start + note_offs +
                               ALIGN(sizeof("GNU"), 4) + sizeof(Elf32_Nhdr),
-                              BPF_BUILD_ID_SIZE);
+                              nhdr->n_descsz);
+                       memset(build_id + nhdr->n_descsz, 0,
+                              BPF_BUILD_ID_SIZE - nhdr->n_descsz);
                        return 0;
                }
                new_offs = note_offs + sizeof(Elf32_Nhdr) +
@@ -260,7 +263,7 @@ static int stack_map_get_build_id(struct vm_area_struct *vma,
                return -EFAULT; /* page not mapped */
 
        ret = -EINVAL;
-       page_addr = page_address(page);
+       page_addr = kmap_atomic(page);
        ehdr = (Elf32_Ehdr *)page_addr;
 
        /* compare magic x7f "ELF" */
@@ -276,6 +279,7 @@ static int stack_map_get_build_id(struct vm_area_struct *vma,
        else if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
                ret = stack_map_get_build_id_64(page_addr, build_id);
 out:
+       kunmap_atomic(page_addr);
        put_page(page);
        return ret;
 }
@@ -310,6 +314,7 @@ static void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs,
                for (i = 0; i < trace_nr; i++) {
                        id_offs[i].status = BPF_STACK_BUILD_ID_IP;
                        id_offs[i].ip = ips[i];
+                       memset(id_offs[i].build_id, 0, BPF_BUILD_ID_SIZE);
                }
                return;
        }
@@ -320,6 +325,7 @@ static void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs,
                        /* per entry fall back to ips */
                        id_offs[i].status = BPF_STACK_BUILD_ID_IP;
                        id_offs[i].ip = ips[i];
+                       memset(id_offs[i].build_id, 0, BPF_BUILD_ID_SIZE);
                        continue;
                }
                id_offs[i].offset = (vma->vm_pgoff << PAGE_SHIFT) + ips[i]
index b155cd1..8577bb7 100644 (file)
@@ -713,8 +713,13 @@ static int map_lookup_elem(union bpf_attr *attr)
 
        if (bpf_map_is_dev_bound(map)) {
                err = bpf_map_offload_lookup_elem(map, key, value);
-       } else if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
-                  map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
+               goto done;
+       }
+
+       preempt_disable();
+       this_cpu_inc(bpf_prog_active);
+       if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
+           map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
                err = bpf_percpu_hash_copy(map, key, value);
        } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
                err = bpf_percpu_array_copy(map, key, value);
@@ -744,7 +749,10 @@ static int map_lookup_elem(union bpf_attr *attr)
                }
                rcu_read_unlock();
        }
+       this_cpu_dec(bpf_prog_active);
+       preempt_enable();
 
+done:
        if (err)
                goto free_value;
 
index f6bc62a..56674a7 100644 (file)
@@ -3103,6 +3103,40 @@ static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg,
        }
 }
 
+static bool can_skip_alu_sanitation(const struct bpf_verifier_env *env,
+                                   const struct bpf_insn *insn)
+{
+       return env->allow_ptr_leaks || BPF_SRC(insn->code) == BPF_K;
+}
+
+static int update_alu_sanitation_state(struct bpf_insn_aux_data *aux,
+                                      u32 alu_state, u32 alu_limit)
+{
+       /* If we arrived here from different branches with different
+        * state or limits to sanitize, then this won't work.
+        */
+       if (aux->alu_state &&
+           (aux->alu_state != alu_state ||
+            aux->alu_limit != alu_limit))
+               return -EACCES;
+
+       /* Corresponding fixup done in fixup_bpf_calls(). */
+       aux->alu_state = alu_state;
+       aux->alu_limit = alu_limit;
+       return 0;
+}
+
+static int sanitize_val_alu(struct bpf_verifier_env *env,
+                           struct bpf_insn *insn)
+{
+       struct bpf_insn_aux_data *aux = cur_aux(env);
+
+       if (can_skip_alu_sanitation(env, insn))
+               return 0;
+
+       return update_alu_sanitation_state(aux, BPF_ALU_NON_POINTER, 0);
+}
+
 static int sanitize_ptr_alu(struct bpf_verifier_env *env,
                            struct bpf_insn *insn,
                            const struct bpf_reg_state *ptr_reg,
@@ -3117,7 +3151,7 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
        struct bpf_reg_state tmp;
        bool ret;
 
-       if (env->allow_ptr_leaks || BPF_SRC(insn->code) == BPF_K)
+       if (can_skip_alu_sanitation(env, insn))
                return 0;
 
        /* We already marked aux for masking from non-speculative
@@ -3133,19 +3167,8 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
 
        if (retrieve_ptr_limit(ptr_reg, &alu_limit, opcode, off_is_neg))
                return 0;
-
-       /* If we arrived here from different branches with different
-        * limits to sanitize, then this won't work.
-        */
-       if (aux->alu_state &&
-           (aux->alu_state != alu_state ||
-            aux->alu_limit != alu_limit))
+       if (update_alu_sanitation_state(aux, alu_state, alu_limit))
                return -EACCES;
-
-       /* Corresponding fixup done in fixup_bpf_calls(). */
-       aux->alu_state = alu_state;
-       aux->alu_limit = alu_limit;
-
 do_sim:
        /* Simulate and find potential out-of-bounds access under
         * speculative execution from truncation as a result of
@@ -3418,6 +3441,8 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
        s64 smin_val, smax_val;
        u64 umin_val, umax_val;
        u64 insn_bitness = (BPF_CLASS(insn->code) == BPF_ALU64) ? 64 : 32;
+       u32 dst = insn->dst_reg;
+       int ret;
 
        if (insn_bitness == 32) {
                /* Relevant for 32-bit RSH: Information can propagate towards
@@ -3452,6 +3477,11 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
 
        switch (opcode) {
        case BPF_ADD:
+               ret = sanitize_val_alu(env, insn);
+               if (ret < 0) {
+                       verbose(env, "R%d tried to add from different pointers or scalars\n", dst);
+                       return ret;
+               }
                if (signed_add_overflows(dst_reg->smin_value, smin_val) ||
                    signed_add_overflows(dst_reg->smax_value, smax_val)) {
                        dst_reg->smin_value = S64_MIN;
@@ -3471,6 +3501,11 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
                dst_reg->var_off = tnum_add(dst_reg->var_off, src_reg.var_off);
                break;
        case BPF_SUB:
+               ret = sanitize_val_alu(env, insn);
+               if (ret < 0) {
+                       verbose(env, "R%d tried to sub from different pointers or scalars\n", dst);
+                       return ret;
+               }
                if (signed_sub_overflows(dst_reg->smin_value, smax_val) ||
                    signed_sub_overflows(dst_reg->smax_value, smin_val)) {
                        /* Overflow possible, we know nothing */
index 91d5c38..d1c6d15 100644 (file)
@@ -376,9 +376,6 @@ void __weak arch_smt_update(void) { }
 
 #ifdef CONFIG_HOTPLUG_SMT
 enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED;
-EXPORT_SYMBOL_GPL(cpu_smt_control);
-
-static bool cpu_smt_available __read_mostly;
 
 void __init cpu_smt_disable(bool force)
 {
@@ -397,25 +394,11 @@ void __init cpu_smt_disable(bool force)
 
 /*
  * The decision whether SMT is supported can only be done after the full
- * CPU identification. Called from architecture code before non boot CPUs
- * are brought up.
- */
-void __init cpu_smt_check_topology_early(void)
-{
-       if (!topology_smt_supported())
-               cpu_smt_control = CPU_SMT_NOT_SUPPORTED;
-}
-
-/*
- * If SMT was disabled by BIOS, detect it here, after the CPUs have been
- * brought online. This ensures the smt/l1tf sysfs entries are consistent
- * with reality. cpu_smt_available is set to true during the bringup of non
- * boot CPUs when a SMT sibling is detected. Note, this may overwrite
- * cpu_smt_control's previous setting.
+ * CPU identification. Called from architecture code.
  */
 void __init cpu_smt_check_topology(void)
 {
-       if (!cpu_smt_available)
+       if (!topology_smt_supported())
                cpu_smt_control = CPU_SMT_NOT_SUPPORTED;
 }
 
@@ -428,18 +411,10 @@ early_param("nosmt", smt_cmdline_disable);
 
 static inline bool cpu_smt_allowed(unsigned int cpu)
 {
-       if (topology_is_primary_thread(cpu))
+       if (cpu_smt_control == CPU_SMT_ENABLED)
                return true;
 
-       /*
-        * If the CPU is not a 'primary' thread and the booted_once bit is
-        * set then the processor has SMT support. Store this information
-        * for the late check of SMT support in cpu_smt_check_topology().
-        */
-       if (per_cpu(cpuhp_state, cpu).booted_once)
-               cpu_smt_available = true;
-
-       if (cpu_smt_control == CPU_SMT_ENABLED)
+       if (topology_is_primary_thread(cpu))
                return true;
 
        /*
@@ -2090,10 +2065,8 @@ static int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval)
                 */
                cpuhp_offline_cpu_device(cpu);
        }
-       if (!ret) {
+       if (!ret)
                cpu_smt_control = ctrlval;
-               arch_smt_update();
-       }
        cpu_maps_update_done();
        return ret;
 }
@@ -2104,7 +2077,6 @@ static int cpuhp_smt_enable(void)
 
        cpu_maps_update_begin();
        cpu_smt_control = CPU_SMT_ENABLED;
-       arch_smt_update();
        for_each_present_cpu(cpu) {
                /* Skip online CPUs and CPUs on offline nodes */
                if (cpu_online(cpu) || !node_online(cpu_to_node(cpu)))
index d636177..1fb6fd6 100644 (file)
@@ -378,6 +378,8 @@ void __init swiotlb_exit(void)
                memblock_free_late(io_tlb_start,
                                   PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT));
        }
+       io_tlb_start = 0;
+       io_tlb_end = 0;
        io_tlb_nslabs = 0;
        max_segment = 0;
 }
index 3cd13a3..26d6eda 100644 (file)
@@ -436,18 +436,18 @@ int perf_proc_update_handler(struct ctl_table *table, int write,
                void __user *buffer, size_t *lenp,
                loff_t *ppos)
 {
-       int ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
-
-       if (ret || !write)
-               return ret;
-
+       int ret;
+       int perf_cpu = sysctl_perf_cpu_time_max_percent;
        /*
         * If throttling is disabled don't allow the write:
         */
-       if (sysctl_perf_cpu_time_max_percent == 100 ||
-           sysctl_perf_cpu_time_max_percent == 0)
+       if (write && (perf_cpu == 100 || perf_cpu == 0))
                return -EINVAL;
 
+       ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+       if (ret || !write)
+               return ret;
+
        max_samples_per_tick = DIV_ROUND_UP(sysctl_perf_event_sample_rate, HZ);
        perf_sample_period_ns = NSEC_PER_SEC / sysctl_perf_event_sample_rate;
        update_perf_cpu_limits();
@@ -4963,6 +4963,11 @@ static void __perf_event_period(struct perf_event *event,
        }
 }
 
+static int perf_event_check_period(struct perf_event *event, u64 value)
+{
+       return event->pmu->check_period(event, value);
+}
+
 static int perf_event_period(struct perf_event *event, u64 __user *arg)
 {
        u64 value;
@@ -4979,6 +4984,9 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg)
        if (event->attr.freq && value > sysctl_perf_event_sample_rate)
                return -EINVAL;
 
+       if (perf_event_check_period(event, value))
+               return -EINVAL;
+
        event_function_call(event, __perf_event_period, &value);
 
        return 0;
@@ -9391,6 +9399,11 @@ static int perf_pmu_nop_int(struct pmu *pmu)
        return 0;
 }
 
+static int perf_event_nop_int(struct perf_event *event, u64 value)
+{
+       return 0;
+}
+
 static DEFINE_PER_CPU(unsigned int, nop_txn_flags);
 
 static void perf_pmu_start_txn(struct pmu *pmu, unsigned int flags)
@@ -9691,6 +9704,9 @@ got_cpu_context:
                pmu->pmu_disable = perf_pmu_nop_void;
        }
 
+       if (!pmu->check_period)
+               pmu->check_period = perf_event_nop_int;
+
        if (!pmu->event_idx)
                pmu->event_idx = perf_event_idx_default;
 
index 4a99370..5ab4fe3 100644 (file)
@@ -734,6 +734,9 @@ struct ring_buffer *rb_alloc(int nr_pages, long watermark, int cpu, int flags)
        size = sizeof(struct ring_buffer);
        size += nr_pages * sizeof(void *);
 
+       if (order_base_2(size) >= PAGE_SHIFT+MAX_ORDER)
+               goto fail;
+
        rb = kzalloc(size, GFP_KERNEL);
        if (!rb)
                goto fail;
index 2d14979..2639a30 100644 (file)
@@ -307,7 +307,7 @@ void rcuwait_wake_up(struct rcuwait *w)
         *        MB (A)              MB (B)
         *    [L] cond            [L] tsk
         */
-       smp_rmb(); /* (B) */
+       smp_mb(); /* (B) */
 
        /*
         * Avoid using task_rcu_dereference() magic as long as we are careful,
@@ -558,12 +558,14 @@ static struct task_struct *find_alive_thread(struct task_struct *p)
        return NULL;
 }
 
-static struct task_struct *find_child_reaper(struct task_struct *father)
+static struct task_struct *find_child_reaper(struct task_struct *father,
+                                               struct list_head *dead)
        __releases(&tasklist_lock)
        __acquires(&tasklist_lock)
 {
        struct pid_namespace *pid_ns = task_active_pid_ns(father);
        struct task_struct *reaper = pid_ns->child_reaper;
+       struct task_struct *p, *n;
 
        if (likely(reaper != father))
                return reaper;
@@ -579,6 +581,12 @@ static struct task_struct *find_child_reaper(struct task_struct *father)
                panic("Attempted to kill init! exitcode=0x%08x\n",
                        father->signal->group_exit_code ?: father->exit_code);
        }
+
+       list_for_each_entry_safe(p, n, dead, ptrace_entry) {
+               list_del_init(&p->ptrace_entry);
+               release_task(p);
+       }
+
        zap_pid_ns_processes(pid_ns);
        write_lock_irq(&tasklist_lock);
 
@@ -668,7 +676,7 @@ static void forget_original_parent(struct task_struct *father,
                exit_ptrace(father, dead);
 
        /* Can drop and reacquire tasklist_lock */
-       reaper = find_child_reaper(father);
+       reaper = find_child_reaper(father, dead);
        if (list_empty(&father->children))
                return;
 
@@ -866,6 +874,7 @@ void __noreturn do_exit(long code)
        exit_task_namespaces(tsk);
        exit_task_work(tsk);
        exit_thread(tsk);
+       exit_umh(tsk);
 
        /*
         * Flush inherited counters to the parent - before the parent
index a604599..b69248e 100644 (file)
@@ -217,6 +217,7 @@ static unsigned long *alloc_thread_stack_node(struct task_struct *tsk, int node)
                memset(s->addr, 0, THREAD_SIZE);
 
                tsk->stack_vm_area = s;
+               tsk->stack = s->addr;
                return s->addr;
        }
 
@@ -1833,8 +1834,6 @@ static __latent_entropy struct task_struct *copy_process(
 
        posix_cpu_timers_init(p);
 
-       p->start_time = ktime_get_ns();
-       p->real_start_time = ktime_get_boot_ns();
        p->io_context = NULL;
        audit_set_context(p, NULL);
        cgroup_fork(p);
@@ -2001,6 +2000,17 @@ static __latent_entropy struct task_struct *copy_process(
                goto bad_fork_free_pid;
 
        /*
+        * From this point on we must avoid any synchronous user-space
+        * communication until we take the tasklist-lock. In particular, we do
+        * not want user-space to be able to predict the process start-time by
+        * stalling fork(2) after we recorded the start_time but before it is
+        * visible to the system.
+        */
+
+       p->start_time = ktime_get_ns();
+       p->real_start_time = ktime_get_boot_ns();
+
+       /*
         * Make it visible to the rest of the system, but dont wake it up yet.
         * Need tasklist lock for parent etc handling!
         */
index be3bff2..a0514e0 100644 (file)
@@ -1452,11 +1452,7 @@ static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q)
        if (WARN(q->pi_state || q->rt_waiter, "refusing to wake PI futex\n"))
                return;
 
-       /*
-        * Queue the task for later wakeup for after we've released
-        * the hb->lock. wake_q_add() grabs reference to p.
-        */
-       wake_q_add(wake_q, p);
+       get_task_struct(p);
        __unqueue_futex(q);
        /*
         * The waiting task can free the futex_q as soon as q->lock_ptr = NULL
@@ -1466,6 +1462,13 @@ static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q)
         * plist_del in __unqueue_futex().
         */
        smp_store_release(&q->lock_ptr, NULL);
+
+       /*
+        * Queue the task for later wakeup for after we've released
+        * the hb->lock. wake_q_add() grabs reference to p.
+        */
+       wake_q_add(wake_q, p);
+       put_task_struct(p);
 }
 
 /*
@@ -2218,11 +2221,11 @@ static inline struct futex_hash_bucket *queue_lock(struct futex_q *q)
         * decrement the counter at queue_unlock() when some error has
         * occurred and we don't end up adding the task to the list.
         */
-       hb_waiters_inc(hb);
+       hb_waiters_inc(hb); /* implies smp_mb(); (A) */
 
        q->lock_ptr = &hb->lock;
 
-       spin_lock(&hb->lock); /* implies smp_mb(); (A) */
+       spin_lock(&hb->lock);
        return hb;
 }
 
@@ -2858,35 +2861,39 @@ retry_private:
         * and BUG when futex_unlock_pi() interleaves with this.
         *
         * Therefore acquire wait_lock while holding hb->lock, but drop the
-        * latter before calling rt_mutex_start_proxy_lock(). This still fully
-        * serializes against futex_unlock_pi() as that does the exact same
-        * lock handoff sequence.
+        * latter before calling __rt_mutex_start_proxy_lock(). This
+        * interleaves with futex_unlock_pi() -- which does a similar lock
+        * handoff -- such that the latter can observe the futex_q::pi_state
+        * before __rt_mutex_start_proxy_lock() is done.
         */
        raw_spin_lock_irq(&q.pi_state->pi_mutex.wait_lock);
        spin_unlock(q.lock_ptr);
+       /*
+        * __rt_mutex_start_proxy_lock() unconditionally enqueues the @rt_waiter
+        * such that futex_unlock_pi() is guaranteed to observe the waiter when
+        * it sees the futex_q::pi_state.
+        */
        ret = __rt_mutex_start_proxy_lock(&q.pi_state->pi_mutex, &rt_waiter, current);
        raw_spin_unlock_irq(&q.pi_state->pi_mutex.wait_lock);
 
        if (ret) {
                if (ret == 1)
                        ret = 0;
-
-               spin_lock(q.lock_ptr);
-               goto no_block;
+               goto cleanup;
        }
 
-
        if (unlikely(to))
                hrtimer_start_expires(&to->timer, HRTIMER_MODE_ABS);
 
        ret = rt_mutex_wait_proxy_lock(&q.pi_state->pi_mutex, to, &rt_waiter);
 
+cleanup:
        spin_lock(q.lock_ptr);
        /*
-        * If we failed to acquire the lock (signal/timeout), we must
+        * If we failed to acquire the lock (deadlock/signal/timeout), we must
         * first acquire the hb->lock before removing the lock from the
-        * rt_mutex waitqueue, such that we can keep the hb and rt_mutex
-        * wait lists consistent.
+        * rt_mutex waitqueue, such that we can keep the hb and rt_mutex wait
+        * lists consistent.
         *
         * In particular; it is important that futex_unlock_pi() can not
         * observe this inconsistency.
@@ -3010,6 +3017,10 @@ retry:
                 * there is no point where we hold neither; and therefore
                 * wake_futex_pi() must observe a state consistent with what we
                 * observed.
+                *
+                * In particular; this forces __rt_mutex_start_proxy() to
+                * complete such that we're guaranteed to observe the
+                * rt_waiter. Also see the WARN in wake_futex_pi().
                 */
                raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
                spin_unlock(&hb->lock);
index ee062b7..ef8ad36 100644 (file)
@@ -457,7 +457,7 @@ static int alloc_descs(unsigned int start, unsigned int cnt, int node,
 
        /* Validate affinity mask(s) */
        if (affinity) {
-               for (i = 0; i < cnt; i++, i++) {
+               for (i = 0; i < cnt; i++) {
                        if (cpumask_empty(&affinity[i].mask))
                                return -EINVAL;
                }
index a4888ce..84b54a1 100644 (file)
@@ -393,6 +393,9 @@ int irq_setup_affinity(struct irq_desc *desc)
        }
 
        cpumask_and(&mask, cpu_online_mask, set);
+       if (cpumask_empty(&mask))
+               cpumask_copy(&mask, cpu_online_mask);
+
        if (node != NUMA_NO_NODE) {
                const struct cpumask *nodemask = cpumask_of_node(node);
 
index 581edcc..978d63a 100644 (file)
@@ -1726,12 +1726,33 @@ void rt_mutex_proxy_unlock(struct rt_mutex *lock,
        rt_mutex_set_owner(lock, NULL);
 }
 
+/**
+ * __rt_mutex_start_proxy_lock() - Start lock acquisition for another task
+ * @lock:              the rt_mutex to take
+ * @waiter:            the pre-initialized rt_mutex_waiter
+ * @task:              the task to prepare
+ *
+ * Starts the rt_mutex acquire; it enqueues the @waiter and does deadlock
+ * detection. It does not wait, see rt_mutex_wait_proxy_lock() for that.
+ *
+ * NOTE: does _NOT_ remove the @waiter on failure; must either call
+ * rt_mutex_wait_proxy_lock() or rt_mutex_cleanup_proxy_lock() after this.
+ *
+ * Returns:
+ *  0 - task blocked on lock
+ *  1 - acquired the lock for task, caller should wake it up
+ * <0 - error
+ *
+ * Special API call for PI-futex support.
+ */
 int __rt_mutex_start_proxy_lock(struct rt_mutex *lock,
                              struct rt_mutex_waiter *waiter,
                              struct task_struct *task)
 {
        int ret;
 
+       lockdep_assert_held(&lock->wait_lock);
+
        if (try_to_take_rt_mutex(lock, task, NULL))
                return 1;
 
@@ -1749,9 +1770,6 @@ int __rt_mutex_start_proxy_lock(struct rt_mutex *lock,
                ret = 0;
        }
 
-       if (unlikely(ret))
-               remove_waiter(lock, waiter);
-
        debug_rt_mutex_print_deadlock(waiter);
 
        return ret;
@@ -1763,12 +1781,18 @@ int __rt_mutex_start_proxy_lock(struct rt_mutex *lock,
  * @waiter:            the pre-initialized rt_mutex_waiter
  * @task:              the task to prepare
  *
+ * Starts the rt_mutex acquire; it enqueues the @waiter and does deadlock
+ * detection. It does not wait, see rt_mutex_wait_proxy_lock() for that.
+ *
+ * NOTE: unlike __rt_mutex_start_proxy_lock this _DOES_ remove the @waiter
+ * on failure.
+ *
  * Returns:
  *  0 - task blocked on lock
  *  1 - acquired the lock for task, caller should wake it up
  * <0 - error
  *
- * Special API call for FUTEX_REQUEUE_PI support.
+ * Special API call for PI-futex support.
  */
 int rt_mutex_start_proxy_lock(struct rt_mutex *lock,
                              struct rt_mutex_waiter *waiter,
@@ -1778,6 +1802,8 @@ int rt_mutex_start_proxy_lock(struct rt_mutex *lock,
 
        raw_spin_lock_irq(&lock->wait_lock);
        ret = __rt_mutex_start_proxy_lock(lock, waiter, task);
+       if (unlikely(ret))
+               remove_waiter(lock, waiter);
        raw_spin_unlock_irq(&lock->wait_lock);
 
        return ret;
@@ -1845,7 +1871,8 @@ int rt_mutex_wait_proxy_lock(struct rt_mutex *lock,
  * @lock:              the rt_mutex we were woken on
  * @waiter:            the pre-initialized rt_mutex_waiter
  *
- * Attempt to clean up after a failed rt_mutex_wait_proxy_lock().
+ * Attempt to clean up after a failed __rt_mutex_start_proxy_lock() or
+ * rt_mutex_wait_proxy_lock().
  *
  * Unless we acquired the lock; we're still enqueued on the wait-list and can
  * in fact still be granted ownership until we're removed. Therefore we can
index 09b1800..50d9af6 100644 (file)
@@ -198,15 +198,22 @@ static void __rwsem_mark_wake(struct rw_semaphore *sem,
                woken++;
                tsk = waiter->task;
 
-               wake_q_add(wake_q, tsk);
+               get_task_struct(tsk);
                list_del(&waiter->list);
                /*
-                * Ensure that the last operation is setting the reader
+                * Ensure calling get_task_struct() before setting the reader
                 * waiter to nil such that rwsem_down_read_failed() cannot
                 * race with do_exit() by always holding a reference count
                 * to the task to wakeup.
                 */
                smp_store_release(&waiter->task, NULL);
+               /*
+                * Ensure issuing the wakeup (either by us or someone else)
+                * after setting the reader waiter to nil.
+                */
+               wake_q_add(wake_q, tsk);
+               /* wake_q_add() already take the task ref */
+               put_task_struct(tsk);
        }
 
        adjustment = woken * RWSEM_ACTIVE_READ_BIAS - adjustment;
index 04f2486..9e0f523 100644 (file)
@@ -428,6 +428,8 @@ static struct dentry *relay_create_buf_file(struct rchan *chan,
        dentry = chan->cb->create_buf_file(tmpname, chan->parent,
                                           S_IRUSR, buf,
                                           &chan->is_global);
+       if (IS_ERR(dentry))
+               dentry = NULL;
 
        kfree(tmpname);
 
@@ -461,7 +463,7 @@ static struct rchan_buf *relay_open_buf(struct rchan *chan, unsigned int cpu)
                dentry = chan->cb->create_buf_file(NULL, NULL,
                                                   S_IRUSR, buf,
                                                   &chan->is_global);
-               if (WARN_ON(dentry))
+               if (IS_ERR_OR_NULL(dentry))
                        goto free_buf;
        }
 
index a674c7d..d8d76a6 100644 (file)
@@ -396,6 +396,18 @@ static bool set_nr_if_polling(struct task_struct *p)
 #endif
 #endif
 
+/**
+ * wake_q_add() - queue a wakeup for 'later' waking.
+ * @head: the wake_q_head to add @task to
+ * @task: the task to queue for 'later' wakeup
+ *
+ * Queue a task for later wakeup, most likely by the wake_up_q() call in the
+ * same context, _HOWEVER_ this is not guaranteed, the wakeup can come
+ * instantly.
+ *
+ * This function must be used as-if it were wake_up_process(); IOW the task
+ * must be ready to be woken at this location.
+ */
 void wake_q_add(struct wake_q_head *head, struct task_struct *task)
 {
        struct wake_q_node *node = &task->wake_q;
@@ -405,10 +417,11 @@ void wake_q_add(struct wake_q_head *head, struct task_struct *task)
         * its already queued (either by us or someone else) and will get the
         * wakeup due to that.
         *
-        * This cmpxchg() executes a full barrier, which pairs with the full
-        * barrier executed by the wakeup in wake_up_q().
+        * In order to ensure that a pending wakeup will observe our pending
+        * state, even in the failed case, an explicit smp_mb() must be used.
         */
-       if (cmpxchg(&node->next, NULL, WAKE_Q_TAIL))
+       smp_mb__before_atomic();
+       if (cmpxchg_relaxed(&node->next, NULL, WAKE_Q_TAIL))
                return;
 
        get_task_struct(task);
index 50aa2ab..310d063 100644 (file)
@@ -5980,6 +5980,7 @@ static inline int find_idlest_cpu(struct sched_domain *sd, struct task_struct *p
 
 #ifdef CONFIG_SCHED_SMT
 DEFINE_STATIC_KEY_FALSE(sched_smt_present);
+EXPORT_SYMBOL_GPL(sched_smt_present);
 
 static inline void set_idle_cores(int cpu, int val)
 {
index fe24de3..c348478 100644 (file)
  * sampling of the aggregate task states would be.
  */
 
+#include "../workqueue_internal.h"
 #include <linux/sched/loadavg.h>
 #include <linux/seq_file.h>
 #include <linux/proc_fs.h>
@@ -480,9 +481,6 @@ static void psi_group_change(struct psi_group *group, int cpu,
                        groupc->tasks[t]++;
 
        write_seqcount_end(&groupc->seq);
-
-       if (!delayed_work_pending(&group->clock_work))
-               schedule_delayed_work(&group->clock_work, PSI_FREQ);
 }
 
 static struct psi_group *iterate_groups(struct task_struct *task, void **iter)
@@ -513,6 +511,7 @@ void psi_task_change(struct task_struct *task, int clear, int set)
 {
        int cpu = task_cpu(task);
        struct psi_group *group;
+       bool wake_clock = true;
        void *iter = NULL;
 
        if (!task->pid)
@@ -530,8 +529,22 @@ void psi_task_change(struct task_struct *task, int clear, int set)
        task->psi_flags &= ~clear;
        task->psi_flags |= set;
 
-       while ((group = iterate_groups(task, &iter)))
+       /*
+        * Periodic aggregation shuts off if there is a period of no
+        * task changes, so we wake it back up if necessary. However,
+        * don't do this if the task change is the aggregation worker
+        * itself going to sleep, or we'll ping-pong forever.
+        */
+       if (unlikely((clear & TSK_RUNNING) &&
+                    (task->flags & PF_WQ_WORKER) &&
+                    wq_worker_last_func(task) == psi_update_work))
+               wake_clock = false;
+
+       while ((group = iterate_groups(task, &iter))) {
                psi_group_change(group, cpu, clear, set);
+               if (wake_clock && !delayed_work_pending(&group->clock_work))
+                       schedule_delayed_work(&group->clock_work, PSI_FREQ);
+       }
 }
 
 void psi_memstall_tick(struct task_struct *task, int cpu)
index d7f5388..e815781 100644 (file)
@@ -976,6 +976,9 @@ static int seccomp_notify_release(struct inode *inode, struct file *file)
        struct seccomp_filter *filter = file->private_data;
        struct seccomp_knotif *knotif;
 
+       if (!filter)
+               return 0;
+
        mutex_lock(&filter->notify_lock);
 
        /*
@@ -1300,6 +1303,7 @@ out:
 out_put_fd:
        if (flags & SECCOMP_FILTER_FLAG_NEW_LISTENER) {
                if (ret < 0) {
+                       listener_f->private_data = NULL;
                        fput(listener_f);
                        put_unused_fd(listener);
                } else {
index e1d7ad8..57b7771 100644 (file)
@@ -688,6 +688,48 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, kernel_siginfo_t *in
 }
 EXPORT_SYMBOL_GPL(dequeue_signal);
 
+static int dequeue_synchronous_signal(kernel_siginfo_t *info)
+{
+       struct task_struct *tsk = current;
+       struct sigpending *pending = &tsk->pending;
+       struct sigqueue *q, *sync = NULL;
+
+       /*
+        * Might a synchronous signal be in the queue?
+        */
+       if (!((pending->signal.sig[0] & ~tsk->blocked.sig[0]) & SYNCHRONOUS_MASK))
+               return 0;
+
+       /*
+        * Return the first synchronous signal in the queue.
+        */
+       list_for_each_entry(q, &pending->list, list) {
+               /* Synchronous signals have a postive si_code */
+               if ((q->info.si_code > SI_USER) &&
+                   (sigmask(q->info.si_signo) & SYNCHRONOUS_MASK)) {
+                       sync = q;
+                       goto next;
+               }
+       }
+       return 0;
+next:
+       /*
+        * Check if there is another siginfo for the same signal.
+        */
+       list_for_each_entry_continue(q, &pending->list, list) {
+               if (q->info.si_signo == sync->info.si_signo)
+                       goto still_pending;
+       }
+
+       sigdelset(&pending->signal, sync->info.si_signo);
+       recalc_sigpending();
+still_pending:
+       list_del_init(&sync->list);
+       copy_siginfo(info, &sync->info);
+       __sigqueue_free(sync);
+       return info->si_signo;
+}
+
 /*
  * Tell a process that it has a new active signal..
  *
@@ -1057,10 +1099,9 @@ static int __send_signal(int sig, struct kernel_siginfo *info, struct task_struc
 
        result = TRACE_SIGNAL_DELIVERED;
        /*
-        * Skip useless siginfo allocation for SIGKILL SIGSTOP,
-        * and kernel threads.
+        * Skip useless siginfo allocation for SIGKILL and kernel threads.
         */
-       if (sig_kernel_only(sig) || (t->flags & PF_KTHREAD))
+       if ((sig == SIGKILL) || (t->flags & PF_KTHREAD))
                goto out_set;
 
        /*
@@ -2394,6 +2435,14 @@ relock:
                goto relock;
        }
 
+       /* Has this task already been marked for death? */
+       if (signal_group_exit(signal)) {
+               ksig->info.si_signo = signr = SIGKILL;
+               sigdelset(&current->pending.signal, SIGKILL);
+               recalc_sigpending();
+               goto fatal;
+       }
+
        for (;;) {
                struct k_sigaction *ka;
 
@@ -2407,7 +2456,15 @@ relock:
                        goto relock;
                }
 
-               signr = dequeue_signal(current, &current->blocked, &ksig->info);
+               /*
+                * Signals generated by the execution of an instruction
+                * need to be delivered before any other pending signals
+                * so that the instruction pointer in the signal stack
+                * frame points to the faulting instruction.
+                */
+               signr = dequeue_synchronous_signal(&ksig->info);
+               if (!signr)
+                       signr = dequeue_signal(current, &current->blocked, &ksig->info);
 
                if (!signr)
                        break; /* will return 0 */
@@ -2489,6 +2546,7 @@ relock:
                        continue;
                }
 
+       fatal:
                spin_unlock_irq(&sighand->siglock);
 
                /*
index 163c451..f4cf1b0 100644 (file)
@@ -584,8 +584,6 @@ void __init smp_init(void)
                num_nodes, (num_nodes > 1 ? "s" : ""),
                num_cpus,  (num_cpus  > 1 ? "s" : ""));
 
-       /* Final decision about SMT support */
-       cpu_smt_check_topology();
        /* Any cleanup work */
        smp_cpus_done(setup_max_cpus);
 }
index a48cbf1..f7eb62e 100644 (file)
@@ -1207,7 +1207,8 @@ DECLARE_RWSEM(uts_sem);
 /*
  * Work around broken programs that cannot handle "Linux 3.0".
  * Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40
- * And we map 4.x to 2.6.60+x, so 4.0 would be 2.6.60.
+ * And we map 4.x and later versions to 2.6.60+x, so 4.0/5.0/6.0/... would be
+ * 2.6.60.
  */
 static int override_release(char __user *release, size_t len)
 {
index 8f0644a..80f9552 100644 (file)
@@ -685,6 +685,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
         * set up the signal and overrun bookkeeping.
         */
        timer->it.cpu.incr = timespec64_to_ns(&new->it_interval);
+       timer->it_interval = ns_to_ktime(timer->it.cpu.incr);
 
        /*
         * This acts as a modification timestamp for the timer,
index 8b068ad..f1a86a0 100644 (file)
@@ -1204,22 +1204,12 @@ static int __bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *
 
 int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *prog)
 {
-       int err;
-
-       mutex_lock(&bpf_event_mutex);
-       err = __bpf_probe_register(btp, prog);
-       mutex_unlock(&bpf_event_mutex);
-       return err;
+       return __bpf_probe_register(btp, prog);
 }
 
 int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_prog *prog)
 {
-       int err;
-
-       mutex_lock(&bpf_event_mutex);
-       err = tracepoint_probe_unregister(btp->tp, (void *)btp->bpf_func, prog);
-       mutex_unlock(&bpf_event_mutex);
-       return err;
+       return tracepoint_probe_unregister(btp->tp, (void *)btp->bpf_func, prog);
 }
 
 int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,
index 5c19b8c..d5fb09e 100644 (file)
@@ -607,11 +607,17 @@ static int trace_kprobe_create(int argc, const char *argv[])
        char buf[MAX_EVENT_NAME_LEN];
        unsigned int flags = TPARG_FL_KERNEL;
 
-       /* argc must be >= 1 */
-       if (argv[0][0] == 'r') {
+       switch (argv[0][0]) {
+       case 'r':
                is_return = true;
                flags |= TPARG_FL_RETURN;
-       } else if (argv[0][0] != 'p' || argc < 2)
+               break;
+       case 'p':
+               break;
+       default:
+               return -ECANCELED;
+       }
+       if (argc < 2)
                return -ECANCELED;
 
        event = strchr(&argv[0][1], ':');
index 5c56afc..4737bb8 100644 (file)
@@ -180,10 +180,12 @@ store_trace_args(void *data, struct trace_probe *tp, struct pt_regs *regs,
                if (unlikely(arg->dynamic))
                        *dl = make_data_loc(maxlen, dyndata - base);
                ret = process_fetch_insn(arg->code, regs, dl, base);
-               if (unlikely(ret < 0 && arg->dynamic))
+               if (unlikely(ret < 0 && arg->dynamic)) {
                        *dl = make_data_loc(0, dyndata - base);
-               else
+               } else {
                        dyndata += ret;
+                       maxlen -= ret;
+               }
        }
 }
 
index e335576..9bde07c 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright (C) IBM Corporation, 2010-2012
  * Author:     Srikar Dronamraju <srikar@linux.vnet.ibm.com>
  */
-#define pr_fmt(fmt)    "trace_kprobe: " fmt
+#define pr_fmt(fmt)    "trace_uprobe: " fmt
 
 #include <linux/ctype.h>
 #include <linux/module.h>
@@ -160,6 +160,13 @@ fetch_store_string(unsigned long addr, void *dest, void *base)
        if (ret >= 0) {
                if (ret == maxlen)
                        dst[ret - 1] = '\0';
+               else
+                       /*
+                        * Include the terminating null byte. In this case it
+                        * was copied by strncpy_from_user but not accounted
+                        * for in ret.
+                        */
+                       ret++;
                *(u32 *)dest = make_data_loc(ret, (void *)dst - base);
        }
 
index 0baa672..d937cba 100644 (file)
@@ -37,6 +37,8 @@ static kernel_cap_t usermodehelper_bset = CAP_FULL_SET;
 static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET;
 static DEFINE_SPINLOCK(umh_sysctl_lock);
 static DECLARE_RWSEM(umhelper_sem);
+static LIST_HEAD(umh_list);
+static DEFINE_MUTEX(umh_list_lock);
 
 static void call_usermodehelper_freeinfo(struct subprocess_info *info)
 {
@@ -100,10 +102,12 @@ static int call_usermodehelper_exec_async(void *data)
        commit_creds(new);
 
        sub_info->pid = task_pid_nr(current);
-       if (sub_info->file)
+       if (sub_info->file) {
                retval = do_execve_file(sub_info->file,
                                        sub_info->argv, sub_info->envp);
-       else
+               if (!retval)
+                       current->flags |= PF_UMH;
+       } else
                retval = do_execve(getname_kernel(sub_info->path),
                                   (const char __user *const __user *)sub_info->argv,
                                   (const char __user *const __user *)sub_info->envp);
@@ -517,6 +521,11 @@ int fork_usermode_blob(void *data, size_t len, struct umh_info *info)
                goto out;
 
        err = call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC);
+       if (!err) {
+               mutex_lock(&umh_list_lock);
+               list_add(&info->list, &umh_list);
+               mutex_unlock(&umh_list_lock);
+       }
 out:
        fput(file);
        return err;
@@ -679,6 +688,26 @@ static int proc_cap_handler(struct ctl_table *table, int write,
        return 0;
 }
 
+void __exit_umh(struct task_struct *tsk)
+{
+       struct umh_info *info;
+       pid_t pid = tsk->pid;
+
+       mutex_lock(&umh_list_lock);
+       list_for_each_entry(info, &umh_list, list) {
+               if (info->pid == pid) {
+                       list_del(&info->list);
+                       mutex_unlock(&umh_list_lock);
+                       goto out;
+               }
+       }
+       mutex_unlock(&umh_list_lock);
+       return;
+out:
+       if (info->cleanup)
+               info->cleanup(info);
+}
+
 struct ctl_table usermodehelper_table[] = {
        {
                .procname       = "bset",
index 392be4b..fc5d23d 100644 (file)
@@ -910,6 +910,26 @@ struct task_struct *wq_worker_sleeping(struct task_struct *task)
 }
 
 /**
+ * wq_worker_last_func - retrieve worker's last work function
+ *
+ * Determine the last function a worker executed. This is called from
+ * the scheduler to get a worker's last known identity.
+ *
+ * CONTEXT:
+ * spin_lock_irq(rq->lock)
+ *
+ * Return:
+ * The last work function %current executed as a worker, NULL if it
+ * hasn't executed any work yet.
+ */
+work_func_t wq_worker_last_func(struct task_struct *task)
+{
+       struct worker *worker = kthread_data(task);
+
+       return worker->last_func;
+}
+
+/**
  * worker_set_flags - set worker flags and adjust nr_running accordingly
  * @worker: self
  * @flags: flags to set
@@ -2184,6 +2204,9 @@ __acquires(&pool->lock)
        if (unlikely(cpu_intensive))
                worker_clr_flags(worker, WORKER_CPU_INTENSIVE);
 
+       /* tag the worker for identification in schedule() */
+       worker->last_func = worker->current_func;
+
        /* we're done with it, release */
        hash_del(&worker->hentry);
        worker->current_work = NULL;
index 66fbb5a..cb68b03 100644 (file)
@@ -53,6 +53,9 @@ struct worker {
 
        /* used only by rescuers to point to the target workqueue */
        struct workqueue_struct *rescue_wq;     /* I: the workqueue to rescue */
+
+       /* used by the scheduler to determine a worker's last known identity */
+       work_func_t             last_func;
 };
 
 /**
@@ -67,9 +70,10 @@ static inline struct worker *current_wq_worker(void)
 
 /*
  * Scheduler hooks for concurrency managed workqueue.  Only to be used from
- * sched/core.c and workqueue.c.
+ * sched/ and workqueue.c.
  */
 void wq_worker_waking_up(struct task_struct *task, int cpu);
 struct task_struct *wq_worker_sleeping(struct task_struct *task);
+work_func_t wq_worker_last_func(struct task_struct *task);
 
 #endif /* _KERNEL_WORKQUEUE_INTERNAL_H */
index 45b1d67..4a20455 100644 (file)
@@ -206,8 +206,8 @@ u32 __pure __weak __crc32c_le(u32 crc, unsigned char const *p, size_t len)
 EXPORT_SYMBOL(crc32_le);
 EXPORT_SYMBOL(__crc32c_le);
 
-u32 crc32_le_base(u32, unsigned char const *, size_t) __alias(crc32_le);
-u32 __crc32c_le_base(u32, unsigned char const *, size_t) __alias(__crc32c_le);
+u32 __pure crc32_le_base(u32, unsigned char const *, size_t) __alias(crc32_le);
+u32 __pure __crc32c_le_base(u32, unsigned char const *, size_t) __alias(__crc32c_le);
 
 /*
  * This multiplies the polynomials x and y modulo the given modulus.
index 14436f4..30e0f97 100644 (file)
@@ -52,7 +52,7 @@ u32 int_sqrt64(u64 x)
        if (x <= ULONG_MAX)
                return int_sqrt((unsigned long) x);
 
-       m = 1ULL << (fls64(x) & ~1ULL);
+       m = 1ULL << ((fls64(x) - 1) & ~1ULL);
        while (m != 0) {
                b = y + m;
                y >>= 1;
index 65c2d06..5b382c1 100644 (file)
 static inline bool sbitmap_deferred_clear(struct sbitmap *sb, int index)
 {
        unsigned long mask, val;
-       unsigned long __maybe_unused flags;
        bool ret = false;
+       unsigned long flags;
 
-       /* Silence bogus lockdep warning */
-#if defined(CONFIG_LOCKDEP)
-       local_irq_save(flags);
-#endif
-       spin_lock(&sb->map[index].swap_lock);
+       spin_lock_irqsave(&sb->map[index].swap_lock, flags);
 
        if (!sb->map[index].cleared)
                goto out_unlock;
@@ -54,10 +50,7 @@ static inline bool sbitmap_deferred_clear(struct sbitmap *sb, int index)
 
        ret = true;
 out_unlock:
-       spin_unlock(&sb->map[index].swap_lock);
-#if defined(CONFIG_LOCKDEP)
-       local_irq_restore(flags);
-#endif
+       spin_unlock_irqrestore(&sb->map[index].swap_lock, flags);
        return ret;
 }
 
index d82d022..9cf7762 100644 (file)
@@ -632,7 +632,7 @@ static void __kmod_config_free(struct test_config *config)
        config->test_driver = NULL;
 
        kfree_const(config->test_fs);
-       config->test_driver = NULL;
+       config->test_fs = NULL;
 }
 
 static void kmod_config_free(struct kmod_test_device *test_dev)
index 6a8ac76..e52f8ca 100644 (file)
@@ -541,38 +541,45 @@ static unsigned int __init print_ht(struct rhltable *rhlt)
 static int __init test_insert_dup(struct test_obj_rhl *rhl_test_objects,
                                  int cnt, bool slow)
 {
-       struct rhltable rhlt;
+       struct rhltable *rhlt;
        unsigned int i, ret;
        const char *key;
        int err = 0;
 
-       err = rhltable_init(&rhlt, &test_rht_params_dup);
-       if (WARN_ON(err))
+       rhlt = kmalloc(sizeof(*rhlt), GFP_KERNEL);
+       if (WARN_ON(!rhlt))
+               return -EINVAL;
+
+       err = rhltable_init(rhlt, &test_rht_params_dup);
+       if (WARN_ON(err)) {
+               kfree(rhlt);
                return err;
+       }
 
        for (i = 0; i < cnt; i++) {
                rhl_test_objects[i].value.tid = i;
-               key = rht_obj(&rhlt.ht, &rhl_test_objects[i].list_node.rhead);
+               key = rht_obj(&rhlt->ht, &rhl_test_objects[i].list_node.rhead);
                key += test_rht_params_dup.key_offset;
 
                if (slow) {
-                       err = PTR_ERR(rhashtable_insert_slow(&rhlt.ht, key,
+                       err = PTR_ERR(rhashtable_insert_slow(&rhlt->ht, key,
                                                             &rhl_test_objects[i].list_node.rhead));
                        if (err == -EAGAIN)
                                err = 0;
                } else
-                       err = rhltable_insert(&rhlt,
+                       err = rhltable_insert(rhlt,
                                              &rhl_test_objects[i].list_node,
                                              test_rht_params_dup);
                if (WARN(err, "error %d on element %d/%d (%s)\n", err, i, cnt, slow? "slow" : "fast"))
                        goto skip_print;
        }
 
-       ret = print_ht(&rhlt);
+       ret = print_ht(rhlt);
        WARN(ret != cnt, "missing rhltable elements (%d != %d, %s)\n", ret, cnt, slow? "slow" : "fast");
 
 skip_print:
-       rhltable_destroy(&rhlt);
+       rhltable_destroy(rhlt);
+       kfree(rhlt);
 
        return 0;
 }
index 4676c0a..c596a95 100644 (file)
@@ -199,7 +199,7 @@ static noinline void check_xa_mark_1(struct xarray *xa, unsigned long index)
                XA_BUG_ON(xa, xa_store_index(xa, index + 1, GFP_KERNEL));
                xa_set_mark(xa, index + 1, XA_MARK_0);
                XA_BUG_ON(xa, xa_store_index(xa, index + 2, GFP_KERNEL));
-               xa_set_mark(xa, index + 2, XA_MARK_1);
+               xa_set_mark(xa, index + 2, XA_MARK_2);
                XA_BUG_ON(xa, xa_store_index(xa, next, GFP_KERNEL));
                xa_store_order(xa, index, order, xa_mk_index(index),
                                GFP_KERNEL);
@@ -209,8 +209,8 @@ static noinline void check_xa_mark_1(struct xarray *xa, unsigned long index)
                        void *entry;
 
                        XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_0));
-                       XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_1));
-                       XA_BUG_ON(xa, xa_get_mark(xa, i, XA_MARK_2));
+                       XA_BUG_ON(xa, xa_get_mark(xa, i, XA_MARK_1));
+                       XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_2));
 
                        /* We should see two elements in the array */
                        rcu_read_lock();
@@ -357,7 +357,7 @@ static noinline void check_cmpxchg(struct xarray *xa)
 static noinline void check_reserve(struct xarray *xa)
 {
        void *entry;
-       unsigned long index = 0;
+       unsigned long index;
 
        /* An array with a reserved entry is not empty */
        XA_BUG_ON(xa, !xa_empty(xa));
@@ -382,10 +382,12 @@ static noinline void check_reserve(struct xarray *xa)
        xa_erase_index(xa, 12345678);
        XA_BUG_ON(xa, !xa_empty(xa));
 
-       /* And so does xa_insert */
+       /* But xa_insert does not */
        xa_reserve(xa, 12345678, GFP_KERNEL);
-       XA_BUG_ON(xa, xa_insert(xa, 12345678, xa_mk_value(12345678), 0) != 0);
-       xa_erase_index(xa, 12345678);
+       XA_BUG_ON(xa, xa_insert(xa, 12345678, xa_mk_value(12345678), 0) !=
+                       -EEXIST);
+       XA_BUG_ON(xa, xa_empty(xa));
+       XA_BUG_ON(xa, xa_erase(xa, 12345678) != NULL);
        XA_BUG_ON(xa, !xa_empty(xa));
 
        /* Can iterate through a reserved entry */
@@ -393,7 +395,7 @@ static noinline void check_reserve(struct xarray *xa)
        xa_reserve(xa, 6, GFP_KERNEL);
        xa_store_index(xa, 7, GFP_KERNEL);
 
-       xa_for_each(xa, entry, index, ULONG_MAX, XA_PRESENT) {
+       xa_for_each(xa, index, entry) {
                XA_BUG_ON(xa, index != 5 && index != 7);
        }
        xa_destroy(xa);
@@ -812,17 +814,16 @@ static noinline void check_find_1(struct xarray *xa)
 static noinline void check_find_2(struct xarray *xa)
 {
        void *entry;
-       unsigned long i, j, index = 0;
+       unsigned long i, j, index;
 
-       xa_for_each(xa, entry, index, ULONG_MAX, XA_PRESENT) {
+       xa_for_each(xa, index, entry) {
                XA_BUG_ON(xa, true);
        }
 
        for (i = 0; i < 1024; i++) {
                xa_store_index(xa, index, GFP_KERNEL);
                j = 0;
-               index = 0;
-               xa_for_each(xa, entry, index, ULONG_MAX, XA_PRESENT) {
+               xa_for_each(xa, index, entry) {
                        XA_BUG_ON(xa, xa_mk_index(index) != entry);
                        XA_BUG_ON(xa, index != j++);
                }
@@ -839,6 +840,7 @@ static noinline void check_find_3(struct xarray *xa)
 
        for (i = 0; i < 100; i++) {
                for (j = 0; j < 100; j++) {
+                       rcu_read_lock();
                        for (k = 0; k < 100; k++) {
                                xas_set(&xas, j);
                                xas_for_each_marked(&xas, entry, k, XA_MARK_0)
@@ -847,6 +849,7 @@ static noinline void check_find_3(struct xarray *xa)
                                        XA_BUG_ON(xa,
                                                xas.xa_node != XAS_RESTART);
                        }
+                       rcu_read_unlock();
                }
                xa_store_index(xa, i, GFP_KERNEL);
                xa_set_mark(xa, i, XA_MARK_0);
@@ -1183,6 +1186,35 @@ static noinline void check_store_range(struct xarray *xa)
        }
 }
 
+static void check_align_1(struct xarray *xa, char *name)
+{
+       int i;
+       unsigned int id;
+       unsigned long index;
+       void *entry;
+
+       for (i = 0; i < 8; i++) {
+               id = 0;
+               XA_BUG_ON(xa, xa_alloc(xa, &id, UINT_MAX, name + i, GFP_KERNEL)
+                               != 0);
+               XA_BUG_ON(xa, id != i);
+       }
+       xa_for_each(xa, index, entry)
+               XA_BUG_ON(xa, xa_is_err(entry));
+       xa_destroy(xa);
+}
+
+static noinline void check_align(struct xarray *xa)
+{
+       char name[] = "Motorola 68000";
+
+       check_align_1(xa, name);
+       check_align_1(xa, name + 1);
+       check_align_1(xa, name + 2);
+       check_align_1(xa, name + 3);
+//     check_align_2(xa, name);
+}
+
 static LIST_HEAD(shadow_nodes);
 
 static void test_update_node(struct xa_node *node)
@@ -1332,6 +1364,7 @@ static int xarray_checks(void)
        check_create_range(&array);
        check_store_range(&array);
        check_store_iter(&array);
+       check_align(&xa0);
 
        check_workingset(&array, 0);
        check_workingset(&array, 64);
index 5f3f931..81c3171 100644 (file)
@@ -232,6 +232,8 @@ void *xas_load(struct xa_state *xas)
                if (xas->xa_shift > node->shift)
                        break;
                entry = xas_descend(xas, node);
+               if (node->shift == 0)
+                       break;
        }
        return entry;
 }
@@ -506,7 +508,7 @@ static void xas_free_nodes(struct xa_state *xas, struct xa_node *top)
        for (;;) {
                void *entry = xa_entry_locked(xas->xa, node, offset);
 
-               if (xa_is_node(entry)) {
+               if (node->shift && xa_is_node(entry)) {
                        node = xa_to_node(entry);
                        offset = 0;
                        continue;
@@ -604,6 +606,7 @@ static int xas_expand(struct xa_state *xas, void *head)
 /*
  * xas_create() - Create a slot to store an entry in.
  * @xas: XArray operation state.
+ * @allow_root: %true if we can store the entry in the root directly
  *
  * Most users will not need to call this function directly, as it is called
  * by xas_store().  It is useful for doing conditional store operations
@@ -613,7 +616,7 @@ static int xas_expand(struct xa_state *xas, void *head)
  * If the slot was newly created, returns %NULL.  If it failed to create the
  * slot, returns %NULL and indicates the error in @xas.
  */
-static void *xas_create(struct xa_state *xas)
+static void *xas_create(struct xa_state *xas, bool allow_root)
 {
        struct xarray *xa = xas->xa;
        void *entry;
@@ -628,6 +631,8 @@ static void *xas_create(struct xa_state *xas)
                shift = xas_expand(xas, entry);
                if (shift < 0)
                        return NULL;
+               if (!shift && !allow_root)
+                       shift = XA_CHUNK_SHIFT;
                entry = xa_head_locked(xa);
                slot = &xa->xa_head;
        } else if (xas_error(xas)) {
@@ -687,7 +692,7 @@ void xas_create_range(struct xa_state *xas)
        xas->xa_sibs = 0;
 
        for (;;) {
-               xas_create(xas);
+               xas_create(xas, true);
                if (xas_error(xas))
                        goto restore;
                if (xas->xa_index <= (index | XA_CHUNK_MASK))
@@ -754,7 +759,7 @@ void *xas_store(struct xa_state *xas, void *entry)
        bool value = xa_is_value(entry);
 
        if (entry)
-               first = xas_create(xas);
+               first = xas_create(xas, !xa_is_node(entry));
        else
                first = xas_load(xas);
 
@@ -1251,35 +1256,6 @@ void *xas_find_conflict(struct xa_state *xas)
 EXPORT_SYMBOL_GPL(xas_find_conflict);
 
 /**
- * xa_init_flags() - Initialise an empty XArray with flags.
- * @xa: XArray.
- * @flags: XA_FLAG values.
- *
- * If you need to initialise an XArray with special flags (eg you need
- * to take the lock from interrupt context), use this function instead
- * of xa_init().
- *
- * Context: Any context.
- */
-void xa_init_flags(struct xarray *xa, gfp_t flags)
-{
-       unsigned int lock_type;
-       static struct lock_class_key xa_lock_irq;
-       static struct lock_class_key xa_lock_bh;
-
-       spin_lock_init(&xa->xa_lock);
-       xa->xa_flags = flags;
-       xa->xa_head = NULL;
-
-       lock_type = xa_lock_type(xa);
-       if (lock_type == XA_LOCK_IRQ)
-               lockdep_set_class(&xa->xa_lock, &xa_lock_irq);
-       else if (lock_type == XA_LOCK_BH)
-               lockdep_set_class(&xa->xa_lock, &xa_lock_bh);
-}
-EXPORT_SYMBOL(xa_init_flags);
-
-/**
  * xa_load() - Load an entry from an XArray.
  * @xa: XArray.
  * @index: index into array.
@@ -1308,7 +1284,6 @@ static void *xas_result(struct xa_state *xas, void *curr)
 {
        if (xa_is_zero(curr))
                return NULL;
-       XA_NODE_BUG_ON(xas->xa_node, xa_is_internal(curr));
        if (xas_error(xas))
                curr = xas->xa_node;
        return curr;
@@ -1378,7 +1353,7 @@ void *__xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
        XA_STATE(xas, xa, index);
        void *curr;
 
-       if (WARN_ON_ONCE(xa_is_internal(entry)))
+       if (WARN_ON_ONCE(xa_is_advanced(entry)))
                return XA_ERROR(-EINVAL);
        if (xa_track_free(xa) && !entry)
                entry = XA_ZERO_ENTRY;
@@ -1444,7 +1419,7 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index,
        XA_STATE(xas, xa, index);
        void *curr;
 
-       if (WARN_ON_ONCE(xa_is_internal(entry)))
+       if (WARN_ON_ONCE(xa_is_advanced(entry)))
                return XA_ERROR(-EINVAL);
        if (xa_track_free(xa) && !entry)
                entry = XA_ZERO_ENTRY;
@@ -1465,6 +1440,47 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index,
 EXPORT_SYMBOL(__xa_cmpxchg);
 
 /**
+ * __xa_insert() - Store this entry in the XArray if no entry is present.
+ * @xa: XArray.
+ * @index: Index into array.
+ * @entry: New entry.
+ * @gfp: Memory allocation flags.
+ *
+ * Inserting a NULL entry will store a reserved entry (like xa_reserve())
+ * if no entry is present.  Inserting will fail if a reserved entry is
+ * present, even though loading from this index will return NULL.
+ *
+ * Context: Any context.  Expects xa_lock to be held on entry.  May
+ * release and reacquire xa_lock if @gfp flags permit.
+ * Return: 0 if the store succeeded.  -EEXIST if another entry was present.
+ * -ENOMEM if memory could not be allocated.
+ */
+int __xa_insert(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
+{
+       XA_STATE(xas, xa, index);
+       void *curr;
+
+       if (WARN_ON_ONCE(xa_is_advanced(entry)))
+               return -EINVAL;
+       if (!entry)
+               entry = XA_ZERO_ENTRY;
+
+       do {
+               curr = xas_load(&xas);
+               if (!curr) {
+                       xas_store(&xas, entry);
+                       if (xa_track_free(xa))
+                               xas_clear_mark(&xas, XA_FREE_MARK);
+               } else {
+                       xas_set_err(&xas, -EEXIST);
+               }
+       } while (__xas_nomem(&xas, gfp));
+
+       return xas_error(&xas);
+}
+EXPORT_SYMBOL(__xa_insert);
+
+/**
  * __xa_reserve() - Reserve this index in the XArray.
  * @xa: XArray.
  * @index: Index into array.
@@ -1567,7 +1583,7 @@ void *xa_store_range(struct xarray *xa, unsigned long first,
                        if (last + 1)
                                order = __ffs(last + 1);
                        xas_set_order(&xas, last, order);
-                       xas_create(&xas);
+                       xas_create(&xas, true);
                        if (xas_error(&xas))
                                goto unlock;
                }
@@ -1609,7 +1625,7 @@ int __xa_alloc(struct xarray *xa, u32 *id, u32 max, void *entry, gfp_t gfp)
        XA_STATE(xas, xa, 0);
        int err;
 
-       if (WARN_ON_ONCE(xa_is_internal(entry)))
+       if (WARN_ON_ONCE(xa_is_advanced(entry)))
                return -EINVAL;
        if (WARN_ON_ONCE(!xa_track_free(xa)))
                return -EINVAL;
index 8a8bb87..72e6d0c 100644 (file)
@@ -689,6 +689,7 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi)
        INIT_RADIX_TREE(&bdi->cgwb_tree, GFP_ATOMIC);
        bdi->cgwb_congested_tree = RB_ROOT;
        mutex_init(&bdi->cgwb_release_mutex);
+       init_rwsem(&bdi->wb_switch_rwsem);
 
        ret = wb_init(&bdi->wb, bdi, 1, GFP_KERNEL);
        if (!ret) {
index 05acd7e..7502964 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -1674,7 +1674,8 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
                if (!pmd_present(pmd))
                        return 0;
 
-               if (unlikely(pmd_trans_huge(pmd) || pmd_huge(pmd))) {
+               if (unlikely(pmd_trans_huge(pmd) || pmd_huge(pmd) ||
+                            pmd_devmap(pmd))) {
                        /*
                         * NUMA hinting faults need to be handled in the GUP
                         * slowpath for accounting purposes and so that they
index 7450888..afef616 100644 (file)
@@ -3238,7 +3238,6 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
        struct page *ptepage;
        unsigned long addr;
        int cow;
-       struct address_space *mapping = vma->vm_file->f_mapping;
        struct hstate *h = hstate_vma(vma);
        unsigned long sz = huge_page_size(h);
        struct mmu_notifier_range range;
@@ -3250,23 +3249,13 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
                mmu_notifier_range_init(&range, src, vma->vm_start,
                                        vma->vm_end);
                mmu_notifier_invalidate_range_start(&range);
-       } else {
-               /*
-                * For shared mappings i_mmap_rwsem must be held to call
-                * huge_pte_alloc, otherwise the returned ptep could go
-                * away if part of a shared pmd and another thread calls
-                * huge_pmd_unshare.
-                */
-               i_mmap_lock_read(mapping);
        }
 
        for (addr = vma->vm_start; addr < vma->vm_end; addr += sz) {
                spinlock_t *src_ptl, *dst_ptl;
-
                src_pte = huge_pte_offset(src, addr, sz);
                if (!src_pte)
                        continue;
-
                dst_pte = huge_pte_alloc(dst, addr, sz);
                if (!dst_pte) {
                        ret = -ENOMEM;
@@ -3337,8 +3326,6 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
 
        if (cow)
                mmu_notifier_invalidate_range_end(&range);
-       else
-               i_mmap_unlock_read(mapping);
 
        return ret;
 }
@@ -3755,16 +3742,16 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm,
        }
 
        /*
-        * We can not race with truncation due to holding i_mmap_rwsem.
-        * Check once here for faults beyond end of file.
+        * Use page lock to guard against racing truncation
+        * before we get page_table_lock.
         */
-       size = i_size_read(mapping->host) >> huge_page_shift(h);
-       if (idx >= size)
-               goto out;
-
 retry:
        page = find_lock_page(mapping, idx);
        if (!page) {
+               size = i_size_read(mapping->host) >> huge_page_shift(h);
+               if (idx >= size)
+                       goto out;
+
                /*
                 * Check for page in userfault range
                 */
@@ -3784,18 +3771,14 @@ retry:
                        };
 
                        /*
-                        * hugetlb_fault_mutex and i_mmap_rwsem must be
-                        * dropped before handling userfault.  Reacquire
-                        * after handling fault to make calling code simpler.
+                        * hugetlb_fault_mutex must be dropped before
+                        * handling userfault.  Reacquire after handling
+                        * fault to make calling code simpler.
                         */
                        hash = hugetlb_fault_mutex_hash(h, mm, vma, mapping,
                                                        idx, haddr);
                        mutex_unlock(&hugetlb_fault_mutex_table[hash]);
-                       i_mmap_unlock_read(mapping);
-
                        ret = handle_userfault(&vmf, VM_UFFD_MISSING);
-
-                       i_mmap_lock_read(mapping);
                        mutex_lock(&hugetlb_fault_mutex_table[hash]);
                        goto out;
                }
@@ -3854,6 +3837,9 @@ retry:
        }
 
        ptl = huge_pte_lock(h, mm, ptep);
+       size = i_size_read(mapping->host) >> huge_page_shift(h);
+       if (idx >= size)
+               goto backout;
 
        ret = 0;
        if (!huge_pte_none(huge_ptep_get(ptep)))
@@ -3940,11 +3926,6 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 
        ptep = huge_pte_offset(mm, haddr, huge_page_size(h));
        if (ptep) {
-               /*
-                * Since we hold no locks, ptep could be stale.  That is
-                * OK as we are only making decisions based on content and
-                * not actually modifying content here.
-                */
                entry = huge_ptep_get(ptep);
                if (unlikely(is_hugetlb_entry_migration(entry))) {
                        migration_entry_wait_huge(vma, mm, ptep);
@@ -3952,33 +3933,20 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                } else if (unlikely(is_hugetlb_entry_hwpoisoned(entry)))
                        return VM_FAULT_HWPOISON_LARGE |
                                VM_FAULT_SET_HINDEX(hstate_index(h));
+       } else {
+               ptep = huge_pte_alloc(mm, haddr, huge_page_size(h));
+               if (!ptep)
+                       return VM_FAULT_OOM;
        }
 
-       /*
-        * Acquire i_mmap_rwsem before calling huge_pte_alloc and hold
-        * until finished with ptep.  This serves two purposes:
-        * 1) It prevents huge_pmd_unshare from being called elsewhere
-        *    and making the ptep no longer valid.
-        * 2) It synchronizes us with file truncation.
-        *
-        * ptep could have already be assigned via huge_pte_offset.  That
-        * is OK, as huge_pte_alloc will return the same value unless
-        * something changed.
-        */
        mapping = vma->vm_file->f_mapping;
-       i_mmap_lock_read(mapping);
-       ptep = huge_pte_alloc(mm, haddr, huge_page_size(h));
-       if (!ptep) {
-               i_mmap_unlock_read(mapping);
-               return VM_FAULT_OOM;
-       }
+       idx = vma_hugecache_offset(h, vma, haddr);
 
        /*
         * Serialize hugepage allocation and instantiation, so that we don't
         * get spurious allocation failures if two CPUs race to instantiate
         * the same page in the page cache.
         */
-       idx = vma_hugecache_offset(h, vma, haddr);
        hash = hugetlb_fault_mutex_hash(h, mm, vma, mapping, idx, haddr);
        mutex_lock(&hugetlb_fault_mutex_table[hash]);
 
@@ -4066,7 +4034,6 @@ out_ptl:
        }
 out_mutex:
        mutex_unlock(&hugetlb_fault_mutex_table[hash]);
-       i_mmap_unlock_read(mapping);
        /*
         * Generally it's safe to hold refcount during waiting page lock. But
         * here we just wait to defer the next page fault to avoid busy loop and
@@ -4301,7 +4268,8 @@ long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
                                break;
                        }
                        if (ret & VM_FAULT_RETRY) {
-                               if (nonblocking)
+                               if (nonblocking &&
+                                   !(fault_flags & FAULT_FLAG_RETRY_NOWAIT))
                                        *nonblocking = 0;
                                *nr_pages = 0;
                                /*
@@ -4671,12 +4639,10 @@ void adjust_range_if_pmd_sharing_possible(struct vm_area_struct *vma,
  * Search for a shareable pmd page for hugetlb. In any case calls pmd_alloc()
  * and returns the corresponding pte. While this is not necessary for the
  * !shared pmd case because we can allocate the pmd later as well, it makes the
- * code much cleaner.
- *
- * This routine must be called with i_mmap_rwsem held in at least read mode.
- * For hugetlbfs, this prevents removal of any page table entries associated
- * with the address space.  This is important as we are setting up sharing
- * based on existing page table entries (mappings).
+ * code much cleaner. pmd allocation is essential for the shared case because
+ * pud has to be populated inside the same i_mmap_rwsem section - otherwise
+ * racing tasks could either miss the sharing (see huge_pte_offset) or select a
+ * bad pmd for sharing.
  */
 pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
 {
@@ -4693,6 +4659,7 @@ pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
        if (!vma_shareable(vma, addr))
                return (pte_t *)pmd_alloc(mm, pud, addr);
 
+       i_mmap_lock_write(mapping);
        vma_interval_tree_foreach(svma, &mapping->i_mmap, idx, idx) {
                if (svma == vma)
                        continue;
@@ -4722,6 +4689,7 @@ pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
        spin_unlock(ptl);
 out:
        pte = (pte_t *)pmd_alloc(mm, pud, addr);
+       i_mmap_unlock_write(mapping);
        return pte;
 }
 
@@ -4732,7 +4700,7 @@ out:
  * indicated by page_count > 1, unmap is achieved by clearing pud and
  * decrementing the ref count. If count == 1, the pte page is not shared.
  *
- * Called with page table lock held and i_mmap_rwsem held in write mode.
+ * called with page table lock held.
  *
  * returns: 1 successfully unmapped a shared pte page
  *         0 the underlying pte page is not shared, or it is the last user
index 0a14fcf..e2bb06c 100644 (file)
@@ -5,6 +5,7 @@ UBSAN_SANITIZE_generic.o := n
 UBSAN_SANITIZE_tags.o := n
 KCOV_INSTRUMENT := n
 
+CFLAGS_REMOVE_common.o = -pg
 CFLAGS_REMOVE_generic.o = -pg
 # Function splitter causes unnecessary splits in __asan_load1/__asan_store1
 # see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63533
index 03d5d13..73c9cbf 100644 (file)
@@ -298,8 +298,6 @@ void kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
                return;
        }
 
-       cache->align = round_up(cache->align, KASAN_SHADOW_SCALE_SIZE);
-
        *flags |= SLAB_KASAN;
 }
 
@@ -349,28 +347,43 @@ void kasan_poison_object_data(struct kmem_cache *cache, void *object)
 }
 
 /*
- * Since it's desirable to only call object contructors once during slab
- * allocation, we preassign tags to all such objects. Also preassign tags for
- * SLAB_TYPESAFE_BY_RCU slabs to avoid use-after-free reports.
- * For SLAB allocator we can't preassign tags randomly since the freelist is
- * stored as an array of indexes instead of a linked list. Assign tags based
- * on objects indexes, so that objects that are next to each other get
- * different tags.
- * After a tag is assigned, the object always gets allocated with the same tag.
- * The reason is that we can't change tags for objects with constructors on
- * reallocation (even for non-SLAB_TYPESAFE_BY_RCU), because the constructor
- * code can save the pointer to the object somewhere (e.g. in the object
- * itself). Then if we retag it, the old saved pointer will become invalid.
+ * This function assigns a tag to an object considering the following:
+ * 1. A cache might have a constructor, which might save a pointer to a slab
+ *    object somewhere (e.g. in the object itself). We preassign a tag for
+ *    each object in caches with constructors during slab creation and reuse
+ *    the same tag each time a particular object is allocated.
+ * 2. A cache might be SLAB_TYPESAFE_BY_RCU, which means objects can be
+ *    accessed after being freed. We preassign tags for objects in these
+ *    caches as well.
+ * 3. For SLAB allocator we can't preassign tags randomly since the freelist
+ *    is stored as an array of indexes instead of a linked list. Assign tags
+ *    based on objects indexes, so that objects that are next to each other
+ *    get different tags.
  */
-static u8 assign_tag(struct kmem_cache *cache, const void *object, bool new)
+static u8 assign_tag(struct kmem_cache *cache, const void *object,
+                       bool init, bool krealloc)
 {
+       /* Reuse the same tag for krealloc'ed objects. */
+       if (krealloc)
+               return get_tag(object);
+
+       /*
+        * If the cache neither has a constructor nor has SLAB_TYPESAFE_BY_RCU
+        * set, assign a tag when the object is being allocated (init == false).
+        */
        if (!cache->ctor && !(cache->flags & SLAB_TYPESAFE_BY_RCU))
-               return new ? KASAN_TAG_KERNEL : random_tag();
+               return init ? KASAN_TAG_KERNEL : random_tag();
 
+       /* For caches that either have a constructor or SLAB_TYPESAFE_BY_RCU: */
 #ifdef CONFIG_SLAB
+       /* For SLAB assign tags based on the object index in the freelist. */
        return (u8)obj_to_index(cache, virt_to_page(object), (void *)object);
 #else
-       return new ? random_tag() : get_tag(object);
+       /*
+        * For SLUB assign a random tag during slab creation, otherwise reuse
+        * the already assigned tag.
+        */
+       return init ? random_tag() : get_tag(object);
 #endif
 }
 
@@ -386,7 +399,8 @@ void * __must_check kasan_init_slab_obj(struct kmem_cache *cache,
        __memset(alloc_info, 0, sizeof(*alloc_info));
 
        if (IS_ENABLED(CONFIG_KASAN_SW_TAGS))
-               object = set_tag(object, assign_tag(cache, object, true));
+               object = set_tag(object,
+                               assign_tag(cache, object, true, false));
 
        return (void *)object;
 }
@@ -452,8 +466,8 @@ bool kasan_slab_free(struct kmem_cache *cache, void *object, unsigned long ip)
        return __kasan_slab_free(cache, object, ip, true);
 }
 
-void * __must_check kasan_kmalloc(struct kmem_cache *cache, const void *object,
-                                       size_t size, gfp_t flags)
+static void *__kasan_kmalloc(struct kmem_cache *cache, const void *object,
+                               size_t size, gfp_t flags, bool krealloc)
 {
        unsigned long redzone_start;
        unsigned long redzone_end;
@@ -471,7 +485,7 @@ void * __must_check kasan_kmalloc(struct kmem_cache *cache, const void *object,
                                KASAN_SHADOW_SCALE_SIZE);
 
        if (IS_ENABLED(CONFIG_KASAN_SW_TAGS))
-               tag = assign_tag(cache, object, false);
+               tag = assign_tag(cache, object, false, krealloc);
 
        /* Tag is ignored in set_tag without CONFIG_KASAN_SW_TAGS */
        kasan_unpoison_shadow(set_tag(object, tag), size);
@@ -483,6 +497,12 @@ void * __must_check kasan_kmalloc(struct kmem_cache *cache, const void *object,
 
        return set_tag(object, tag);
 }
+
+void * __must_check kasan_kmalloc(struct kmem_cache *cache, const void *object,
+                               size_t size, gfp_t flags)
+{
+       return __kasan_kmalloc(cache, object, size, flags, false);
+}
 EXPORT_SYMBOL(kasan_kmalloc);
 
 void * __must_check kasan_kmalloc_large(const void *ptr, size_t size,
@@ -522,7 +542,8 @@ void * __must_check kasan_krealloc(const void *object, size_t size, gfp_t flags)
        if (unlikely(!PageSlab(page)))
                return kasan_kmalloc_large(object, size, flags);
        else
-               return kasan_kmalloc(page->slab_cache, object, size, flags);
+               return __kasan_kmalloc(page->slab_cache, object, size,
+                                               flags, true);
 }
 
 void kasan_poison_kfree(void *ptr, unsigned long ip)
index 022d4cb..ea31045 100644 (file)
 
 #include "internal.h"
 
+#define INIT_MEMBLOCK_REGIONS                  128
+#define INIT_PHYSMEM_REGIONS                   4
+
+#ifndef INIT_MEMBLOCK_RESERVED_REGIONS
+# define INIT_MEMBLOCK_RESERVED_REGIONS                INIT_MEMBLOCK_REGIONS
+#endif
+
 /**
  * DOC: memblock overview
  *
@@ -92,7 +99,7 @@ unsigned long max_pfn;
 unsigned long long max_possible_pfn;
 
 static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
-static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
+static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_RESERVED_REGIONS] __initdata_memblock;
 #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
 static struct memblock_region memblock_physmem_init_regions[INIT_PHYSMEM_REGIONS] __initdata_memblock;
 #endif
@@ -105,7 +112,7 @@ struct memblock memblock __initdata_memblock = {
 
        .reserved.regions       = memblock_reserved_init_regions,
        .reserved.cnt           = 1,    /* empty dummy entry */
-       .reserved.max           = INIT_MEMBLOCK_REGIONS,
+       .reserved.max           = INIT_MEMBLOCK_RESERVED_REGIONS,
        .reserved.name          = "reserved",
 
 #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
index 6379fff..831be5f 100644 (file)
@@ -372,7 +372,8 @@ static void kill_procs(struct list_head *to_kill, int forcekill, bool fail,
                        if (fail || tk->addr_valid == 0) {
                                pr_err("Memory failure: %#lx: forcibly killing %s:%d because of failure to unmap corrupted page\n",
                                       pfn, tk->tsk->comm, tk->tsk->pid);
-                               force_sig(SIGKILL, tk->tsk);
+                               do_send_sig_info(SIGKILL, SEND_SIG_PRIV,
+                                                tk->tsk, PIDTYPE_PID);
                        }
 
                        /*
@@ -966,7 +967,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
        enum ttu_flags ttu = TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS;
        struct address_space *mapping;
        LIST_HEAD(tokill);
-       bool unmap_success = true;
+       bool unmap_success;
        int kill = 1, forcekill;
        struct page *hpage = *hpagep;
        bool mlocked = PageMlocked(hpage);
@@ -1028,19 +1029,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
        if (kill)
                collect_procs(hpage, &tokill, flags & MF_ACTION_REQUIRED);
 
-       if (!PageHuge(hpage)) {
-               unmap_success = try_to_unmap(hpage, ttu);
-       } else if (mapping) {
-               /*
-                * For hugetlb pages, try_to_unmap could potentially call
-                * huge_pmd_unshare.  Because of this, take semaphore in
-                * write mode here and set TTU_RMAP_LOCKED to indicate we
-                * have taken the lock at this higer level.
-                */
-               i_mmap_lock_write(mapping);
-               unmap_success = try_to_unmap(hpage, ttu|TTU_RMAP_LOCKED);
-               i_mmap_unlock_write(mapping);
-       }
+       unmap_success = try_to_unmap(hpage, ttu);
        if (!unmap_success)
                pr_err("Memory failure: %#lx: failed to unmap page (mapcount=%d)\n",
                       pfn, page_mapcount(hpage));
index a52663c..e11ca9d 100644 (file)
@@ -2994,6 +2994,28 @@ static vm_fault_t __do_fault(struct vm_fault *vmf)
        struct vm_area_struct *vma = vmf->vma;
        vm_fault_t ret;
 
+       /*
+        * Preallocate pte before we take page_lock because this might lead to
+        * deadlocks for memcg reclaim which waits for pages under writeback:
+        *                              lock_page(A)
+        *                              SetPageWriteback(A)
+        *                              unlock_page(A)
+        * lock_page(B)
+        *                              lock_page(B)
+        * pte_alloc_pne
+        *   shrink_page_list
+        *     wait_on_page_writeback(A)
+        *                              SetPageWriteback(B)
+        *                              unlock_page(B)
+        *                              # flush A, B to clear the writeback
+        */
+       if (pmd_none(*vmf->pmd) && !vmf->prealloc_pte) {
+               vmf->prealloc_pte = pte_alloc_one(vmf->vma->vm_mm);
+               if (!vmf->prealloc_pte)
+                       return VM_FAULT_OOM;
+               smp_wmb(); /* See comment in __pte_alloc() */
+       }
+
        ret = vma->vm_ops->fault(vmf);
        if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE | VM_FAULT_RETRY |
                            VM_FAULT_DONE_COW)))
@@ -4077,8 +4099,8 @@ static int __follow_pte_pmd(struct mm_struct *mm, unsigned long address,
                goto out;
 
        if (range) {
-               range->start = address & PAGE_MASK;
-               range->end = range->start + PAGE_SIZE;
+               mmu_notifier_range_init(range, mm, address & PAGE_MASK,
+                                    (address & PAGE_MASK) + PAGE_SIZE);
                mmu_notifier_invalidate_range_start(range);
        }
        ptep = pte_offset_map_lock(mm, pmd, address, ptlp);
index b9a667d..124e794 100644 (file)
@@ -1233,7 +1233,8 @@ static bool is_pageblock_removable_nolock(struct page *page)
 bool is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages)
 {
        struct page *page = pfn_to_page(start_pfn);
-       struct page *end_page = page + nr_pages;
+       unsigned long end_pfn = min(start_pfn + nr_pages, zone_end_pfn(page_zone(page)));
+       struct page *end_page = pfn_to_page(end_pfn);
 
        /* Check the starting page of each pageblock within the range */
        for (; page < end_page; page = next_active_pageblock(page)) {
@@ -1273,6 +1274,9 @@ int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
                                i++;
                        if (i == MAX_ORDER_NR_PAGES || pfn + i >= end_pfn)
                                continue;
+                       /* Check if we got outside of the zone */
+                       if (zone && !zone_spans_pfn(zone, pfn + i))
+                               return 0;
                        page = pfn_to_page(pfn + i);
                        if (zone && page_zone(page) != zone)
                                return 0;
@@ -1301,23 +1305,27 @@ int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
 static unsigned long scan_movable_pages(unsigned long start, unsigned long end)
 {
        unsigned long pfn;
-       struct page *page;
+
        for (pfn = start; pfn < end; pfn++) {
-               if (pfn_valid(pfn)) {
-                       page = pfn_to_page(pfn);
-                       if (PageLRU(page))
-                               return pfn;
-                       if (__PageMovable(page))
-                               return pfn;
-                       if (PageHuge(page)) {
-                               if (hugepage_migration_supported(page_hstate(page)) &&
-                                   page_huge_active(page))
-                                       return pfn;
-                               else
-                                       pfn = round_up(pfn + 1,
-                                               1 << compound_order(page)) - 1;
-                       }
-               }
+               struct page *page, *head;
+               unsigned long skip;
+
+               if (!pfn_valid(pfn))
+                       continue;
+               page = pfn_to_page(pfn);
+               if (PageLRU(page))
+                       return pfn;
+               if (__PageMovable(page))
+                       return pfn;
+
+               if (!PageHuge(page))
+                       continue;
+               head = compound_head(page);
+               if (hugepage_migration_supported(page_hstate(head)) &&
+                   page_huge_active(head))
+                       return pfn;
+               skip = (1 << compound_order(head)) - (page - head);
+               pfn += skip - 1;
        }
        return 0;
 }
@@ -1344,7 +1352,6 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
 {
        unsigned long pfn;
        struct page *page;
-       int not_managed = 0;
        int ret = 0;
        LIST_HEAD(source);
 
@@ -1392,7 +1399,6 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
                else
                        ret = isolate_movable_page(page, ISOLATE_UNEVICTABLE);
                if (!ret) { /* Success */
-                       put_page(page);
                        list_add_tail(&page->lru, &source);
                        if (!__PageMovable(page))
                                inc_node_page_state(page, NR_ISOLATED_ANON +
@@ -1401,22 +1407,10 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
                } else {
                        pr_warn("failed to isolate pfn %lx\n", pfn);
                        dump_page(page, "isolation failed");
-                       put_page(page);
-                       /* Because we don't have big zone->lock. we should
-                          check this again here. */
-                       if (page_count(page)) {
-                               not_managed++;
-                               ret = -EBUSY;
-                               break;
-                       }
                }
+               put_page(page);
        }
        if (!list_empty(&source)) {
-               if (not_managed) {
-                       putback_movable_pages(&source);
-                       goto out;
-               }
-
                /* Allocate a new page from the nearest neighbor node */
                ret = migrate_pages(&source, new_node_page, NULL, 0,
                                        MIGRATE_SYNC, MR_MEMORY_HOTPLUG);
@@ -1429,7 +1423,7 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
                        putback_movable_pages(&source);
                }
        }
-out:
+
        return ret;
 }
 
@@ -1576,7 +1570,6 @@ static int __ref __offline_pages(unsigned long start_pfn,
           we assume this for now. .*/
        if (!test_pages_in_a_zone(start_pfn, end_pfn, &valid_start,
                                  &valid_end)) {
-               mem_hotplug_done();
                ret = -EINVAL;
                reason = "multizone range";
                goto failed_removal;
@@ -1591,7 +1584,6 @@ static int __ref __offline_pages(unsigned long start_pfn,
                                       MIGRATE_MOVABLE,
                                       SKIP_HWPOISON | REPORT_FAILURE);
        if (ret) {
-               mem_hotplug_done();
                reason = "failure to isolate range";
                goto failed_removal;
        }
index ccf8966..d4fd680 100644 (file)
@@ -709,7 +709,6 @@ static bool buffer_migrate_lock_buffers(struct buffer_head *head,
        /* Simple case, sync compaction */
        if (mode != MIGRATE_ASYNC) {
                do {
-                       get_bh(bh);
                        lock_buffer(bh);
                        bh = bh->b_this_page;
 
@@ -720,18 +719,15 @@ static bool buffer_migrate_lock_buffers(struct buffer_head *head,
 
        /* async case, we cannot block on lock_buffer so use trylock_buffer */
        do {
-               get_bh(bh);
                if (!trylock_buffer(bh)) {
                        /*
                         * We failed to lock the buffer and cannot stall in
                         * async migration. Release the taken locks
                         */
                        struct buffer_head *failed_bh = bh;
-                       put_bh(failed_bh);
                        bh = head;
                        while (bh != failed_bh) {
                                unlock_buffer(bh);
-                               put_bh(bh);
                                bh = bh->b_this_page;
                        }
                        return false;
@@ -818,7 +814,6 @@ unlock_buffers:
        bh = head;
        do {
                unlock_buffer(bh);
-               put_bh(bh);
                bh = bh->b_this_page;
 
        } while (bh != head);
@@ -1135,10 +1130,13 @@ out:
         * If migration is successful, decrease refcount of the newpage
         * which will not free the page because new page owner increased
         * refcounter. As well, if it is LRU page, add the page to LRU
-        * list in here.
+        * list in here. Use the old state of the isolated source page to
+        * determine if we migrated a LRU page. newpage was already unlocked
+        * and possibly modified by its owner - don't rely on the page
+        * state.
         */
        if (rc == MIGRATEPAGE_SUCCESS) {
-               if (unlikely(__PageMovable(newpage)))
+               if (unlikely(!is_lru))
                        put_page(newpage);
                else
                        putback_lru_page(newpage);
@@ -1324,19 +1322,8 @@ static int unmap_and_move_huge_page(new_page_t get_new_page,
                goto put_anon;
 
        if (page_mapped(hpage)) {
-               struct address_space *mapping = page_mapping(hpage);
-
-               /*
-                * try_to_unmap could potentially call huge_pmd_unshare.
-                * Because of this, take semaphore in write mode here and
-                * set TTU_RMAP_LOCKED to let lower levels know we have
-                * taken the lock.
-                */
-               i_mmap_lock_write(mapping);
                try_to_unmap(hpage,
-                       TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS|
-                       TTU_RMAP_LOCKED);
-               i_mmap_unlock_write(mapping);
+                       TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS);
                page_was_mapped = 1;
        }
 
index f0f9146..218099b 100644 (file)
@@ -42,14 +42,72 @@ static int mincore_hugetlb(pte_t *pte, unsigned long hmask, unsigned long addr,
        return 0;
 }
 
-static int mincore_unmapped_range(unsigned long addr, unsigned long end,
-                                  struct mm_walk *walk)
+/*
+ * Later we can get more picky about what "in core" means precisely.
+ * For now, simply check to see if the page is in the page cache,
+ * and is up to date; i.e. that no page-in operation would be required
+ * at this time if an application were to map and access this page.
+ */
+static unsigned char mincore_page(struct address_space *mapping, pgoff_t pgoff)
+{
+       unsigned char present = 0;
+       struct page *page;
+
+       /*
+        * When tmpfs swaps out a page from a file, any process mapping that
+        * file will not get a swp_entry_t in its pte, but rather it is like
+        * any other file mapping (ie. marked !present and faulted in with
+        * tmpfs's .fault). So swapped out tmpfs mappings are tested here.
+        */
+#ifdef CONFIG_SWAP
+       if (shmem_mapping(mapping)) {
+               page = find_get_entry(mapping, pgoff);
+               /*
+                * shmem/tmpfs may return swap: account for swapcache
+                * page too.
+                */
+               if (xa_is_value(page)) {
+                       swp_entry_t swp = radix_to_swp_entry(page);
+                       page = find_get_page(swap_address_space(swp),
+                                            swp_offset(swp));
+               }
+       } else
+               page = find_get_page(mapping, pgoff);
+#else
+       page = find_get_page(mapping, pgoff);
+#endif
+       if (page) {
+               present = PageUptodate(page);
+               put_page(page);
+       }
+
+       return present;
+}
+
+static int __mincore_unmapped_range(unsigned long addr, unsigned long end,
+                               struct vm_area_struct *vma, unsigned char *vec)
 {
-       unsigned char *vec = walk->private;
        unsigned long nr = (end - addr) >> PAGE_SHIFT;
+       int i;
 
-       memset(vec, 0, nr);
-       walk->private += nr;
+       if (vma->vm_file) {
+               pgoff_t pgoff;
+
+               pgoff = linear_page_index(vma, addr);
+               for (i = 0; i < nr; i++, pgoff++)
+                       vec[i] = mincore_page(vma->vm_file->f_mapping, pgoff);
+       } else {
+               for (i = 0; i < nr; i++)
+                       vec[i] = 0;
+       }
+       return nr;
+}
+
+static int mincore_unmapped_range(unsigned long addr, unsigned long end,
+                                  struct mm_walk *walk)
+{
+       walk->private += __mincore_unmapped_range(addr, end,
+                                                 walk->vma, walk->private);
        return 0;
 }
 
@@ -69,9 +127,8 @@ static int mincore_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
                goto out;
        }
 
-       /* We'll consider a THP page under construction to be there */
        if (pmd_trans_unstable(pmd)) {
-               memset(vec, 1, nr);
+               __mincore_unmapped_range(addr, end, vma, vec);
                goto out;
        }
 
@@ -80,17 +137,28 @@ static int mincore_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
                pte_t pte = *ptep;
 
                if (pte_none(pte))
-                       *vec = 0;
+                       __mincore_unmapped_range(addr, addr + PAGE_SIZE,
+                                                vma, vec);
                else if (pte_present(pte))
                        *vec = 1;
                else { /* pte is a swap entry */
                        swp_entry_t entry = pte_to_swp_entry(pte);
 
-                       /*
-                        * migration or hwpoison entries are always
-                        * uptodate
-                        */
-                       *vec = !!non_swap_entry(entry);
+                       if (non_swap_entry(entry)) {
+                               /*
+                                * migration or hwpoison entries are always
+                                * uptodate
+                                */
+                               *vec = 1;
+                       } else {
+#ifdef CONFIG_SWAP
+                               *vec = mincore_page(swap_address_space(entry),
+                                                   swp_offset(entry));
+#else
+                               WARN_ON(1);
+                               *vec = 1;
+#endif
+                       }
                }
                vec++;
        }
index f0e8cd9..26ea863 100644 (file)
@@ -647,8 +647,8 @@ static int oom_reaper(void *unused)
 
 static void wake_oom_reaper(struct task_struct *tsk)
 {
-       /* tsk is already queued? */
-       if (tsk == oom_reaper_list || tsk->oom_reaper_list)
+       /* mm is already queued? */
+       if (test_and_set_bit(MMF_OOM_REAP_QUEUED, &tsk->signal->oom_mm->flags))
                return;
 
        get_task_struct(tsk);
@@ -975,6 +975,13 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
         * still freeing memory.
         */
        read_lock(&tasklist_lock);
+
+       /*
+        * The task 'p' might have already exited before reaching here. The
+        * put_task_struct() will free task_struct 'p' while the loop still try
+        * to access the field of 'p', so, get an extra reference.
+        */
+       get_task_struct(p);
        for_each_thread(p, t) {
                list_for_each_entry(child, &t->children, sibling) {
                        unsigned int child_points;
@@ -994,6 +1001,7 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
                        }
                }
        }
+       put_task_struct(p);
        read_unlock(&tasklist_lock);
 
        /*
index cde5dac..46285d2 100644 (file)
@@ -2214,7 +2214,7 @@ static void steal_suitable_fallback(struct zone *zone, struct page *page,
         */
        boost_watermark(zone);
        if (alloc_flags & ALLOC_KSWAPD)
-               wakeup_kswapd(zone, 0, 0, zone_idx(zone));
+               set_bit(ZONE_BOOSTED_WATERMARK, &zone->flags);
 
        /* We are not allowed to try stealing from the whole block */
        if (!whole_block)
@@ -3102,6 +3102,12 @@ struct page *rmqueue(struct zone *preferred_zone,
        local_irq_restore(flags);
 
 out:
+       /* Separate test+clear to avoid unnecessary atomics */
+       if (test_bit(ZONE_BOOSTED_WATERMARK, &zone->flags)) {
+               clear_bit(ZONE_BOOSTED_WATERMARK, &zone->flags);
+               wakeup_kswapd(zone, 0, 0, zone_idx(zone));
+       }
+
        VM_BUG_ON_PAGE(page && bad_range(zone, page), page);
        return page;
 
@@ -4669,11 +4675,11 @@ refill:
                /* Even if we own the page, we do not use atomic_set().
                 * This would break get_page_unless_zero() users.
                 */
-               page_ref_add(page, size - 1);
+               page_ref_add(page, size);
 
                /* reset page count bias and offset to start of new frag */
                nc->pfmemalloc = page_is_pfmemalloc(page);
-               nc->pagecnt_bias = size;
+               nc->pagecnt_bias = size + 1;
                nc->offset = size;
        }
 
@@ -4689,10 +4695,10 @@ refill:
                size = nc->size;
 #endif
                /* OK, page count is 0, we can safely set it */
-               set_page_count(page, size);
+               set_page_count(page, size + 1);
 
                /* reset page count bias and offset to start of new frag */
-               nc->pagecnt_bias = size;
+               nc->pagecnt_bias = size + 1;
                offset = size - fragsz;
        }
 
@@ -5695,18 +5701,6 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
                        cond_resched();
                }
        }
-#ifdef CONFIG_SPARSEMEM
-       /*
-        * If the zone does not span the rest of the section then
-        * we should at least initialize those pages. Otherwise we
-        * could blow up on a poisoned page in some paths which depend
-        * on full sections being initialized (e.g. memory hotplug).
-        */
-       while (end_pfn % PAGES_PER_SECTION) {
-               __init_single_page(pfn_to_page(end_pfn), end_pfn, zone, nid);
-               end_pfn++;
-       }
-#endif
 }
 
 #ifdef CONFIG_ZONE_DEVICE
index ae44f7a..8c78b8d 100644 (file)
@@ -398,10 +398,8 @@ void __init page_ext_init(void)
                         * We know some arch can have a nodes layout such as
                         * -------------pfn-------------->
                         * N0 | N1 | N2 | N0 | N1 | N2|....
-                        *
-                        * Take into account DEFERRED_STRUCT_PAGE_INIT.
                         */
-                       if (early_pfn_to_nid(pfn) != nid)
+                       if (pfn_to_nid(pfn) != nid)
                                continue;
                        if (init_section_page_ext(pfn, nid))
                                goto oom;
index 21a26cf..0454ecc 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -25,7 +25,6 @@
  *     page->flags PG_locked (lock_page)
  *       hugetlbfs_i_mmap_rwsem_key (in huge_pmd_share)
  *         mapping->i_mmap_rwsem
- *           hugetlb_fault_mutex (hugetlbfs specific page fault mutex)
  *           anon_vma->rwsem
  *             mm->page_table_lock or pte_lock
  *               zone_lru_lock (in mark_page_accessed, isolate_lru_page)
@@ -1372,16 +1371,13 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
         * Note that the page can not be free in this function as call of
         * try_to_unmap() must hold a reference on the page.
         */
-       mmu_notifier_range_init(&range, vma->vm_mm, vma->vm_start,
-                               min(vma->vm_end, vma->vm_start +
+       mmu_notifier_range_init(&range, vma->vm_mm, address,
+                               min(vma->vm_end, address +
                                    (PAGE_SIZE << compound_order(page))));
        if (PageHuge(page)) {
                /*
                 * If sharing is possible, start and end will be adjusted
                 * accordingly.
-                *
-                * If called for a huge page, caller must hold i_mmap_rwsem
-                * in write mode as it is possible to call huge_pmd_unshare.
                 */
                adjust_range_if_pmd_sharing_possible(vma, &range.start,
                                                     &range.end);
index 73fe23e..78eb8c5 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -666,8 +666,10 @@ static struct alien_cache *__alloc_alien_cache(int node, int entries,
        struct alien_cache *alc = NULL;
 
        alc = kmalloc_node(memsize, gfp, node);
-       init_arraycache(&alc->ac, entries, batch);
-       spin_lock_init(&alc->lock);
+       if (alc) {
+               init_arraycache(&alc->ac, entries, batch);
+               spin_lock_init(&alc->lock);
+       }
        return alc;
 }
 
index 36c0bef..1e3d0ec 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -3846,6 +3846,8 @@ void __check_heap_object(const void *ptr, unsigned long n, struct page *page,
        unsigned int offset;
        size_t object_size;
 
+       ptr = kasan_reset_tag(ptr);
+
        /* Find object and usable object size. */
        s = page->slab_cache;
 
index 852eb4e..14faadc 100644 (file)
@@ -247,7 +247,8 @@ static DEFINE_STATIC_KEY_FALSE_RO(bypass_usercopy_checks);
 /*
  * Validates that the given object is:
  * - not bogus address
- * - known-safe heap or stack object
+ * - fully contained by stack (or stack frame, when available)
+ * - fully within SLAB object (or object whitelist area, when available)
  * - not in kernel text
  */
 void __check_object_size(const void *ptr, unsigned long n, bool to_user)
@@ -262,9 +263,6 @@ void __check_object_size(const void *ptr, unsigned long n, bool to_user)
        /* Check for invalid addresses. */
        check_bogus_address((const unsigned long)ptr, n, to_user);
 
-       /* Check for bad heap object. */
-       check_heap_object(ptr, n, to_user);
-
        /* Check for bad stack object. */
        switch (check_stack_object(ptr, n)) {
        case NOT_STACK:
@@ -282,6 +280,9 @@ void __check_object_size(const void *ptr, unsigned long n, bool to_user)
                usercopy_abort("process stack", NULL, to_user, 0, n);
        }
 
+       /* Check for bad heap object. */
+       check_heap_object(ptr, n, to_user);
+
        /* Check for object in kernel to avoid text exposure. */
        check_kernel_text_object((const unsigned long)ptr, n, to_user);
 }
index 065c1ce..d59b5a7 100644 (file)
@@ -267,14 +267,10 @@ retry:
                VM_BUG_ON(dst_addr & ~huge_page_mask(h));
 
                /*
-                * Serialize via i_mmap_rwsem and hugetlb_fault_mutex.
-                * i_mmap_rwsem ensures the dst_pte remains valid even
-                * in the case of shared pmds.  fault mutex prevents
-                * races with other faulting threads.
+                * Serialize via hugetlb_fault_mutex
                 */
-               mapping = dst_vma->vm_file->f_mapping;
-               i_mmap_lock_read(mapping);
                idx = linear_page_index(dst_vma, dst_addr);
+               mapping = dst_vma->vm_file->f_mapping;
                hash = hugetlb_fault_mutex_hash(h, dst_mm, dst_vma, mapping,
                                                                idx, dst_addr);
                mutex_lock(&hugetlb_fault_mutex_table[hash]);
@@ -283,7 +279,6 @@ retry:
                dst_pte = huge_pte_alloc(dst_mm, dst_addr, huge_page_size(h));
                if (!dst_pte) {
                        mutex_unlock(&hugetlb_fault_mutex_table[hash]);
-                       i_mmap_unlock_read(mapping);
                        goto out_unlock;
                }
 
@@ -291,7 +286,6 @@ retry:
                dst_pteval = huge_ptep_get(dst_pte);
                if (!huge_pte_none(dst_pteval)) {
                        mutex_unlock(&hugetlb_fault_mutex_table[hash]);
-                       i_mmap_unlock_read(mapping);
                        goto out_unlock;
                }
 
@@ -299,7 +293,6 @@ retry:
                                                dst_addr, src_addr, &page);
 
                mutex_unlock(&hugetlb_fault_mutex_table[hash]);
-               i_mmap_unlock_read(mapping);
                vm_alloc_shared = vm_shared;
 
                cond_resched();
index 4df23d6..1ea0551 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -478,7 +478,7 @@ bool page_mapped(struct page *page)
                return true;
        if (PageHuge(page))
                return false;
-       for (i = 0; i < hpage_nr_pages(page); i++) {
+       for (i = 0; i < (1 << compound_order(page)); i++) {
                if (atomic_read(&page[i]._mapcount) >= 0)
                        return true;
        }
index a714c4f..e979705 100644 (file)
@@ -491,16 +491,6 @@ static unsigned long do_shrink_slab(struct shrink_control *shrinkctl,
                delta = freeable / 2;
        }
 
-       /*
-        * Make sure we apply some minimal pressure on default priority
-        * even on small cgroups. Stale objects are not only consuming memory
-        * by themselves, but can also hold a reference to a dying cgroup,
-        * preventing it from being reclaimed. A dying cgroup with all
-        * corresponding structures like per-cpu stats and kmem caches
-        * can be really big, so it may lead to a significant waste of memory.
-        */
-       delta = max_t(unsigned long long, delta, min(freeable, batch_size));
-
        total_scan += delta;
        if (total_scan < 0) {
                pr_err("shrink_slab: %pF negative objects to delete nr=%ld\n",
index 70417e9..314bbc8 100644 (file)
@@ -114,6 +114,7 @@ netdev_tx_t ax25_ip_xmit(struct sk_buff *skb)
        dst = (ax25_address *)(bp + 1);
        src = (ax25_address *)(bp + 8);
 
+       ax25_route_lock_use();
        route = ax25_get_route(dst, NULL);
        if (route) {
                digipeat = route->digipeat;
@@ -206,9 +207,8 @@ netdev_tx_t ax25_ip_xmit(struct sk_buff *skb)
        ax25_queue_xmit(skb, dev);
 
 put:
-       if (route)
-               ax25_put_route(route);
 
+       ax25_route_lock_unuse();
        return NETDEV_TX_OK;
 }
 
index a0eff32..66f74c8 100644 (file)
@@ -40,7 +40,7 @@
 #include <linux/export.h>
 
 static ax25_route *ax25_route_list;
-static DEFINE_RWLOCK(ax25_route_lock);
+DEFINE_RWLOCK(ax25_route_lock);
 
 void ax25_rt_device_down(struct net_device *dev)
 {
@@ -335,6 +335,7 @@ const struct seq_operations ax25_rt_seqops = {
  *     Find AX.25 route
  *
  *     Only routes with a reference count of zero can be destroyed.
+ *     Must be called with ax25_route_lock read locked.
  */
 ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev)
 {
@@ -342,7 +343,6 @@ ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev)
        ax25_route *ax25_def_rt = NULL;
        ax25_route *ax25_rt;
 
-       read_lock(&ax25_route_lock);
        /*
         *      Bind to the physical interface we heard them on, or the default
         *      route if none is found;
@@ -365,11 +365,6 @@ ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev)
        if (ax25_spe_rt != NULL)
                ax25_rt = ax25_spe_rt;
 
-       if (ax25_rt != NULL)
-               ax25_hold_route(ax25_rt);
-
-       read_unlock(&ax25_route_lock);
-
        return ax25_rt;
 }
 
@@ -400,9 +395,12 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
        ax25_route *ax25_rt;
        int err = 0;
 
-       if ((ax25_rt = ax25_get_route(addr, NULL)) == NULL)
+       ax25_route_lock_use();
+       ax25_rt = ax25_get_route(addr, NULL);
+       if (!ax25_rt) {
+               ax25_route_lock_unuse();
                return -EHOSTUNREACH;
-
+       }
        if ((ax25->ax25_dev = ax25_dev_ax25dev(ax25_rt->dev)) == NULL) {
                err = -EHOSTUNREACH;
                goto put;
@@ -437,8 +435,7 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
        }
 
 put:
-       ax25_put_route(ax25_rt);
-
+       ax25_route_lock_unuse();
        return err;
 }
 
index e8090f0..ef0dec2 100644 (file)
@@ -104,6 +104,9 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
 
                ret = cfg80211_get_station(real_netdev, neigh->addr, &sinfo);
 
+               /* free the TID stats immediately */
+               cfg80211_sinfo_release_content(&sinfo);
+
                dev_put(real_netdev);
                if (ret == -ENOENT) {
                        /* Node is not associated anymore! It would be
index 508f441..415d494 100644 (file)
@@ -20,7 +20,6 @@
 #include "main.h"
 
 #include <linux/atomic.h>
-#include <linux/bug.h>
 #include <linux/byteorder/generic.h>
 #include <linux/errno.h>
 #include <linux/gfp.h>
@@ -179,8 +178,10 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
        parent_dev = __dev_get_by_index((struct net *)parent_net,
                                        dev_get_iflink(net_dev));
        /* if we got a NULL parent_dev there is something broken.. */
-       if (WARN(!parent_dev, "Cannot find parent device"))
+       if (!parent_dev) {
+               pr_err("Cannot find parent device\n");
                return false;
+       }
 
        if (batadv_mutual_parents(net_dev, net, parent_dev, parent_net))
                return false;
index 5db5a0a..ffc83be 100644 (file)
@@ -221,10 +221,14 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb,
 
        netif_trans_update(soft_iface);
        vid = batadv_get_vid(skb, 0);
+
+       skb_reset_mac_header(skb);
        ethhdr = eth_hdr(skb);
 
        switch (ntohs(ethhdr->h_proto)) {
        case ETH_P_8021Q:
+               if (!pskb_may_pull(skb, sizeof(*vhdr)))
+                       goto dropped;
                vhdr = vlan_eth_hdr(skb);
 
                /* drop batman-in-batman packets to prevent loops */
index 7acfc83..7ee4fea 100644 (file)
 extern char bpfilter_umh_start;
 extern char bpfilter_umh_end;
 
-static struct umh_info info;
-/* since ip_getsockopt() can run in parallel, serialize access to umh */
-static DEFINE_MUTEX(bpfilter_lock);
-
-static void shutdown_umh(struct umh_info *info)
+static void shutdown_umh(void)
 {
        struct task_struct *tsk;
 
-       if (!info->pid)
+       if (bpfilter_ops.stop)
                return;
-       tsk = get_pid_task(find_vpid(info->pid), PIDTYPE_PID);
+
+       tsk = get_pid_task(find_vpid(bpfilter_ops.info.pid), PIDTYPE_PID);
        if (tsk) {
                force_sig(SIGKILL, tsk);
                put_task_struct(tsk);
        }
-       fput(info->pipe_to_umh);
-       fput(info->pipe_from_umh);
-       info->pid = 0;
 }
 
 static void __stop_umh(void)
 {
-       if (IS_ENABLED(CONFIG_INET)) {
-               bpfilter_process_sockopt = NULL;
-               shutdown_umh(&info);
-       }
-}
-
-static void stop_umh(void)
-{
-       mutex_lock(&bpfilter_lock);
-       __stop_umh();
-       mutex_unlock(&bpfilter_lock);
+       if (IS_ENABLED(CONFIG_INET))
+               shutdown_umh();
 }
 
 static int __bpfilter_process_sockopt(struct sock *sk, int optname,
@@ -63,10 +48,10 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname,
        req.cmd = optname;
        req.addr = (long __force __user)optval;
        req.len = optlen;
-       mutex_lock(&bpfilter_lock);
-       if (!info.pid)
+       if (!bpfilter_ops.info.pid)
                goto out;
-       n = __kernel_write(info.pipe_to_umh, &req, sizeof(req), &pos);
+       n = __kernel_write(bpfilter_ops.info.pipe_to_umh, &req, sizeof(req),
+                          &pos);
        if (n != sizeof(req)) {
                pr_err("write fail %zd\n", n);
                __stop_umh();
@@ -74,7 +59,8 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname,
                goto out;
        }
        pos = 0;
-       n = kernel_read(info.pipe_from_umh, &reply, sizeof(reply), &pos);
+       n = kernel_read(bpfilter_ops.info.pipe_from_umh, &reply, sizeof(reply),
+                       &pos);
        if (n != sizeof(reply)) {
                pr_err("read fail %zd\n", n);
                __stop_umh();
@@ -83,37 +69,59 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname,
        }
        ret = reply.status;
 out:
-       mutex_unlock(&bpfilter_lock);
        return ret;
 }
 
-static int __init load_umh(void)
+static int start_umh(void)
 {
        int err;
 
        /* fork usermode process */
-       info.cmdline = "bpfilter_umh";
        err = fork_usermode_blob(&bpfilter_umh_start,
                                 &bpfilter_umh_end - &bpfilter_umh_start,
-                                &info);
+                                &bpfilter_ops.info);
        if (err)
                return err;
-       pr_info("Loaded bpfilter_umh pid %d\n", info.pid);
+       bpfilter_ops.stop = false;
+       pr_info("Loaded bpfilter_umh pid %d\n", bpfilter_ops.info.pid);
 
        /* health check that usermode process started correctly */
        if (__bpfilter_process_sockopt(NULL, 0, NULL, 0, 0) != 0) {
-               stop_umh();
+               shutdown_umh();
                return -EFAULT;
        }
-       if (IS_ENABLED(CONFIG_INET))
-               bpfilter_process_sockopt = &__bpfilter_process_sockopt;
 
        return 0;
 }
 
+static int __init load_umh(void)
+{
+       int err;
+
+       mutex_lock(&bpfilter_ops.lock);
+       if (!bpfilter_ops.stop) {
+               err = -EFAULT;
+               goto out;
+       }
+       err = start_umh();
+       if (!err && IS_ENABLED(CONFIG_INET)) {
+               bpfilter_ops.sockopt = &__bpfilter_process_sockopt;
+               bpfilter_ops.start = &start_umh;
+       }
+out:
+       mutex_unlock(&bpfilter_ops.lock);
+       return err;
+}
+
 static void __exit fini_umh(void)
 {
-       stop_umh();
+       mutex_lock(&bpfilter_ops.lock);
+       if (IS_ENABLED(CONFIG_INET)) {
+               shutdown_umh();
+               bpfilter_ops.start = NULL;
+               bpfilter_ops.sockopt = NULL;
+       }
+       mutex_unlock(&bpfilter_ops.lock);
 }
 module_init(load_umh);
 module_exit(fini_umh);
index 40311d1..9ea6100 100644 (file)
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-       .section .init.rodata, "a"
+       .section .rodata, "a"
        .global bpfilter_umh_start
 bpfilter_umh_start:
        .incbin "net/bpfilter/bpfilter_umh"
index fe3c758..9e14767 100644 (file)
@@ -1128,6 +1128,8 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
                        err = -ENOMEM;
                        goto err_unlock;
                }
+               if (swdev_notify)
+                       fdb->added_by_user = 1;
                fdb->added_by_external_learn = 1;
                fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
        } else {
@@ -1147,6 +1149,9 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
                        modified = true;
                }
 
+               if (swdev_notify)
+                       fdb->added_by_user = 1;
+
                if (modified)
                        fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
        }
index 5372e20..48ddc60 100644 (file)
@@ -36,10 +36,10 @@ static inline int should_deliver(const struct net_bridge_port *p,
 
 int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
+       skb_push(skb, ETH_HLEN);
        if (!is_skb_forwardable(skb->dev, skb))
                goto drop;
 
-       skb_push(skb, ETH_HLEN);
        br_drop_fake_rtable(skb);
 
        if (skb->ip_summed == CHECKSUM_PARTIAL &&
@@ -65,6 +65,7 @@ EXPORT_SYMBOL_GPL(br_dev_queue_push_xmit);
 
 int br_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
+       skb->tstamp = 0;
        return NF_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING,
                       net, sk, skb, NULL, skb->dev,
                       br_dev_queue_push_xmit);
@@ -97,12 +98,11 @@ static void __br_forward(const struct net_bridge_port *to,
                net = dev_net(indev);
        } else {
                if (unlikely(netpoll_tx_running(to->br->dev))) {
-                       if (!is_skb_forwardable(skb->dev, skb)) {
+                       skb_push(skb, ETH_HLEN);
+                       if (!is_skb_forwardable(skb->dev, skb))
                                kfree_skb(skb);
-                       } else {
-                               skb_push(skb, ETH_HLEN);
+                       else
                                br_netpoll_send_skb(to, skb);
-                       }
                        return;
                }
                br_hook = NF_BR_LOCAL_OUT;
index d21a236..c93c35b 100644 (file)
@@ -265,7 +265,7 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_
                struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
                int ret;
 
-               if (neigh->hh.hh_len) {
+               if ((neigh->nud_state & NUD_CONNECTED) && neigh->hh.hh_len) {
                        neigh_hh_bridge(&neigh->hh, skb);
                        skb->dev = nf_bridge->physindev;
                        ret = br_handle_frame_finish(net, sk, skb);
index 94039f5..564710f 100644 (file)
@@ -131,6 +131,7 @@ int br_validate_ipv6(struct net *net, struct sk_buff *skb)
                                        IPSTATS_MIB_INDISCARDS);
                        goto drop;
                }
+               hdr = ipv6_hdr(skb);
        }
        if (hdr->nexthdr == NEXTHDR_HOP && br_nf_check_hbh_len(skb))
                goto drop;
index d240b3e..eabf8bf 100644 (file)
@@ -107,6 +107,7 @@ struct br_tunnel_info {
 /* private vlan flags */
 enum {
        BR_VLFLAG_PER_PORT_STATS = BIT(0),
+       BR_VLFLAG_ADDED_BY_SWITCHDEV = BIT(1),
 };
 
 /**
index 4a2f311..96abf8f 100644 (file)
@@ -80,16 +80,18 @@ static bool __vlan_add_flags(struct net_bridge_vlan *v, u16 flags)
 }
 
 static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br,
-                         u16 vid, u16 flags, struct netlink_ext_ack *extack)
+                         struct net_bridge_vlan *v, u16 flags,
+                         struct netlink_ext_ack *extack)
 {
        int err;
 
        /* Try switchdev op first. In case it is not supported, fallback to
         * 8021q add.
         */
-       err = br_switchdev_port_vlan_add(dev, vid, flags, extack);
+       err = br_switchdev_port_vlan_add(dev, v->vid, flags, extack);
        if (err == -EOPNOTSUPP)
-               return vlan_vid_add(dev, br->vlan_proto, vid);
+               return vlan_vid_add(dev, br->vlan_proto, v->vid);
+       v->priv_flags |= BR_VLFLAG_ADDED_BY_SWITCHDEV;
        return err;
 }
 
@@ -121,19 +123,17 @@ static void __vlan_del_list(struct net_bridge_vlan *v)
 }
 
 static int __vlan_vid_del(struct net_device *dev, struct net_bridge *br,
-                         u16 vid)
+                         const struct net_bridge_vlan *v)
 {
        int err;
 
        /* Try switchdev op first. In case it is not supported, fallback to
         * 8021q del.
         */
-       err = br_switchdev_port_vlan_del(dev, vid);
-       if (err == -EOPNOTSUPP) {
-               vlan_vid_del(dev, br->vlan_proto, vid);
-               return 0;
-       }
-       return err;
+       err = br_switchdev_port_vlan_del(dev, v->vid);
+       if (!(v->priv_flags & BR_VLFLAG_ADDED_BY_SWITCHDEV))
+               vlan_vid_del(dev, br->vlan_proto, v->vid);
+       return err == -EOPNOTSUPP ? 0 : err;
 }
 
 /* Returns a master vlan, if it didn't exist it gets created. In all cases a
@@ -242,7 +242,7 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags,
                 * This ensures tagged traffic enters the bridge when
                 * promiscuous mode is disabled by br_manage_promisc().
                 */
-               err = __vlan_vid_add(dev, br, v->vid, flags, extack);
+               err = __vlan_vid_add(dev, br, v, flags, extack);
                if (err)
                        goto out;
 
@@ -305,7 +305,7 @@ out_fdb_insert:
 
 out_filt:
        if (p) {
-               __vlan_vid_del(dev, br, v->vid);
+               __vlan_vid_del(dev, br, v);
                if (masterv) {
                        if (v->stats && masterv->stats != v->stats)
                                free_percpu(v->stats);
@@ -338,7 +338,7 @@ static int __vlan_del(struct net_bridge_vlan *v)
 
        __vlan_delete_pvid(vg, v->vid);
        if (p) {
-               err = __vlan_vid_del(p->dev, p->br, v->vid);
+               err = __vlan_vid_del(p->dev, p->br, v);
                if (err)
                        goto out;
        } else {
index 4918287..6693e20 100644 (file)
@@ -1137,14 +1137,16 @@ static int do_replace(struct net *net, const void __user *user,
        tmp.name[sizeof(tmp.name) - 1] = 0;
 
        countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
-       newinfo = vmalloc(sizeof(*newinfo) + countersize);
+       newinfo = __vmalloc(sizeof(*newinfo) + countersize, GFP_KERNEL_ACCOUNT,
+                           PAGE_KERNEL);
        if (!newinfo)
                return -ENOMEM;
 
        if (countersize)
                memset(newinfo->counters, 0, countersize);
 
-       newinfo->entries = vmalloc(tmp.entries_size);
+       newinfo->entries = __vmalloc(tmp.entries_size, GFP_KERNEL_ACCOUNT,
+                                    PAGE_KERNEL);
        if (!newinfo->entries) {
                ret = -ENOMEM;
                goto free_newinfo;
@@ -2291,9 +2293,12 @@ static int compat_do_replace(struct net *net, void __user *user,
 
        xt_compat_lock(NFPROTO_BRIDGE);
 
-       ret = xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries);
-       if (ret < 0)
-               goto out_unlock;
+       if (tmp.nentries) {
+               ret = xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries);
+               if (ret < 0)
+                       goto out_unlock;
+       }
+
        ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
        if (ret < 0)
                goto out_unlock;
index 08cbed7..419e8ed 100644 (file)
@@ -229,6 +229,7 @@ static bool reject6_br_csum_ok(struct sk_buff *skb, int hook)
            pskb_trim_rcsum(skb, ntohs(ip6h->payload_len) + sizeof(*ip6h)))
                return false;
 
+       ip6h = ipv6_hdr(skb);
        thoff = ipv6_skip_exthdr(skb, ((u8*)(ip6h+1) - skb->data), &proto, &fo);
        if (thoff < 0 || thoff >= skb->len || (fo & htons(~0x7)) != 0)
                return false;
index 0af8f0d..79bb8af 100644 (file)
@@ -67,6 +67,9 @@
  */
 #define MAX_NFRAMES 256
 
+/* limit timers to 400 days for sending/timeouts */
+#define BCM_TIMER_SEC_MAX (400 * 24 * 60 * 60)
+
 /* use of last_frames[index].flags */
 #define RX_RECV    0x40 /* received data for this element */
 #define RX_THR     0x80 /* element not been sent due to throttle feature */
@@ -140,6 +143,22 @@ static inline ktime_t bcm_timeval_to_ktime(struct bcm_timeval tv)
        return ktime_set(tv.tv_sec, tv.tv_usec * NSEC_PER_USEC);
 }
 
+/* check limitations for timeval provided by user */
+static bool bcm_is_invalid_tv(struct bcm_msg_head *msg_head)
+{
+       if ((msg_head->ival1.tv_sec < 0) ||
+           (msg_head->ival1.tv_sec > BCM_TIMER_SEC_MAX) ||
+           (msg_head->ival1.tv_usec < 0) ||
+           (msg_head->ival1.tv_usec >= USEC_PER_SEC) ||
+           (msg_head->ival2.tv_sec < 0) ||
+           (msg_head->ival2.tv_sec > BCM_TIMER_SEC_MAX) ||
+           (msg_head->ival2.tv_usec < 0) ||
+           (msg_head->ival2.tv_usec >= USEC_PER_SEC))
+               return true;
+
+       return false;
+}
+
 #define CFSIZ(flags) ((flags & CAN_FD_FRAME) ? CANFD_MTU : CAN_MTU)
 #define OPSIZ sizeof(struct bcm_op)
 #define MHSIZ sizeof(struct bcm_msg_head)
@@ -873,6 +892,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
        if (msg_head->nframes < 1 || msg_head->nframes > MAX_NFRAMES)
                return -EINVAL;
 
+       /* check timeval limitations */
+       if ((msg_head->flags & SETTIMER) && bcm_is_invalid_tv(msg_head))
+               return -EINVAL;
+
        /* check the given can_id */
        op = bcm_find_op(&bo->tx_ops, msg_head, ifindex);
        if (op) {
@@ -1053,6 +1076,10 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
             (!(msg_head->can_id & CAN_RTR_FLAG))))
                return -EINVAL;
 
+       /* check timeval limitations */
+       if ((msg_head->flags & SETTIMER) && bcm_is_invalid_tv(msg_head))
+               return -EINVAL;
+
        /* check the given can_id */
        op = bcm_find_op(&bo->rx_ops, msg_head, ifindex);
        if (op) {
index faa3da8..5385934 100644 (file)
@@ -416,13 +416,29 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
        while (modidx < MAX_MODFUNCTIONS && gwj->mod.modfunc[modidx])
                (*gwj->mod.modfunc[modidx++])(cf, &gwj->mod);
 
-       /* check for checksum updates when the CAN frame has been modified */
+       /* Has the CAN frame been modified? */
        if (modidx) {
-               if (gwj->mod.csumfunc.crc8)
+               /* get available space for the processed CAN frame type */
+               int max_len = nskb->len - offsetof(struct can_frame, data);
+
+               /* dlc may have changed, make sure it fits to the CAN frame */
+               if (cf->can_dlc > max_len)
+                       goto out_delete;
+
+               /* check for checksum updates in classic CAN length only */
+               if (gwj->mod.csumfunc.crc8) {
+                       if (cf->can_dlc > 8)
+                               goto out_delete;
+
                        (*gwj->mod.csumfunc.crc8)(cf, &gwj->mod.csum.crc8);
+               }
+
+               if (gwj->mod.csumfunc.xor) {
+                       if (cf->can_dlc > 8)
+                               goto out_delete;
 
-               if (gwj->mod.csumfunc.xor)
                        (*gwj->mod.csumfunc.xor)(cf, &gwj->mod.csum.xor);
+               }
        }
 
        /* clear the skb timestamp if not configured the other way */
@@ -434,6 +450,14 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
                gwj->dropped_frames++;
        else
                gwj->handled_frames++;
+
+       return;
+
+ out_delete:
+       /* delete frame due to misconfiguration */
+       gwj->deleted_frames++;
+       kfree_skb(nskb);
+       return;
 }
 
 static inline int cgw_register_filter(struct net *net, struct cgw_job *gwj)
index 87afb9e..9cab802 100644 (file)
@@ -255,6 +255,7 @@ enum {
        Opt_nocephx_sign_messages,
        Opt_tcp_nodelay,
        Opt_notcp_nodelay,
+       Opt_abort_on_full,
 };
 
 static match_table_t opt_tokens = {
@@ -280,6 +281,7 @@ static match_table_t opt_tokens = {
        {Opt_nocephx_sign_messages, "nocephx_sign_messages"},
        {Opt_tcp_nodelay, "tcp_nodelay"},
        {Opt_notcp_nodelay, "notcp_nodelay"},
+       {Opt_abort_on_full, "abort_on_full"},
        {-1, NULL}
 };
 
@@ -535,6 +537,10 @@ ceph_parse_options(char *options, const char *dev_name,
                        opt->flags &= ~CEPH_OPT_TCP_NODELAY;
                        break;
 
+               case Opt_abort_on_full:
+                       opt->flags |= CEPH_OPT_ABORT_ON_FULL;
+                       break;
+
                default:
                        BUG_ON(token);
                }
@@ -549,7 +555,8 @@ out:
 }
 EXPORT_SYMBOL(ceph_parse_options);
 
-int ceph_print_client_options(struct seq_file *m, struct ceph_client *client)
+int ceph_print_client_options(struct seq_file *m, struct ceph_client *client,
+                             bool show_all)
 {
        struct ceph_options *opt = client->options;
        size_t pos = m->count;
@@ -574,6 +581,8 @@ int ceph_print_client_options(struct seq_file *m, struct ceph_client *client)
                seq_puts(m, "nocephx_sign_messages,");
        if ((opt->flags & CEPH_OPT_TCP_NODELAY) == 0)
                seq_puts(m, "notcp_nodelay,");
+       if (show_all && (opt->flags & CEPH_OPT_ABORT_ON_FULL))
+               seq_puts(m, "abort_on_full,");
 
        if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT)
                seq_printf(m, "mount_timeout=%d,",
index 0295260..46f6570 100644 (file)
@@ -375,7 +375,7 @@ static int client_options_show(struct seq_file *s, void *p)
        struct ceph_client *client = s->private;
        int ret;
 
-       ret = ceph_print_client_options(s, client);
+       ret = ceph_print_client_options(s, client, true);
        if (ret)
                return ret;
 
index d571828..3661cdd 100644 (file)
@@ -3206,9 +3206,10 @@ void ceph_con_keepalive(struct ceph_connection *con)
        dout("con_keepalive %p\n", con);
        mutex_lock(&con->mutex);
        clear_standby(con);
+       con_flag_set(con, CON_FLAG_KEEPALIVE_PENDING);
        mutex_unlock(&con->mutex);
-       if (con_flag_test_and_set(con, CON_FLAG_KEEPALIVE_PENDING) == 0 &&
-           con_flag_test_and_set(con, CON_FLAG_WRITE_PENDING) == 0)
+
+       if (con_flag_test_and_set(con, CON_FLAG_WRITE_PENDING) == 0)
                queue_con(con);
 }
 EXPORT_SYMBOL(ceph_con_keepalive);
index d23a9f8..fa9530d 100644 (file)
@@ -2315,7 +2315,7 @@ again:
                   (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) ||
                    pool_full(osdc, req->r_t.base_oloc.pool))) {
                dout("req %p full/pool_full\n", req);
-               if (osdc->abort_on_full) {
+               if (ceph_test_opt(osdc->client, ABORT_ON_FULL)) {
                        err = -ENOSPC;
                } else {
                        pr_warn_ratelimited("FULL or reached pool quota\n");
@@ -2545,7 +2545,7 @@ static void ceph_osdc_abort_on_full(struct ceph_osd_client *osdc)
 {
        bool victims = false;
 
-       if (osdc->abort_on_full &&
+       if (ceph_test_opt(osdc->client, ABORT_ON_FULL) &&
            (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) || have_pool_full(osdc)))
                for_each_request(osdc, abort_on_full_fn, &victims);
 }
index 82f2002..8e276e0 100644 (file)
@@ -8712,6 +8712,9 @@ int init_dummy_netdev(struct net_device *dev)
        set_bit(__LINK_STATE_PRESENT, &dev->state);
        set_bit(__LINK_STATE_START, &dev->state);
 
+       /* napi_busy_loop stats accounting wants this */
+       dev_net_set(dev, &init_net);
+
        /* Note : We dont allocate pcpu_refcnt for dummy devices,
         * because users of this 'device' dont need to change
         * its refcount.
index 447dd1b..7a54dc1 100644 (file)
@@ -2020,18 +2020,19 @@ static inline int __bpf_tx_skb(struct net_device *dev, struct sk_buff *skb)
 static int __bpf_redirect_no_mac(struct sk_buff *skb, struct net_device *dev,
                                 u32 flags)
 {
-       /* skb->mac_len is not set on normal egress */
-       unsigned int mlen = skb->network_header - skb->mac_header;
+       unsigned int mlen = skb_network_offset(skb);
 
-       __skb_pull(skb, mlen);
+       if (mlen) {
+               __skb_pull(skb, mlen);
 
-       /* At ingress, the mac header has already been pulled once.
-        * At egress, skb_pospull_rcsum has to be done in case that
-        * the skb is originated from ingress (i.e. a forwarded skb)
-        * to ensure that rcsum starts at net header.
-        */
-       if (!skb_at_tc_ingress(skb))
-               skb_postpull_rcsum(skb, skb_mac_header(skb), mlen);
+               /* At ingress, the mac header has already been pulled once.
+                * At egress, skb_pospull_rcsum has to be done in case that
+                * the skb is originated from ingress (i.e. a forwarded skb)
+                * to ensure that rcsum starts at net header.
+                */
+               if (!skb_at_tc_ingress(skb))
+                       skb_postpull_rcsum(skb, skb_mac_header(skb), mlen);
+       }
        skb_pop_mac_header(skb);
        skb_reset_mac_len(skb);
        return flags & BPF_F_INGRESS ?
@@ -4111,14 +4112,20 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
                /* Only some socketops are supported */
                switch (optname) {
                case SO_RCVBUF:
+                       val = min_t(u32, val, sysctl_rmem_max);
                        sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
                        sk->sk_rcvbuf = max_t(int, val * 2, SOCK_MIN_RCVBUF);
                        break;
                case SO_SNDBUF:
+                       val = min_t(u32, val, sysctl_wmem_max);
                        sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
                        sk->sk_sndbuf = max_t(int, val * 2, SOCK_MIN_SNDBUF);
                        break;
                case SO_MAX_PACING_RATE: /* 32bit version */
+                       if (val != ~0U)
+                               cmpxchg(&sk->sk_pacing_status,
+                                       SK_PACING_NONE,
+                                       SK_PACING_NEEDED);
                        sk->sk_max_pacing_rate = (val == ~0U) ? ~0UL : val;
                        sk->sk_pacing_rate = min(sk->sk_pacing_rate,
                                                 sk->sk_max_pacing_rate);
@@ -4132,7 +4139,10 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
                        sk->sk_rcvlowat = val ? : 1;
                        break;
                case SO_MARK:
-                       sk->sk_mark = val;
+                       if (sk->sk_mark != val) {
+                               sk->sk_mark = val;
+                               sk_dst_reset(sk);
+                       }
                        break;
                default:
                        ret = -EINVAL;
@@ -4203,7 +4213,7 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
                        /* Only some options are supported */
                        switch (optname) {
                        case TCP_BPF_IW:
-                               if (val <= 0 || tp->data_segs_out > 0)
+                               if (val <= 0 || tp->data_segs_out > tp->syn_data)
                                        ret = -EINVAL;
                                else
                                        tp->snd_cwnd = val;
@@ -5309,7 +5319,7 @@ bpf_base_func_proto(enum bpf_func_id func_id)
        case BPF_FUNC_trace_printk:
                if (capable(CAP_SYS_ADMIN))
                        return bpf_get_trace_printk_proto();
-               /* else: fall through */
+               /* else, fall through */
        default:
                return NULL;
        }
index 3e85437..a648568 100644 (file)
@@ -63,6 +63,7 @@ static int run_lwt_bpf(struct sk_buff *skb, struct bpf_lwt_prog *lwt,
                                     lwt->name ? : "<unknown>");
                        ret = BPF_OK;
                } else {
+                       skb_reset_mac_header(skb);
                        ret = skb_do_redirect(skb);
                        if (ret == 0)
                                ret = BPF_REDIRECT;
index 763a7b0..4230400 100644 (file)
@@ -18,6 +18,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/slab.h>
+#include <linux/kmemleak.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -443,12 +444,14 @@ static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
        ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
        if (!ret)
                return NULL;
-       if (size <= PAGE_SIZE)
+       if (size <= PAGE_SIZE) {
                buckets = kzalloc(size, GFP_ATOMIC);
-       else
+       } else {
                buckets = (struct neighbour __rcu **)
                          __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
                                           get_order(size));
+               kmemleak_alloc(buckets, size, 1, GFP_ATOMIC);
+       }
        if (!buckets) {
                kfree(ret);
                return NULL;
@@ -468,10 +471,12 @@ static void neigh_hash_free_rcu(struct rcu_head *head)
        size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
        struct neighbour __rcu **buckets = nht->hash_buckets;
 
-       if (size <= PAGE_SIZE)
+       if (size <= PAGE_SIZE) {
                kfree(buckets);
-       else
+       } else {
+               kmemleak_free(buckets);
                free_pages((unsigned long)buckets, get_order(size));
+       }
        kfree(nht);
 }
 
@@ -1002,7 +1007,7 @@ static void neigh_probe(struct neighbour *neigh)
        if (neigh->ops->solicit)
                neigh->ops->solicit(neigh, skb);
        atomic_inc(&neigh->probes);
-       kfree_skb(skb);
+       consume_skb(skb);
 }
 
 /* Called when a timer expires for a neighbour entry. */
index 37317ff..26d8484 100644 (file)
@@ -5270,7 +5270,6 @@ struct sk_buff *alloc_skb_with_frags(unsigned long header_len,
        unsigned long chunk;
        struct sk_buff *skb;
        struct page *page;
-       gfp_t gfp_head;
        int i;
 
        *errcode = -EMSGSIZE;
@@ -5280,12 +5279,8 @@ struct sk_buff *alloc_skb_with_frags(unsigned long header_len,
        if (npages > MAX_SKB_FRAGS)
                return NULL;
 
-       gfp_head = gfp_mask;
-       if (gfp_head & __GFP_DIRECT_RECLAIM)
-               gfp_head |= __GFP_RETRY_MAYFAIL;
-
        *errcode = -ENOBUFS;
-       skb = alloc_skb(header_len, gfp_head);
+       skb = alloc_skb(header_len, gfp_mask);
        if (!skb)
                return NULL;
 
index d6d5c20..8c82660 100644 (file)
@@ -545,8 +545,7 @@ static void sk_psock_destroy_deferred(struct work_struct *gc)
        struct sk_psock *psock = container_of(gc, struct sk_psock, gc);
 
        /* No sk_callback_lock since already detached. */
-       if (psock->parser.enabled)
-               strp_done(&psock->parser.strp);
+       strp_done(&psock->parser.strp);
 
        cancel_work_sync(&psock->work);
 
index 6aa2e7e..bc3512f 100644 (file)
@@ -2380,7 +2380,7 @@ int __sk_mem_raise_allocated(struct sock *sk, int size, int amt, int kind)
        }
 
        if (sk_has_memory_pressure(sk)) {
-               int alloc;
+               u64 alloc;
 
                if (!sk_under_memory_pressure(sk))
                        return 1;
index 6eb837a..baaaeb2 100644 (file)
@@ -202,7 +202,7 @@ static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
 static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
                                           u8 pkt, u8 opt, u8 *val, u8 len)
 {
-       if (ccid->ccid_ops->ccid_hc_tx_parse_options == NULL)
+       if (!ccid || !ccid->ccid_ops->ccid_hc_tx_parse_options)
                return 0;
        return ccid->ccid_ops->ccid_hc_tx_parse_options(sk, pkt, opt, val, len);
 }
@@ -214,7 +214,7 @@ static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
 static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
                                           u8 pkt, u8 opt, u8 *val, u8 len)
 {
-       if (ccid->ccid_ops->ccid_hc_rx_parse_options == NULL)
+       if (!ccid || !ccid->ccid_ops->ccid_hc_rx_parse_options)
                return 0;
        return ccid->ccid_ops->ccid_hc_rx_parse_options(sk, pkt, opt, val, len);
 }
index d0b3e69..0962f92 100644 (file)
@@ -56,7 +56,7 @@
 #include <net/dn_neigh.h>
 #include <net/dn_fib.h>
 
-#define DN_IFREQ_SIZE (sizeof(struct ifreq) - sizeof(struct sockaddr) + sizeof(struct sockaddr_dn))
+#define DN_IFREQ_SIZE (offsetof(struct ifreq, ifr_ifru) + sizeof(struct sockaddr_dn))
 
 static char dn_rt_all_end_mcast[ETH_ALEN] = {0xAB,0x00,0x00,0x04,0x00,0x00};
 static char dn_rt_all_rt_mcast[ETH_ALEN]  = {0xAB,0x00,0x00,0x03,0x00,0x00};
index 71bb15f..54f5551 100644 (file)
@@ -205,6 +205,8 @@ static void dsa_master_reset_mtu(struct net_device *dev)
        rtnl_unlock();
 }
 
+static struct lock_class_key dsa_master_addr_list_lock_key;
+
 int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
 {
        int ret;
@@ -218,6 +220,8 @@ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
        wmb();
 
        dev->dsa_ptr = cpu_dp;
+       lockdep_set_class(&dev->addr_list_lock,
+                         &dsa_master_addr_list_lock_key);
 
        ret = dsa_master_ethtool_setup(dev);
        if (ret)
index a3fcc1d..a1c9fe1 100644 (file)
@@ -140,11 +140,14 @@ static int dsa_slave_close(struct net_device *dev)
 static void dsa_slave_change_rx_flags(struct net_device *dev, int change)
 {
        struct net_device *master = dsa_slave_to_master(dev);
-
-       if (change & IFF_ALLMULTI)
-               dev_set_allmulti(master, dev->flags & IFF_ALLMULTI ? 1 : -1);
-       if (change & IFF_PROMISC)
-               dev_set_promiscuity(master, dev->flags & IFF_PROMISC ? 1 : -1);
+       if (dev->flags & IFF_UP) {
+               if (change & IFF_ALLMULTI)
+                       dev_set_allmulti(master,
+                                        dev->flags & IFF_ALLMULTI ? 1 : -1);
+               if (change & IFF_PROMISC)
+                       dev_set_promiscuity(master,
+                                           dev->flags & IFF_PROMISC ? 1 : -1);
+       }
 }
 
 static void dsa_slave_set_rx_mode(struct net_device *dev)
@@ -639,7 +642,7 @@ static int dsa_slave_set_eee(struct net_device *dev, struct ethtool_eee *e)
        int ret;
 
        /* Port's PHY and MAC both need to be EEE capable */
-       if (!dev->phydev && !dp->pl)
+       if (!dev->phydev || !dp->pl)
                return -ENODEV;
 
        if (!ds->ops->set_mac_eee)
@@ -659,7 +662,7 @@ static int dsa_slave_get_eee(struct net_device *dev, struct ethtool_eee *e)
        int ret;
 
        /* Port's PHY and MAC both need to be EEE capable */
-       if (!dev->phydev && !dp->pl)
+       if (!dev->phydev || !dp->pl)
                return -ENODEV;
 
        if (!ds->ops->get_mac_eee)
index 5e04ed2..1e976bb 100644 (file)
@@ -1,28 +1,54 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <linux/init.h>
+#include <linux/module.h>
 #include <linux/uaccess.h>
 #include <linux/bpfilter.h>
 #include <uapi/linux/bpf.h>
 #include <linux/wait.h>
 #include <linux/kmod.h>
+#include <linux/fs.h>
+#include <linux/file.h>
 
-int (*bpfilter_process_sockopt)(struct sock *sk, int optname,
-                               char __user *optval,
-                               unsigned int optlen, bool is_set);
-EXPORT_SYMBOL_GPL(bpfilter_process_sockopt);
+struct bpfilter_umh_ops bpfilter_ops;
+EXPORT_SYMBOL_GPL(bpfilter_ops);
+
+static void bpfilter_umh_cleanup(struct umh_info *info)
+{
+       mutex_lock(&bpfilter_ops.lock);
+       bpfilter_ops.stop = true;
+       fput(info->pipe_to_umh);
+       fput(info->pipe_from_umh);
+       info->pid = 0;
+       mutex_unlock(&bpfilter_ops.lock);
+}
 
 static int bpfilter_mbox_request(struct sock *sk, int optname,
                                 char __user *optval,
                                 unsigned int optlen, bool is_set)
 {
-       if (!bpfilter_process_sockopt) {
-               int err = request_module("bpfilter");
+       int err;
+       mutex_lock(&bpfilter_ops.lock);
+       if (!bpfilter_ops.sockopt) {
+               mutex_unlock(&bpfilter_ops.lock);
+               err = request_module("bpfilter");
+               mutex_lock(&bpfilter_ops.lock);
 
                if (err)
-                       return err;
-               if (!bpfilter_process_sockopt)
-                       return -ECHILD;
+                       goto out;
+               if (!bpfilter_ops.sockopt) {
+                       err = -ECHILD;
+                       goto out;
+               }
+       }
+       if (bpfilter_ops.stop) {
+               err = bpfilter_ops.start();
+               if (err)
+                       goto out;
        }
-       return bpfilter_process_sockopt(sk, optname, optval, optlen, is_set);
+       err = bpfilter_ops.sockopt(sk, optname, optval, optlen, is_set);
+out:
+       mutex_unlock(&bpfilter_ops.lock);
+       return err;
 }
 
 int bpfilter_ip_set_sockopt(struct sock *sk, int optname, char __user *optval,
@@ -41,3 +67,15 @@ int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval,
 
        return bpfilter_mbox_request(sk, optname, optval, len, false);
 }
+
+static int __init bpfilter_sockopt_init(void)
+{
+       mutex_init(&bpfilter_ops.lock);
+       bpfilter_ops.stop = true;
+       bpfilter_ops.info.cmdline = "bpfilter_umh";
+       bpfilter_ops.info.cleanup = &bpfilter_umh_cleanup;
+
+       return 0;
+}
+
+module_init(bpfilter_sockopt_init);
index 04ba321..e258a00 100644 (file)
@@ -1826,7 +1826,7 @@ put_tgt_net:
        if (fillargs.netnsid >= 0)
                put_net(tgt_net);
 
-       return err < 0 ? err : skb->len;
+       return skb->len ? : err;
 }
 
 static void rtmsg_ifa(int event, struct in_ifaddr *ifa, struct nlmsghdr *nlh,
index 6df95be..fe4f6a6 100644 (file)
@@ -203,7 +203,7 @@ static void fib_flush(struct net *net)
                struct fib_table *tb;
 
                hlist_for_each_entry_safe(tb, tmp, head, tb_hlist)
-                       flushed += fib_table_flush(net, tb);
+                       flushed += fib_table_flush(net, tb, false);
        }
 
        if (flushed)
@@ -1463,7 +1463,7 @@ static void ip_fib_net_exit(struct net *net)
 
                hlist_for_each_entry_safe(tb, tmp, head, tb_hlist) {
                        hlist_del(&tb->tb_hlist);
-                       fib_table_flush(net, tb);
+                       fib_table_flush(net, tb, true);
                        fib_free_table(tb);
                }
        }
index 237c9f7..a573e37 100644 (file)
@@ -1856,7 +1856,7 @@ void fib_table_flush_external(struct fib_table *tb)
 }
 
 /* Caller must hold RTNL. */
-int fib_table_flush(struct net *net, struct fib_table *tb)
+int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all)
 {
        struct trie *t = (struct trie *)tb->tb_data;
        struct key_vector *pn = t->kv;
@@ -1904,8 +1904,17 @@ int fib_table_flush(struct net *net, struct fib_table *tb)
                hlist_for_each_entry_safe(fa, tmp, &n->leaf, fa_list) {
                        struct fib_info *fi = fa->fa_info;
 
-                       if (!fi || !(fi->fib_flags & RTNH_F_DEAD) ||
-                           tb->tb_id != fa->tb_id) {
+                       if (!fi || tb->tb_id != fa->tb_id ||
+                           (!(fi->fib_flags & RTNH_F_DEAD) &&
+                            !fib_props[fa->fa_type].error)) {
+                               slen = fa->fa_slen;
+                               continue;
+                       }
+
+                       /* Do not flush error routes if network namespace is
+                        * not being dismantled
+                        */
+                       if (!flush_all && fib_props[fa->fa_type].error) {
                                slen = fa->fa_slen;
                                continue;
                        }
index 0c9f171..437070d 100644 (file)
@@ -1020,10 +1020,11 @@ static int gue_err(struct sk_buff *skb, u32 info)
 {
        int transport_offset = skb_transport_offset(skb);
        struct guehdr *guehdr;
-       size_t optlen;
+       size_t len, optlen;
        int ret;
 
-       if (skb->len < sizeof(struct udphdr) + sizeof(struct guehdr))
+       len = sizeof(struct udphdr) + sizeof(struct guehdr);
+       if (!pskb_may_pull(skb, len))
                return -EINVAL;
 
        guehdr = (struct guehdr *)&udp_hdr(skb)[1];
@@ -1058,6 +1059,10 @@ static int gue_err(struct sk_buff *skb, u32 info)
 
        optlen = guehdr->hlen << 2;
 
+       if (!pskb_may_pull(skb, len + optlen))
+               return -EINVAL;
+
+       guehdr = (struct guehdr *)&udp_hdr(skb)[1];
        if (validate_gue_flags(guehdr, optlen))
                return -EINVAL;
 
@@ -1065,7 +1070,8 @@ static int gue_err(struct sk_buff *skb, u32 info)
         * recursion. Besides, this kind of encapsulation can't even be
         * configured currently. Discard this.
         */
-       if (guehdr->proto_ctype == IPPROTO_UDP)
+       if (guehdr->proto_ctype == IPPROTO_UDP ||
+           guehdr->proto_ctype == IPPROTO_UDPLITE)
                return -EOPNOTSUPP;
 
        skb_set_transport_header(skb, -(int)sizeof(struct icmphdr));
index a4bf22e..7c4a41d 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/spinlock.h>
 #include <net/protocol.h>
 #include <net/gre.h>
+#include <net/erspan.h>
 
 #include <net/icmp.h>
 #include <net/route.h>
@@ -119,6 +120,22 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
                        hdr_len += 4;
        }
        tpi->hdr_len = hdr_len;
+
+       /* ERSPAN ver 1 and 2 protocol sets GRE key field
+        * to 0 and sets the configured key in the
+        * inner erspan header field
+        */
+       if (greh->protocol == htons(ETH_P_ERSPAN) ||
+           greh->protocol == htons(ETH_P_ERSPAN2)) {
+               struct erspan_base_hdr *ershdr;
+
+               if (!pskb_may_pull(skb, nhs + hdr_len + sizeof(*ershdr)))
+                       return -EINVAL;
+
+               ershdr = (struct erspan_base_hdr *)options;
+               tpi->key = cpu_to_be32(get_session_id(ershdr));
+       }
+
        return hdr_len;
 }
 EXPORT_SYMBOL(gre_parse_header);
index 1a4e9ff..5731670 100644 (file)
@@ -108,6 +108,7 @@ static size_t inet_sk_attr_size(struct sock *sk,
                + nla_total_size(1) /* INET_DIAG_TOS */
                + nla_total_size(1) /* INET_DIAG_TCLASS */
                + nla_total_size(4) /* INET_DIAG_MARK */
+               + nla_total_size(4) /* INET_DIAG_CLASS_ID */
                + nla_total_size(sizeof(struct inet_diag_meminfo))
                + nla_total_size(sizeof(struct inet_diag_msg))
                + nla_total_size(SK_MEMINFO_VARS * sizeof(u32))
@@ -287,12 +288,19 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
                        goto errout;
        }
 
-       if (ext & (1 << (INET_DIAG_CLASS_ID - 1))) {
+       if (ext & (1 << (INET_DIAG_CLASS_ID - 1)) ||
+           ext & (1 << (INET_DIAG_TCLASS - 1))) {
                u32 classid = 0;
 
 #ifdef CONFIG_SOCK_CGROUP_DATA
                classid = sock_cgroup_classid(&sk->sk_cgrp_data);
 #endif
+               /* Fallback to socket priority if class id isn't set.
+                * Classful qdiscs use it as direct reference to class.
+                * For cgroup2 classid is always zero.
+                */
+               if (!classid)
+                       classid = sk->sk_priority;
 
                if (nla_put_u32(skb, INET_DIAG_CLASS_ID, classid))
                        goto errout;
index d757b96..be77859 100644 (file)
@@ -216,6 +216,7 @@ struct inet_peer *inet_getpeer(struct inet_peer_base *base,
                        atomic_set(&p->rid, 0);
                        p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW;
                        p->rate_tokens = 0;
+                       p->n_redirects = 0;
                        /* 60*HZ is arbitrary, but chosen enough high so that the first
                         * calculation of tokens is at its maximum.
                         */
index d1d09f3..3978f80 100644 (file)
@@ -268,20 +268,11 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
        int len;
 
        itn = net_generic(net, erspan_net_id);
-       len = gre_hdr_len + sizeof(*ershdr);
-
-       /* Check based hdr len */
-       if (unlikely(!pskb_may_pull(skb, len)))
-               return PACKET_REJECT;
 
        iph = ip_hdr(skb);
        ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
        ver = ershdr->ver;
 
-       /* The original GRE header does not have key field,
-        * Use ERSPAN 10-bit session ID as key.
-        */
-       tpi->key = cpu_to_be32(get_session_id(ershdr));
        tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
                                  tpi->flags | TUNNEL_KEY,
                                  iph->saddr, iph->daddr, tpi->key);
@@ -569,8 +560,7 @@ err_free_skb:
        dev->stats.tx_dropped++;
 }
 
-static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
-                          __be16 proto)
+static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct ip_tunnel *tunnel = netdev_priv(dev);
        struct ip_tunnel_info *tun_info;
@@ -578,10 +568,10 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
        struct erspan_metadata *md;
        struct rtable *rt = NULL;
        bool truncate = false;
+       __be16 df, proto;
        struct flowi4 fl;
        int tunnel_hlen;
        int version;
-       __be16 df;
        int nhoff;
        int thoff;
 
@@ -626,18 +616,20 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
        if (version == 1) {
                erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)),
                                    ntohl(md->u.index), truncate, true);
+               proto = htons(ETH_P_ERSPAN);
        } else if (version == 2) {
                erspan_build_header_v2(skb,
                                       ntohl(tunnel_id_to_key32(key->tun_id)),
                                       md->u.md2.dir,
                                       get_hwid(&md->u.md2),
                                       truncate, true);
+               proto = htons(ETH_P_ERSPAN2);
        } else {
                goto err_free_rt;
        }
 
        gre_build_header(skb, 8, TUNNEL_SEQ,
-                        htons(ETH_P_ERSPAN), 0, htonl(tunnel->o_seqno++));
+                        proto, 0, htonl(tunnel->o_seqno++));
 
        df = key->tun_flags & TUNNEL_DONT_FRAGMENT ?  htons(IP_DF) : 0;
 
@@ -721,12 +713,13 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
 {
        struct ip_tunnel *tunnel = netdev_priv(dev);
        bool truncate = false;
+       __be16 proto;
 
        if (!pskb_inet_may_pull(skb))
                goto free_skb;
 
        if (tunnel->collect_md) {
-               erspan_fb_xmit(skb, dev, skb->protocol);
+               erspan_fb_xmit(skb, dev);
                return NETDEV_TX_OK;
        }
 
@@ -742,19 +735,22 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
        }
 
        /* Push ERSPAN header */
-       if (tunnel->erspan_ver == 1)
+       if (tunnel->erspan_ver == 1) {
                erspan_build_header(skb, ntohl(tunnel->parms.o_key),
                                    tunnel->index,
                                    truncate, true);
-       else if (tunnel->erspan_ver == 2)
+               proto = htons(ETH_P_ERSPAN);
+       } else if (tunnel->erspan_ver == 2) {
                erspan_build_header_v2(skb, ntohl(tunnel->parms.o_key),
                                       tunnel->dir, tunnel->hwid,
                                       truncate, true);
-       else
+               proto = htons(ETH_P_ERSPAN2);
+       } else {
                goto free_skb;
+       }
 
        tunnel->parms.o_flags &= ~TUNNEL_KEY;
-       __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN));
+       __gre_xmit(skb, dev, &tunnel->parms.iph, proto);
        return NETDEV_TX_OK;
 
 free_skb:
@@ -1459,12 +1455,17 @@ static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
 {
        struct ip_tunnel *t = netdev_priv(dev);
        struct ip_tunnel_parm *p = &t->parms;
+       __be16 o_flags = p->o_flags;
+
+       if ((t->erspan_ver == 1 || t->erspan_ver == 2) &&
+           !t->collect_md)
+               o_flags |= TUNNEL_KEY;
 
        if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
            nla_put_be16(skb, IFLA_GRE_IFLAGS,
                         gre_tnl_flags_to_gre_flags(p->i_flags)) ||
            nla_put_be16(skb, IFLA_GRE_OFLAGS,
-                        gre_tnl_flags_to_gre_flags(p->o_flags)) ||
+                        gre_tnl_flags_to_gre_flags(o_flags)) ||
            nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
            nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
            nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
index 26921f6..51d8efb 100644 (file)
@@ -488,6 +488,7 @@ static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net)
                goto drop;
        }
 
+       iph = ip_hdr(skb);
        skb->transport_header = skb->network_header + iph->ihl*4;
 
        /* Remove any debris in the socket control block */
index fffcc13..82f341e 100644 (file)
@@ -148,19 +148,17 @@ static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
 
 static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb)
 {
+       __be16 _ports[2], *ports;
        struct sockaddr_in sin;
-       __be16 *ports;
-       int end;
-
-       end = skb_transport_offset(skb) + 4;
-       if (end > 0 && !pskb_may_pull(skb, end))
-               return;
 
        /* All current transport protocols have the port numbers in the
         * first four bytes of the transport header and this function is
         * written with this assumption in mind.
         */
-       ports = (__be16 *)skb_transport_header(skb);
+       ports = skb_header_pointer(skb, skb_transport_offset(skb),
+                                  sizeof(_ports), &_ports);
+       if (!ports)
+               return;
 
        sin.sin_family = AF_INET;
        sin.sin_addr.s_addr = ip_hdr(skb)->daddr;
index c4f5602..054d01c 100644 (file)
@@ -644,13 +644,19 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
        dst = tnl_params->daddr;
        if (dst == 0) {
                /* NBMA tunnel */
+               struct ip_tunnel_info *tun_info;
 
                if (!skb_dst(skb)) {
                        dev->stats.tx_fifo_errors++;
                        goto tx_error;
                }
 
-               if (skb->protocol == htons(ETH_P_IP)) {
+               tun_info = skb_tunnel_info(skb);
+               if (tun_info && (tun_info->mode & IP_TUNNEL_INFO_TX) &&
+                   ip_tunnel_info_af(tun_info) == AF_INET &&
+                   tun_info->key.u.ipv4.dst)
+                       dst = tun_info->key.u.ipv4.dst;
+               else if (skb->protocol == htons(ETH_P_IP)) {
                        rt = skb_rtable(skb);
                        dst = rt_nexthop(rt, inner_iph->daddr);
                }
index d7b43e7..68a21bf 100644 (file)
@@ -74,6 +74,33 @@ drop:
        return 0;
 }
 
+static int vti_input_ipip(struct sk_buff *skb, int nexthdr, __be32 spi,
+                    int encap_type)
+{
+       struct ip_tunnel *tunnel;
+       const struct iphdr *iph = ip_hdr(skb);
+       struct net *net = dev_net(skb->dev);
+       struct ip_tunnel_net *itn = net_generic(net, vti_net_id);
+
+       tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
+                                 iph->saddr, iph->daddr, 0);
+       if (tunnel) {
+               if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
+                       goto drop;
+
+               XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = tunnel;
+
+               skb->dev = tunnel->dev;
+
+               return xfrm_input(skb, nexthdr, spi, encap_type);
+       }
+
+       return -EINVAL;
+drop:
+       kfree_skb(skb);
+       return 0;
+}
+
 static int vti_rcv(struct sk_buff *skb)
 {
        XFRM_SPI_SKB_CB(skb)->family = AF_INET;
@@ -82,6 +109,14 @@ static int vti_rcv(struct sk_buff *skb)
        return vti_input(skb, ip_hdr(skb)->protocol, 0, 0);
 }
 
+static int vti_rcv_ipip(struct sk_buff *skb)
+{
+       XFRM_SPI_SKB_CB(skb)->family = AF_INET;
+       XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
+
+       return vti_input_ipip(skb, ip_hdr(skb)->protocol, ip_hdr(skb)->saddr, 0);
+}
+
 static int vti_rcv_cb(struct sk_buff *skb, int err)
 {
        unsigned short family;
@@ -435,6 +470,12 @@ static struct xfrm4_protocol vti_ipcomp4_protocol __read_mostly = {
        .priority       =       100,
 };
 
+static struct xfrm_tunnel ipip_handler __read_mostly = {
+       .handler        =       vti_rcv_ipip,
+       .err_handler    =       vti4_err,
+       .priority       =       0,
+};
+
 static int __net_init vti_init_net(struct net *net)
 {
        int err;
@@ -603,6 +644,13 @@ static int __init vti_init(void)
        if (err < 0)
                goto xfrm_proto_comp_failed;
 
+       msg = "ipip tunnel";
+       err = xfrm4_tunnel_register(&ipip_handler, AF_INET);
+       if (err < 0) {
+               pr_info("%s: cant't register tunnel\n",__func__);
+               goto xfrm_tunnel_failed;
+       }
+
        msg = "netlink interface";
        err = rtnl_link_register(&vti_link_ops);
        if (err < 0)
@@ -612,6 +660,8 @@ static int __init vti_init(void)
 
 rtnl_link_failed:
        xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP);
+xfrm_tunnel_failed:
+       xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
 xfrm_proto_comp_failed:
        xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH);
 xfrm_proto_ah_failed:
index b61977d..2a909e5 100644 (file)
@@ -846,9 +846,9 @@ static int clusterip_net_init(struct net *net)
 
 static void clusterip_net_exit(struct net *net)
 {
+#ifdef CONFIG_PROC_FS
        struct clusterip_net *cn = clusterip_pernet(net);
 
-#ifdef CONFIG_PROC_FS
        mutex_lock(&cn->mutex);
        proc_remove(cn->procdir);
        cn->procdir = NULL;
index 2687db0..fa2ba7c 100644 (file)
@@ -215,6 +215,7 @@ int nf_nat_icmp_reply_translation(struct sk_buff *skb,
 
        /* Change outer to look like the reply to an incoming packet */
        nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
+       target.dst.protonum = IPPROTO_ICMP;
        if (!nf_nat_ipv4_manip_pkt(skb, 0, &target, manip))
                return 0;
 
index a0aa13b..0a8a60c 100644 (file)
@@ -105,6 +105,8 @@ static void fast_csum(struct snmp_ctx *ctx, unsigned char offset)
 int snmp_version(void *context, size_t hdrlen, unsigned char tag,
                 const void *data, size_t datalen)
 {
+       if (datalen != 1)
+               return -EINVAL;
        if (*(unsigned char *)data > 1)
                return -ENOTSUPP;
        return 1;
@@ -114,8 +116,11 @@ int snmp_helper(void *context, size_t hdrlen, unsigned char tag,
                const void *data, size_t datalen)
 {
        struct snmp_ctx *ctx = (struct snmp_ctx *)context;
-       __be32 *pdata = (__be32 *)data;
+       __be32 *pdata;
 
+       if (datalen != 4)
+               return -EINVAL;
+       pdata = (__be32 *)data;
        if (*pdata == ctx->from) {
                pr_debug("%s: %pI4 to %pI4\n", __func__,
                         (void *)&ctx->from, (void *)&ctx->to);
index ce92f73..5163b64 100644 (file)
@@ -887,13 +887,15 @@ void ip_rt_send_redirect(struct sk_buff *skb)
        /* No redirected packets during ip_rt_redirect_silence;
         * reset the algorithm.
         */
-       if (time_after(jiffies, peer->rate_last + ip_rt_redirect_silence))
+       if (time_after(jiffies, peer->rate_last + ip_rt_redirect_silence)) {
                peer->rate_tokens = 0;
+               peer->n_redirects = 0;
+       }
 
        /* Too many ignored redirects; do not send anything
         * set dst.rate_last to the last seen redirected packet.
         */
-       if (peer->rate_tokens >= ip_rt_redirect_number) {
+       if (peer->n_redirects >= ip_rt_redirect_number) {
                peer->rate_last = jiffies;
                goto out_put_peer;
        }
@@ -910,6 +912,7 @@ void ip_rt_send_redirect(struct sk_buff *skb)
                icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, gw);
                peer->rate_last = jiffies;
                ++peer->rate_tokens;
+               ++peer->n_redirects;
 #ifdef CONFIG_IP_ROUTE_VERBOSE
                if (log_martians &&
                    peer->rate_tokens == ip_rt_redirect_number)
index 27e2f68..2079145 100644 (file)
@@ -1186,7 +1186,7 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
        flags = msg->msg_flags;
 
        if (flags & MSG_ZEROCOPY && size && sock_flag(sk, SOCK_ZEROCOPY)) {
-               if (sk->sk_state != TCP_ESTABLISHED) {
+               if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) {
                        err = -EINVAL;
                        goto out_err;
                }
index f87dbc7..71a29e9 100644 (file)
@@ -226,7 +226,7 @@ static int tcp_write_timeout(struct sock *sk)
        if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {
                if (icsk->icsk_retransmits) {
                        dst_negative_advice(sk);
-               } else if (!tp->syn_data && !tp->syn_fastopen) {
+               } else {
                        sk_rethink_txhash(sk);
                }
                retry_until = icsk->icsk_syn_retries ? : net->ipv4.sysctl_tcp_syn_retries;
index 3fb0ed5..5c3cd5d 100644 (file)
@@ -847,15 +847,23 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4,
                const int hlen = skb_network_header_len(skb) +
                                 sizeof(struct udphdr);
 
-               if (hlen + cork->gso_size > cork->fragsize)
+               if (hlen + cork->gso_size > cork->fragsize) {
+                       kfree_skb(skb);
                        return -EINVAL;
-               if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS)
+               }
+               if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS) {
+                       kfree_skb(skb);
                        return -EINVAL;
-               if (sk->sk_no_check_tx)
+               }
+               if (sk->sk_no_check_tx) {
+                       kfree_skb(skb);
                        return -EINVAL;
+               }
                if (skb->ip_summed != CHECKSUM_PARTIAL || is_udplite ||
-                   dst_xfrm(skb_dst(skb)))
+                   dst_xfrm(skb_dst(skb))) {
+                       kfree_skb(skb);
                        return -EIO;
+               }
 
                skb_shinfo(skb)->gso_size = cork->gso_size;
                skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;
@@ -1918,7 +1926,7 @@ void udp_lib_rehash(struct sock *sk, u16 newhash)
 }
 EXPORT_SYMBOL(udp_lib_rehash);
 
-static void udp_v4_rehash(struct sock *sk)
+void udp_v4_rehash(struct sock *sk)
 {
        u16 new_hash = ipv4_portaddr_hash(sock_net(sk),
                                          inet_sk(sk)->inet_rcv_saddr,
index 3226726..6b2fa77 100644 (file)
@@ -10,6 +10,7 @@ int __udp4_lib_rcv(struct sk_buff *, struct udp_table *, int);
 int __udp4_lib_err(struct sk_buff *, u32, struct udp_table *);
 
 int udp_v4_get_port(struct sock *sk, unsigned short snum);
+void udp_v4_rehash(struct sock *sk);
 
 int udp_setsockopt(struct sock *sk, int level, int optname,
                   char __user *optval, unsigned int optlen);
index 39c7f17..3c94b8f 100644 (file)
@@ -53,6 +53,7 @@ struct proto  udplite_prot = {
        .sendpage          = udp_sendpage,
        .hash              = udp_lib_hash,
        .unhash            = udp_lib_unhash,
+       .rehash            = udp_v4_rehash,
        .get_port          = udp_v4_get_port,
        .memory_allocated  = &udp_memory_allocated,
        .sysctl_mem        = sysctl_udp_mem,
index 8eeec6e..72ffd3d 100644 (file)
@@ -1165,7 +1165,8 @@ check_cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long *expires)
        list_for_each_entry(ifa, &idev->addr_list, if_list) {
                if (ifa == ifp)
                        continue;
-               if (!ipv6_prefix_equal(&ifa->addr, &ifp->addr,
+               if (ifa->prefix_len != ifp->prefix_len ||
+                   !ipv6_prefix_equal(&ifa->addr, &ifp->addr,
                                       ifp->prefix_len))
                        continue;
                if (ifa->flags & (IFA_F_PERMANENT | IFA_F_NOPREFIXROUTE))
@@ -3495,8 +3496,8 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 
                        if (!addrconf_link_ready(dev)) {
                                /* device is not ready yet. */
-                               pr_info("ADDRCONF(NETDEV_UP): %s: link is not ready\n",
-                                       dev->name);
+                               pr_debug("ADDRCONF(NETDEV_UP): %s: link is not ready\n",
+                                        dev->name);
                                break;
                        }
 
@@ -5120,6 +5121,8 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
                        if (idev) {
                                err = in6_dump_addrs(idev, skb, cb, s_ip_idx,
                                                     &fillargs);
+                               if (err > 0)
+                                       err = 0;
                        }
                        goto put_tgt_net;
                }
@@ -5154,7 +5157,7 @@ put_tgt_net:
        if (fillargs.netnsid >= 0)
                put_net(tgt_net);
 
-       return err < 0 ? err : skb->len;
+       return skb->len ? : err;
 }
 
 static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
index 0bfb6cc..d99753b 100644 (file)
@@ -310,6 +310,7 @@ static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
 
        /* Check if the address belongs to the host. */
        if (addr_type == IPV6_ADDR_MAPPED) {
+               struct net_device *dev = NULL;
                int chk_addr_ret;
 
                /* Binding to v4-mapped address on a v6-only socket
@@ -320,9 +321,20 @@ static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
                        goto out;
                }
 
+               rcu_read_lock();
+               if (sk->sk_bound_dev_if) {
+                       dev = dev_get_by_index_rcu(net, sk->sk_bound_dev_if);
+                       if (!dev) {
+                               err = -ENODEV;
+                               goto out_unlock;
+                       }
+               }
+
                /* Reproduce AF_INET checks to make the bindings consistent */
                v4addr = addr->sin6_addr.s6_addr32[3];
-               chk_addr_ret = inet_addr_type(net, v4addr);
+               chk_addr_ret = inet_addr_type_dev_table(net, dev, v4addr);
+               rcu_read_unlock();
+
                if (!inet_can_nonlocal_bind(net, inet) &&
                    v4addr != htonl(INADDR_ANY) &&
                    chk_addr_ret != RTN_LOCAL &&
index bde08aa..ee4a4e5 100644 (file)
@@ -341,6 +341,7 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info)
        skb_reset_network_header(skb);
        iph = ipv6_hdr(skb);
        iph->daddr = fl6->daddr;
+       ip6_flow_hdr(iph, 0, 0);
 
        serr = SKB_EXT_ERR(skb);
        serr->ee.ee_errno = err;
@@ -700,17 +701,15 @@ void ip6_datagram_recv_specific_ctl(struct sock *sk, struct msghdr *msg,
        }
        if (np->rxopt.bits.rxorigdstaddr) {
                struct sockaddr_in6 sin6;
-               __be16 *ports;
-               int end;
+               __be16 _ports[2], *ports;
 
-               end = skb_transport_offset(skb) + 4;
-               if (end <= 0 || pskb_may_pull(skb, end)) {
+               ports = skb_header_pointer(skb, skb_transport_offset(skb),
+                                          sizeof(_ports), &_ports);
+               if (ports) {
                        /* All current transport protocols have the port numbers in the
                         * first four bytes of the transport header and this function is
                         * written with this assumption in mind.
                         */
-                       ports = (__be16 *)skb_transport_header(skb);
-
                        sin6.sin6_family = AF_INET6;
                        sin6.sin6_addr = ipv6_hdr(skb)->daddr;
                        sin6.sin6_port = ports[1];
index bd675c6..b858bd5 100644 (file)
@@ -90,10 +90,11 @@ static int gue6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 {
        int transport_offset = skb_transport_offset(skb);
        struct guehdr *guehdr;
-       size_t optlen;
+       size_t len, optlen;
        int ret;
 
-       if (skb->len < sizeof(struct udphdr) + sizeof(struct guehdr))
+       len = sizeof(struct udphdr) + sizeof(struct guehdr);
+       if (!pskb_may_pull(skb, len))
                return -EINVAL;
 
        guehdr = (struct guehdr *)&udp_hdr(skb)[1];
@@ -128,9 +129,21 @@ static int gue6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 
        optlen = guehdr->hlen << 2;
 
+       if (!pskb_may_pull(skb, len + optlen))
+               return -EINVAL;
+
+       guehdr = (struct guehdr *)&udp_hdr(skb)[1];
        if (validate_gue_flags(guehdr, optlen))
                return -EINVAL;
 
+       /* Handling exceptions for direct UDP encapsulation in GUE would lead to
+        * recursion. Besides, this kind of encapsulation can't even be
+        * configured currently. Discard this.
+        */
+       if (guehdr->proto_ctype == IPPROTO_UDP ||
+           guehdr->proto_ctype == IPPROTO_UDPLITE)
+               return -EOPNOTSUPP;
+
        skb_set_transport_header(skb, -(int)sizeof(struct icmp6hdr));
        ret = gue6_err_proto_handler(guehdr->proto_ctype, skb,
                                     opt, type, code, offset, info);
index 5d7aa2c..bbcdfd2 100644 (file)
@@ -423,10 +423,10 @@ static int icmp6_iif(const struct sk_buff *skb)
 static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
                       const struct in6_addr *force_saddr)
 {
-       struct net *net = dev_net(skb->dev);
        struct inet6_dev *idev = NULL;
        struct ipv6hdr *hdr = ipv6_hdr(skb);
        struct sock *sk;
+       struct net *net;
        struct ipv6_pinfo *np;
        const struct in6_addr *saddr = NULL;
        struct dst_entry *dst;
@@ -437,12 +437,16 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
        int iif = 0;
        int addr_type = 0;
        int len;
-       u32 mark = IP6_REPLY_MARK(net, skb->mark);
+       u32 mark;
 
        if ((u8 *)hdr < skb->head ||
            (skb_network_header(skb) + sizeof(*hdr)) > skb_tail_pointer(skb))
                return;
 
+       if (!skb->dev)
+               return;
+       net = dev_net(skb->dev);
+       mark = IP6_REPLY_MARK(net, skb->mark);
        /*
         *      Make sure we respect the rules
         *      i.e. RFC 1885 2.4(e)
index 09d0826..801a9a0 100644 (file)
@@ -534,13 +534,9 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
        struct ip6_tnl *tunnel;
        u8 ver;
 
-       if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr))))
-               return PACKET_REJECT;
-
        ipv6h = ipv6_hdr(skb);
        ershdr = (struct erspan_base_hdr *)skb->data;
        ver = ershdr->ver;
-       tpi->key = cpu_to_be32(get_session_id(ershdr));
 
        tunnel = ip6gre_tunnel_lookup(skb->dev,
                                      &ipv6h->saddr, &ipv6h->daddr, tpi->key,
@@ -922,6 +918,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
        __u8 dsfield = false;
        struct flowi6 fl6;
        int err = -EINVAL;
+       __be16 proto;
        __u32 mtu;
        int nhoff;
        int thoff;
@@ -1035,8 +1032,9 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
        }
 
        /* Push GRE header. */
-       gre_build_header(skb, 8, TUNNEL_SEQ,
-                        htons(ETH_P_ERSPAN), 0, htonl(t->o_seqno++));
+       proto = (t->parms.erspan_ver == 1) ? htons(ETH_P_ERSPAN)
+                                          : htons(ETH_P_ERSPAN2);
+       gre_build_header(skb, 8, TUNNEL_SEQ, proto, 0, htonl(t->o_seqno++));
 
        /* TooBig packet may have updated dst->dev's mtu */
        if (!t->parms.collect_md && dst && dst_mtu(dst) > dst->dev->mtu)
@@ -1169,6 +1167,10 @@ static void ip6gre_tnl_copy_tnl_parm(struct ip6_tnl *t,
        t->parms.i_flags = p->i_flags;
        t->parms.o_flags = p->o_flags;
        t->parms.fwmark = p->fwmark;
+       t->parms.erspan_ver = p->erspan_ver;
+       t->parms.index = p->index;
+       t->parms.dir = p->dir;
+       t->parms.hwid = p->hwid;
        dst_cache_reset(&t->dst_cache);
 }
 
@@ -2025,9 +2027,9 @@ static int ip6gre_changelink(struct net_device *dev, struct nlattr *tb[],
                             struct nlattr *data[],
                             struct netlink_ext_ack *extack)
 {
-       struct ip6gre_net *ign = net_generic(dev_net(dev), ip6gre_net_id);
+       struct ip6_tnl *t = netdev_priv(dev);
+       struct ip6gre_net *ign = net_generic(t->net, ip6gre_net_id);
        struct __ip6_tnl_parm p;
-       struct ip6_tnl *t;
 
        t = ip6gre_changelink_common(dev, tb, data, &p, extack);
        if (IS_ERR(t))
@@ -2096,12 +2098,17 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev)
 {
        struct ip6_tnl *t = netdev_priv(dev);
        struct __ip6_tnl_parm *p = &t->parms;
+       __be16 o_flags = p->o_flags;
+
+       if ((p->erspan_ver == 1 || p->erspan_ver == 2) &&
+           !p->collect_md)
+               o_flags |= TUNNEL_KEY;
 
        if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
            nla_put_be16(skb, IFLA_GRE_IFLAGS,
                         gre_tnl_flags_to_gre_flags(p->i_flags)) ||
            nla_put_be16(skb, IFLA_GRE_OFLAGS,
-                        gre_tnl_flags_to_gre_flags(p->o_flags)) ||
+                        gre_tnl_flags_to_gre_flags(o_flags)) ||
            nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
            nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
            nla_put_in6_addr(skb, IFLA_GRE_LOCAL, &p->laddr) ||
index 30337b3..cc01aa3 100644 (file)
@@ -1516,6 +1516,9 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all)
                        continue;
                rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params);
                list_del_rcu(&c->list);
+               call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
+                                              FIB_EVENT_ENTRY_DEL,
+                                              (struct mfc6_cache *)c, mrt->id);
                mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
                mr_cache_put(c);
        }
@@ -1524,10 +1527,6 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all)
                spin_lock_bh(&mfc_unres_lock);
                list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
                        list_del(&c->list);
-                       call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
-                                                      FIB_EVENT_ENTRY_DEL,
-                                                      (struct mfc6_cache *)c,
-                                                      mrt->id);
                        mr6_netlink_event(mrt, (struct mfc6_cache *)c,
                                          RTM_DELROUTE);
                        ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
index 8b075f0..6d0b1f3 100644 (file)
@@ -23,9 +23,11 @@ int ip6_route_me_harder(struct net *net, struct sk_buff *skb)
        struct sock *sk = sk_to_full_sk(skb->sk);
        unsigned int hh_len;
        struct dst_entry *dst;
+       int strict = (ipv6_addr_type(&iph->daddr) &
+                     (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL));
        struct flowi6 fl6 = {
                .flowi6_oif = sk && sk->sk_bound_dev_if ? sk->sk_bound_dev_if :
-                       rt6_need_strict(&iph->daddr) ? skb_dst(skb)->dev->ifindex : 0,
+                       strict ? skb_dst(skb)->dev->ifindex : 0,
                .flowi6_mark = skb->mark,
                .flowi6_uid = sock_net_uid(net, sk),
                .daddr = iph->daddr,
index 2302244..7a41ee3 100644 (file)
@@ -226,6 +226,7 @@ int nf_nat_icmpv6_reply_translation(struct sk_buff *skb,
        }
 
        nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
+       target.dst.protonum = IPPROTO_ICMPV6;
        if (!nf_nat_ipv6_manip_pkt(skb, 0, &target, manip))
                return 0;
 
index 40b225f..964491c 100644 (file)
@@ -4251,17 +4251,6 @@ struct rt6_nh {
        struct list_head next;
 };
 
-static void ip6_print_replace_route_err(struct list_head *rt6_nh_list)
-{
-       struct rt6_nh *nh;
-
-       list_for_each_entry(nh, rt6_nh_list, next) {
-               pr_warn("IPV6: multipath route replace failed (check consistency of installed routes): %pI6c nexthop %pI6c ifi %d\n",
-                       &nh->r_cfg.fc_dst, &nh->r_cfg.fc_gateway,
-                       nh->r_cfg.fc_ifindex);
-       }
-}
-
 static int ip6_route_info_append(struct net *net,
                                 struct list_head *rt6_nh_list,
                                 struct fib6_info *rt,
@@ -4407,7 +4396,8 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
                nh->fib6_info = NULL;
                if (err) {
                        if (replace && nhn)
-                               ip6_print_replace_route_err(&rt6_nh_list);
+                               NL_SET_ERR_MSG_MOD(extack,
+                                                  "multipath route replace failed (check consistency of installed routes)");
                        err_nh = nh;
                        goto add_errout;
                }
index 8d0ba75..9b2f272 100644 (file)
@@ -221,9 +221,7 @@ static int seg6_genl_get_tunsrc(struct sk_buff *skb, struct genl_info *info)
        rcu_read_unlock();
 
        genlmsg_end(msg, hdr);
-       genlmsg_reply(msg, info);
-
-       return 0;
+       return genlmsg_reply(msg, info);
 
 nla_put_failure:
        rcu_read_unlock();
index 8181ee7..ee5403c 100644 (file)
@@ -146,6 +146,8 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto)
        } else {
                ip6_flow_hdr(hdr, 0, flowlabel);
                hdr->hop_limit = ip6_dst_hoplimit(skb_dst(skb));
+
+               memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
        }
 
        hdr->nexthdr = NEXTHDR_ROUTING;
index 1e03305..e8a1dab 100644 (file)
@@ -546,7 +546,8 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
        }
 
        err = 0;
-       if (!ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4, type, data_len))
+       if (__in6_dev_get(skb->dev) &&
+           !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4, type, data_len))
                goto out;
 
        if (t->parms.iph.daddr == 0)
index 9cbf363..2596ffd 100644 (file)
@@ -102,7 +102,7 @@ int udp_v6_get_port(struct sock *sk, unsigned short snum)
        return udp_lib_get_port(sk, snum, hash2_nulladdr);
 }
 
-static void udp_v6_rehash(struct sock *sk)
+void udp_v6_rehash(struct sock *sk)
 {
        u16 new_hash = ipv6_portaddr_hash(sock_net(sk),
                                          &sk->sk_v6_rcv_saddr,
@@ -1132,15 +1132,23 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6,
                const int hlen = skb_network_header_len(skb) +
                                 sizeof(struct udphdr);
 
-               if (hlen + cork->gso_size > cork->fragsize)
+               if (hlen + cork->gso_size > cork->fragsize) {
+                       kfree_skb(skb);
                        return -EINVAL;
-               if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS)
+               }
+               if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS) {
+                       kfree_skb(skb);
                        return -EINVAL;
-               if (udp_sk(sk)->no_check6_tx)
+               }
+               if (udp_sk(sk)->no_check6_tx) {
+                       kfree_skb(skb);
                        return -EINVAL;
+               }
                if (skb->ip_summed != CHECKSUM_PARTIAL || is_udplite ||
-                   dst_xfrm(skb_dst(skb)))
+                   dst_xfrm(skb_dst(skb))) {
+                       kfree_skb(skb);
                        return -EIO;
+               }
 
                skb_shinfo(skb)->gso_size = cork->gso_size;
                skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;
@@ -1390,10 +1398,7 @@ do_udp_sendmsg:
        ipc6.opt = opt;
 
        fl6.flowi6_proto = sk->sk_protocol;
-       if (!ipv6_addr_any(daddr))
-               fl6.daddr = *daddr;
-       else
-               fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
+       fl6.daddr = *daddr;
        if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr))
                fl6.saddr = np->saddr;
        fl6.fl6_sport = inet->inet_sport;
@@ -1421,6 +1426,9 @@ do_udp_sendmsg:
                }
        }
 
+       if (ipv6_addr_any(&fl6.daddr))
+               fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
+
        final_p = fl6_update_dst(&fl6, opt, &final);
        if (final_p)
                connected = false;
index 5730e65..20e324b 100644 (file)
@@ -13,6 +13,7 @@ int __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, u8, u8, int,
                   __be32, struct udp_table *);
 
 int udp_v6_get_port(struct sock *sk, unsigned short snum);
+void udp_v6_rehash(struct sock *sk);
 
 int udpv6_getsockopt(struct sock *sk, int level, int optname,
                     char __user *optval, int __user *optlen);
index a125aeb..f359078 100644 (file)
@@ -49,6 +49,7 @@ struct proto udplitev6_prot = {
        .recvmsg           = udpv6_recvmsg,
        .hash              = udp_lib_hash,
        .unhash            = udp_lib_unhash,
+       .rehash            = udp_v6_rehash,
        .get_port          = udp_v6_get_port,
        .memory_allocated  = &udp_memory_allocated,
        .sysctl_mem        = sysctl_udp_mem,
index 26f1d43..fed6bec 100644 (file)
@@ -83,8 +83,7 @@
 #define L2TP_SLFLAG_S     0x40000000
 #define L2TP_SL_SEQ_MASK   0x00ffffff
 
-#define L2TP_HDR_SIZE_SEQ              10
-#define L2TP_HDR_SIZE_NOSEQ            6
+#define L2TP_HDR_SIZE_MAX              14
 
 /* Default trace flags */
 #define L2TP_DEFAULT_DEBUG_FLAGS       0
@@ -808,7 +807,7 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb)
        __skb_pull(skb, sizeof(struct udphdr));
 
        /* Short packet? */
-       if (!pskb_may_pull(skb, L2TP_HDR_SIZE_SEQ)) {
+       if (!pskb_may_pull(skb, L2TP_HDR_SIZE_MAX)) {
                l2tp_info(tunnel, L2TP_MSG_DATA,
                          "%s: recv short packet (len=%d)\n",
                          tunnel->name, skb->len);
@@ -884,6 +883,10 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb)
                goto error;
        }
 
+       if (tunnel->version == L2TP_HDR_VER_3 &&
+           l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
+               goto error;
+
        l2tp_recv_common(session, skb, ptr, optr, hdrflags, length);
        l2tp_session_dec_refcount(session);
 
index 9c9afe9..b2ce902 100644 (file)
@@ -301,6 +301,26 @@ static inline bool l2tp_tunnel_uses_xfrm(const struct l2tp_tunnel *tunnel)
 }
 #endif
 
+static inline int l2tp_v3_ensure_opt_in_linear(struct l2tp_session *session, struct sk_buff *skb,
+                                              unsigned char **ptr, unsigned char **optr)
+{
+       int opt_len = session->peer_cookie_len + l2tp_get_l2specific_len(session);
+
+       if (opt_len > 0) {
+               int off = *ptr - *optr;
+
+               if (!pskb_may_pull(skb, off + opt_len))
+                       return -1;
+
+               if (skb->data != *optr) {
+                       *optr = skb->data;
+                       *ptr = skb->data + off;
+               }
+       }
+
+       return 0;
+}
+
 #define l2tp_printk(ptr, type, func, fmt, ...)                         \
 do {                                                                   \
        if (((ptr)->debug) & (type))                                    \
index 35f6f86..d4c6052 100644 (file)
@@ -165,6 +165,9 @@ static int l2tp_ip_recv(struct sk_buff *skb)
                print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length);
        }
 
+       if (l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
+               goto discard_sess;
+
        l2tp_recv_common(session, skb, ptr, optr, 0, skb->len);
        l2tp_session_dec_refcount(session);
 
index 237f1a4..0ae6899 100644 (file)
@@ -178,6 +178,9 @@ static int l2tp_ip6_recv(struct sk_buff *skb)
                print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length);
        }
 
+       if (l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
+               goto discard_sess;
+
        l2tp_recv_common(session, skb, ptr, optr, 0, skb->len);
        l2tp_session_dec_refcount(session);
 
index 69e831b..54821fb 100644 (file)
@@ -8,7 +8,7 @@
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2007-2010, Intel Corporation
  * Copyright(c) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -366,6 +366,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
 
        set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state);
 
+       ieee80211_agg_stop_txq(sta, tid);
+
        spin_unlock_bh(&sta->lock);
 
        ht_dbg(sta->sdata, "Tx BA session stop requested for %pM tid %u\n",
index de65fe3..2493c74 100644 (file)
@@ -1490,6 +1490,10 @@ 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);
index 45aad3d..bb4d71e 100644 (file)
@@ -231,7 +231,7 @@ static void ieee80211_handle_mu_mimo_mon(struct ieee80211_sub_if_data *sdata,
                struct ieee80211_hdr_3addr hdr;
                u8 category;
                u8 action_code;
-       } __packed action;
+       } __packed __aligned(2) action;
 
        if (!sdata)
                return;
@@ -2723,7 +2723,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        skb_set_queue_mapping(skb, q);
 
        if (!--mesh_hdr->ttl) {
-               IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
+               if (!is_multicast_ether_addr(hdr->addr1))
+                       IEEE80211_IFSTA_MESH_CTR_INC(ifmsh,
+                                                    dropped_frames_ttl);
                goto out;
        }
 
index f170d6c..928f13a 100644 (file)
@@ -1938,9 +1938,16 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
                                int head_need, bool may_encrypt)
 {
        struct ieee80211_local *local = sdata->local;
+       struct ieee80211_hdr *hdr;
+       bool enc_tailroom;
        int tail_need = 0;
 
-       if (may_encrypt && sdata->crypto_tx_tailroom_needed_cnt) {
+       hdr = (struct ieee80211_hdr *) skb->data;
+       enc_tailroom = may_encrypt &&
+                      (sdata->crypto_tx_tailroom_needed_cnt ||
+                       ieee80211_is_mgmt(hdr->frame_control));
+
+       if (enc_tailroom) {
                tail_need = IEEE80211_ENCRYPT_TAILROOM;
                tail_need -= skb_tailroom(skb);
                tail_need = max_t(int, tail_need, 0);
@@ -1948,8 +1955,7 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
 
        if (skb_cloned(skb) &&
            (!ieee80211_hw_check(&local->hw, SUPPORTS_CLONED_SKBS) ||
-            !skb_clone_writable(skb, ETH_HLEN) ||
-            (may_encrypt && sdata->crypto_tx_tailroom_needed_cnt)))
+            !skb_clone_writable(skb, ETH_HLEN) || enc_tailroom))
                I802_DEBUG_INC(local->tx_expand_skb_head_cloned);
        else if (head_need || tail_need)
                I802_DEBUG_INC(local->tx_expand_skb_head);
index d0eb38b..ba950ae 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2007      Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright (C) 2015-2017     Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018-2019 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -2146,6 +2146,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                case NL80211_IFTYPE_AP_VLAN:
                case NL80211_IFTYPE_MONITOR:
                        break;
+               case NL80211_IFTYPE_ADHOC:
+                       if (sdata->vif.bss_conf.ibss_joined)
+                               WARN_ON(drv_join_ibss(local, sdata));
+                       /* fall through */
                default:
                        ieee80211_reconfig_stations(sdata);
                        /* fall through */
index cad48d0..8401cef 100644 (file)
@@ -29,6 +29,7 @@ config        IP_VS_IPV6
        bool "IPv6 support for IPVS"
        depends on IPV6 = y || IP_VS = IPV6
        select IP6_NF_IPTABLES
+       select NF_DEFRAG_IPV6
        ---help---
          Add IPv6 support to IPVS.
 
index fe9abf3..235205c 100644 (file)
@@ -1536,14 +1536,12 @@ ip_vs_try_to_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
                /* sorry, all this trouble for a no-hit :) */
                IP_VS_DBG_PKT(12, af, pp, skb, iph->off,
                              "ip_vs_in: packet continues traversal as normal");
-               if (iph->fragoffs) {
-                       /* Fragment that couldn't be mapped to a conn entry
-                        * is missing module nf_defrag_ipv6
-                        */
-                       IP_VS_DBG_RL("Unhandled frag, load nf_defrag_ipv6\n");
+
+               /* Fragment couldn't be mapped to a conn entry */
+               if (iph->fragoffs)
                        IP_VS_DBG_PKT(7, af, pp, skb, iph->off,
                                      "unhandled fragment");
-               }
+
                *verdict = NF_ACCEPT;
                return 0;
        }
index 432141f..86afacb 100644 (file)
@@ -43,6 +43,7 @@
 #ifdef CONFIG_IP_VS_IPV6
 #include <net/ipv6.h>
 #include <net/ip6_route.h>
+#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
 #endif
 #include <net/route.h>
 #include <net/sock.h>
@@ -895,6 +896,7 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
 {
        struct ip_vs_dest *dest;
        unsigned int atype, i;
+       int ret = 0;
 
        EnterFunction(2);
 
@@ -905,6 +907,10 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
                        atype & IPV6_ADDR_LINKLOCAL) &&
                        !__ip_vs_addr_is_local_v6(svc->ipvs->net, &udest->addr.in6))
                        return -EINVAL;
+
+               ret = nf_defrag_ipv6_enable(svc->ipvs->net);
+               if (ret)
+                       return ret;
        } else
 #endif
        {
@@ -1228,6 +1234,10 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
                        ret = -EINVAL;
                        goto out_err;
                }
+
+               ret = nf_defrag_ipv6_enable(ipvs->net);
+               if (ret)
+                       goto out_err;
        }
 #endif
 
@@ -2221,6 +2231,18 @@ static int ip_vs_set_timeout(struct netns_ipvs *ipvs, struct ip_vs_timeout_user
                  u->udp_timeout);
 
 #ifdef CONFIG_IP_VS_PROTO_TCP
+       if (u->tcp_timeout < 0 || u->tcp_timeout > (INT_MAX / HZ) ||
+           u->tcp_fin_timeout < 0 || u->tcp_fin_timeout > (INT_MAX / HZ)) {
+               return -EINVAL;
+       }
+#endif
+
+#ifdef CONFIG_IP_VS_PROTO_UDP
+       if (u->udp_timeout < 0 || u->udp_timeout > (INT_MAX / HZ))
+               return -EINVAL;
+#endif
+
+#ifdef CONFIG_IP_VS_PROTO_TCP
        if (u->tcp_timeout) {
                pd = ip_vs_proto_data_get(ipvs, IPPROTO_TCP);
                pd->timeout_table[IP_VS_TCP_S_ESTABLISHED]
index 741b533..db4d463 100644 (file)
@@ -1007,6 +1007,22 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple,
                }
 
                if (nf_ct_key_equal(h, tuple, zone, net)) {
+                       /* Tuple is taken already, so caller will need to find
+                        * a new source port to use.
+                        *
+                        * Only exception:
+                        * If the *original tuples* are identical, then both
+                        * conntracks refer to the same flow.
+                        * This is a rare situation, it can occur e.g. when
+                        * more than one UDP packet is sent from same socket
+                        * in different threads.
+                        *
+                        * Let nf_ct_resolve_clash() deal with this later.
+                        */
+                       if (nf_ct_tuple_equal(&ignored_conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+                                             &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple))
+                               continue;
+
                        NF_CT_STAT_INC_ATOMIC(net, found);
                        rcu_read_unlock();
                        return 1;
index fa0844e..c0c72ae 100644 (file)
@@ -28,6 +28,7 @@ flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct,
 {
        struct flow_offload_tuple *ft = &flow->tuplehash[dir].tuple;
        struct nf_conntrack_tuple *ctt = &ct->tuplehash[dir].tuple;
+       struct dst_entry *other_dst = route->tuple[!dir].dst;
        struct dst_entry *dst = route->tuple[dir].dst;
 
        ft->dir = dir;
@@ -50,8 +51,8 @@ flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct,
        ft->src_port = ctt->src.u.tcp.port;
        ft->dst_port = ctt->dst.u.tcp.port;
 
-       ft->iifidx = route->tuple[dir].ifindex;
-       ft->oifidx = route->tuple[!dir].ifindex;
+       ft->iifidx = other_dst->dev->ifindex;
+       ft->oifidx = dst->dev->ifindex;
        ft->dst_cache = dst;
 }
 
index 2b0a933..5a92f23 100644 (file)
@@ -116,6 +116,23 @@ static void nft_trans_destroy(struct nft_trans *trans)
        kfree(trans);
 }
 
+static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
+{
+       struct net *net = ctx->net;
+       struct nft_trans *trans;
+
+       if (!nft_set_is_anonymous(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) {
+                       nft_trans_set_bound(trans) = true;
+                       break;
+               }
+       }
+}
+
 static int nf_tables_register_hook(struct net *net,
                                   const struct nft_table *table,
                                   struct nft_chain *chain)
@@ -211,18 +228,6 @@ static int nft_delchain(struct nft_ctx *ctx)
        return err;
 }
 
-/* either expr ops provide both activate/deactivate, or neither */
-static bool nft_expr_check_ops(const struct nft_expr_ops *ops)
-{
-       if (!ops)
-               return true;
-
-       if (WARN_ON_ONCE((!ops->activate ^ !ops->deactivate)))
-               return false;
-
-       return true;
-}
-
 static void nft_rule_expr_activate(const struct nft_ctx *ctx,
                                   struct nft_rule *rule)
 {
@@ -238,14 +243,15 @@ static void nft_rule_expr_activate(const struct nft_ctx *ctx,
 }
 
 static void nft_rule_expr_deactivate(const struct nft_ctx *ctx,
-                                    struct nft_rule *rule)
+                                    struct nft_rule *rule,
+                                    enum nft_trans_phase phase)
 {
        struct nft_expr *expr;
 
        expr = nft_expr_first(rule);
        while (expr != nft_expr_last(rule) && expr->ops) {
                if (expr->ops->deactivate)
-                       expr->ops->deactivate(ctx, expr);
+                       expr->ops->deactivate(ctx, expr, phase);
 
                expr = nft_expr_next(expr);
        }
@@ -296,7 +302,7 @@ static int nft_delrule(struct nft_ctx *ctx, struct nft_rule *rule)
                nft_trans_destroy(trans);
                return err;
        }
-       nft_rule_expr_deactivate(ctx, rule);
+       nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_PREPARE);
 
        return 0;
 }
@@ -1929,9 +1935,6 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk,
  */
 int nft_register_expr(struct nft_expr_type *type)
 {
-       if (!nft_expr_check_ops(type->ops))
-               return -EINVAL;
-
        nfnl_lock(NFNL_SUBSYS_NFTABLES);
        if (type->family == NFPROTO_UNSPEC)
                list_add_tail_rcu(&type->list, &nf_tables_expressions);
@@ -2079,10 +2082,6 @@ static int nf_tables_expr_parse(const struct nft_ctx *ctx,
                        err = PTR_ERR(ops);
                        goto err1;
                }
-               if (!nft_expr_check_ops(ops)) {
-                       err = -EINVAL;
-                       goto err1;
-               }
        } else
                ops = type->ops;
 
@@ -2304,7 +2303,6 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
        struct net *net = sock_net(skb->sk);
        unsigned int s_idx = cb->args[0];
        const struct nft_rule *rule;
-       int rc = 1;
 
        list_for_each_entry_rcu(rule, &chain->rules, list) {
                if (!nft_is_active(net, rule))
@@ -2321,16 +2319,13 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
                                        NLM_F_MULTI | NLM_F_APPEND,
                                        table->family,
                                        table, chain, rule) < 0)
-                       goto out_unfinished;
+                       return 1;
 
                nl_dump_check_consistent(cb, nlmsg_hdr(skb));
 cont:
                (*idx)++;
        }
-       rc = 0;
-out_unfinished:
-       cb->args[0] = *idx;
-       return rc;
+       return 0;
 }
 
 static int nf_tables_dump_rules(struct sk_buff *skb,
@@ -2354,7 +2349,7 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
                if (ctx && ctx->table && strcmp(ctx->table, table->name) != 0)
                        continue;
 
-               if (ctx && ctx->chain) {
+               if (ctx && ctx->table && ctx->chain) {
                        struct rhlist_head *list, *tmp;
 
                        list = rhltable_lookup(&table->chains_ht, ctx->chain,
@@ -2382,6 +2377,8 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
        }
 done:
        rcu_read_unlock();
+
+       cb->args[0] = idx;
        return skb->len;
 }
 
@@ -2513,7 +2510,7 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
 static void nf_tables_rule_release(const struct nft_ctx *ctx,
                                   struct nft_rule *rule)
 {
-       nft_rule_expr_deactivate(ctx, rule);
+       nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE);
        nf_tables_rule_destroy(ctx, rule);
 }
 
@@ -3710,39 +3707,30 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
 bind:
        binding->chain = ctx->chain;
        list_add_tail_rcu(&binding->list, &set->bindings);
+       nft_set_trans_bind(ctx, set);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(nf_tables_bind_set);
 
-void nf_tables_rebind_set(const struct nft_ctx *ctx, struct nft_set *set,
-                         struct nft_set_binding *binding)
-{
-       if (list_empty(&set->bindings) && nft_set_is_anonymous(set) &&
-           nft_is_active(ctx->net, set))
-               list_add_tail_rcu(&set->list, &ctx->table->sets);
-
-       list_add_tail_rcu(&binding->list, &set->bindings);
-}
-EXPORT_SYMBOL_GPL(nf_tables_rebind_set);
-
 void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
-                         struct nft_set_binding *binding)
+                         struct nft_set_binding *binding, bool event)
 {
        list_del_rcu(&binding->list);
 
-       if (list_empty(&set->bindings) && nft_set_is_anonymous(set) &&
-           nft_is_active(ctx->net, set))
+       if (list_empty(&set->bindings) && nft_set_is_anonymous(set)) {
                list_del_rcu(&set->list);
+               if (event)
+                       nf_tables_set_notify(ctx, set, NFT_MSG_DELSET,
+                                            GFP_KERNEL);
+       }
 }
 EXPORT_SYMBOL_GPL(nf_tables_unbind_set);
 
 void nf_tables_destroy_set(const struct nft_ctx *ctx, struct nft_set *set)
 {
-       if (list_empty(&set->bindings) && nft_set_is_anonymous(set) &&
-           nft_is_active(ctx->net, set)) {
-               nf_tables_set_notify(ctx, set, NFT_MSG_DELSET, GFP_ATOMIC);
+       if (list_empty(&set->bindings) && nft_set_is_anonymous(set))
                nft_set_destroy(set);
-       }
 }
 EXPORT_SYMBOL_GPL(nf_tables_destroy_set);
 
@@ -4508,6 +4496,8 @@ err6:
 err5:
        kfree(trans);
 err4:
+       if (obj)
+               obj->use--;
        kfree(elem.priv);
 err3:
        if (nla[NFTA_SET_ELEM_DATA] != NULL)
@@ -6535,6 +6525,9 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
                        nf_tables_rule_notify(&trans->ctx,
                                              nft_trans_rule(trans),
                                              NFT_MSG_DELRULE);
+                       nft_rule_expr_deactivate(&trans->ctx,
+                                                nft_trans_rule(trans),
+                                                NFT_TRANS_COMMIT);
                        break;
                case NFT_MSG_NEWSET:
                        nft_clear(net, nft_trans_set(trans));
@@ -6621,7 +6614,8 @@ static void nf_tables_abort_release(struct nft_trans *trans)
                nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
                break;
        case NFT_MSG_NEWSET:
-               nft_set_destroy(nft_trans_set(trans));
+               if (!nft_trans_set_bound(trans))
+                       nft_set_destroy(nft_trans_set(trans));
                break;
        case NFT_MSG_NEWSETELEM:
                nft_set_elem_destroy(nft_trans_elem_set(trans),
@@ -6682,7 +6676,9 @@ static int __nf_tables_abort(struct net *net)
                case NFT_MSG_NEWRULE:
                        trans->ctx.chain->use--;
                        list_del_rcu(&nft_trans_rule(trans)->list);
-                       nft_rule_expr_deactivate(&trans->ctx, nft_trans_rule(trans));
+                       nft_rule_expr_deactivate(&trans->ctx,
+                                                nft_trans_rule(trans),
+                                                NFT_TRANS_ABORT);
                        break;
                case NFT_MSG_DELRULE:
                        trans->ctx.chain->use++;
@@ -6692,7 +6688,8 @@ static int __nf_tables_abort(struct net *net)
                        break;
                case NFT_MSG_NEWSET:
                        trans->ctx.table->use--;
-                       list_del_rcu(&nft_trans_set(trans)->list);
+                       if (!nft_trans_set_bound(trans))
+                               list_del_rcu(&nft_trans_set(trans)->list);
                        break;
                case NFT_MSG_DELSET:
                        trans->ctx.table->use++;
index 6f41dd7..1f1d90c 100644 (file)
@@ -66,6 +66,7 @@ static bool nf_osf_match_one(const struct sk_buff *skb,
                             int ttl_check,
                             struct nf_osf_hdr_ctx *ctx)
 {
+       const __u8 *optpinit = ctx->optp;
        unsigned int check_WSS = 0;
        int fmatch = FMATCH_WRONG;
        int foptsize, optnum;
@@ -155,6 +156,9 @@ static bool nf_osf_match_one(const struct sk_buff *skb,
                }
        }
 
+       if (fmatch != FMATCH_OK)
+               ctx->optp = optpinit;
+
        return fmatch == FMATCH_OK;
 }
 
index 7334e0b..0a4bad5 100644 (file)
 #include <linux/netfilter_bridge/ebtables.h>
 #include <linux/netfilter_arp/arp_tables.h>
 #include <net/netfilter/nf_tables.h>
+#include <net/netns/generic.h>
 
 struct nft_xt {
        struct list_head        head;
        struct nft_expr_ops     ops;
-       unsigned int            refcnt;
+       refcount_t              refcnt;
+
+       /* used only when transaction mutex is locked */
+       unsigned int            listcnt;
 
        /* Unlike other expressions, ops doesn't have static storage duration.
         * nft core assumes they do.  We use kfree_rcu so that nft core can
@@ -43,10 +47,39 @@ struct nft_xt_match_priv {
        void *info;
 };
 
+struct nft_compat_net {
+       struct list_head nft_target_list;
+       struct list_head nft_match_list;
+};
+
+static unsigned int nft_compat_net_id __read_mostly;
+static struct nft_expr_type nft_match_type;
+static struct nft_expr_type nft_target_type;
+
+static struct nft_compat_net *nft_compat_pernet(struct net *net)
+{
+       return net_generic(net, nft_compat_net_id);
+}
+
+static void nft_xt_get(struct nft_xt *xt)
+{
+       /* refcount_inc() warns on 0 -> 1 transition, but we can't
+        * init the reference count to 1 in .select_ops -- we can't
+        * undo such an increase when another expression inside the same
+        * rule fails afterwards.
+        */
+       if (xt->listcnt == 0)
+               refcount_set(&xt->refcnt, 1);
+       else
+               refcount_inc(&xt->refcnt);
+
+       xt->listcnt++;
+}
+
 static bool nft_xt_put(struct nft_xt *xt)
 {
-       if (--xt->refcnt == 0) {
-               list_del(&xt->head);
+       if (refcount_dec_and_test(&xt->refcnt)) {
+               WARN_ON_ONCE(!list_empty(&xt->head));
                kfree_rcu(xt, rcu_head);
                return true;
        }
@@ -273,7 +306,7 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
                return -EINVAL;
 
        nft_xt = container_of(expr->ops, struct nft_xt, ops);
-       nft_xt->refcnt++;
+       nft_xt_get(nft_xt);
        return 0;
 }
 
@@ -282,6 +315,7 @@ nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
 {
        struct xt_target *target = expr->ops->data;
        void *info = nft_expr_priv(expr);
+       struct module *me = target->me;
        struct xt_tgdtor_param par;
 
        par.net = ctx->net;
@@ -292,7 +326,7 @@ nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
                par.target->destroy(&par);
 
        if (nft_xt_put(container_of(expr->ops, struct nft_xt, ops)))
-               module_put(target->me);
+               module_put(me);
 }
 
 static int nft_extension_dump_info(struct sk_buff *skb, int attr,
@@ -486,7 +520,7 @@ __nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
                return ret;
 
        nft_xt = container_of(expr->ops, struct nft_xt, ops);
-       nft_xt->refcnt++;
+       nft_xt_get(nft_xt);
        return 0;
 }
 
@@ -540,6 +574,18 @@ nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
        __nft_match_destroy(ctx, expr, nft_expr_priv(expr));
 }
 
+static void nft_compat_deactivate(const struct nft_ctx *ctx,
+                                 const struct nft_expr *expr,
+                                 enum nft_trans_phase phase)
+{
+       struct nft_xt *xt = container_of(expr->ops, struct nft_xt, ops);
+
+       if (phase == NFT_TRANS_ABORT || phase == NFT_TRANS_COMMIT) {
+               if (--xt->listcnt == 0)
+                       list_del_init(&xt->head);
+       }
+}
+
 static void
 nft_match_large_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
 {
@@ -734,10 +780,6 @@ static const struct nfnetlink_subsystem nfnl_compat_subsys = {
        .cb             = nfnl_nft_compat_cb,
 };
 
-static LIST_HEAD(nft_match_list);
-
-static struct nft_expr_type nft_match_type;
-
 static bool nft_match_cmp(const struct xt_match *match,
                          const char *name, u32 rev, u32 family)
 {
@@ -749,6 +791,7 @@ static const struct nft_expr_ops *
 nft_match_select_ops(const struct nft_ctx *ctx,
                     const struct nlattr * const tb[])
 {
+       struct nft_compat_net *cn;
        struct nft_xt *nft_match;
        struct xt_match *match;
        unsigned int matchsize;
@@ -765,8 +808,10 @@ nft_match_select_ops(const struct nft_ctx *ctx,
        rev = ntohl(nla_get_be32(tb[NFTA_MATCH_REV]));
        family = ctx->family;
 
+       cn = nft_compat_pernet(ctx->net);
+
        /* Re-use the existing match if it's already loaded. */
-       list_for_each_entry(nft_match, &nft_match_list, head) {
+       list_for_each_entry(nft_match, &cn->nft_match_list, head) {
                struct xt_match *match = nft_match->ops.data;
 
                if (nft_match_cmp(match, mt_name, rev, family))
@@ -789,11 +834,12 @@ nft_match_select_ops(const struct nft_ctx *ctx,
                goto err;
        }
 
-       nft_match->refcnt = 0;
+       refcount_set(&nft_match->refcnt, 0);
        nft_match->ops.type = &nft_match_type;
        nft_match->ops.eval = nft_match_eval;
        nft_match->ops.init = nft_match_init;
        nft_match->ops.destroy = nft_match_destroy;
+       nft_match->ops.deactivate = nft_compat_deactivate;
        nft_match->ops.dump = nft_match_dump;
        nft_match->ops.validate = nft_match_validate;
        nft_match->ops.data = match;
@@ -810,7 +856,8 @@ nft_match_select_ops(const struct nft_ctx *ctx,
 
        nft_match->ops.size = matchsize;
 
-       list_add(&nft_match->head, &nft_match_list);
+       nft_match->listcnt = 0;
+       list_add(&nft_match->head, &cn->nft_match_list);
 
        return &nft_match->ops;
 err:
@@ -826,10 +873,6 @@ static struct nft_expr_type nft_match_type __read_mostly = {
        .owner          = THIS_MODULE,
 };
 
-static LIST_HEAD(nft_target_list);
-
-static struct nft_expr_type nft_target_type;
-
 static bool nft_target_cmp(const struct xt_target *tg,
                           const char *name, u32 rev, u32 family)
 {
@@ -841,6 +884,7 @@ static const struct nft_expr_ops *
 nft_target_select_ops(const struct nft_ctx *ctx,
                      const struct nlattr * const tb[])
 {
+       struct nft_compat_net *cn;
        struct nft_xt *nft_target;
        struct xt_target *target;
        char *tg_name;
@@ -861,8 +905,9 @@ nft_target_select_ops(const struct nft_ctx *ctx,
            strcmp(tg_name, "standard") == 0)
                return ERR_PTR(-EINVAL);
 
+       cn = nft_compat_pernet(ctx->net);
        /* Re-use the existing target if it's already loaded. */
-       list_for_each_entry(nft_target, &nft_target_list, head) {
+       list_for_each_entry(nft_target, &cn->nft_target_list, head) {
                struct xt_target *target = nft_target->ops.data;
 
                if (!target->target)
@@ -893,11 +938,12 @@ nft_target_select_ops(const struct nft_ctx *ctx,
                goto err;
        }
 
-       nft_target->refcnt = 0;
+       refcount_set(&nft_target->refcnt, 0);
        nft_target->ops.type = &nft_target_type;
        nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize));
        nft_target->ops.init = nft_target_init;
        nft_target->ops.destroy = nft_target_destroy;
+       nft_target->ops.deactivate = nft_compat_deactivate;
        nft_target->ops.dump = nft_target_dump;
        nft_target->ops.validate = nft_target_validate;
        nft_target->ops.data = target;
@@ -907,7 +953,8 @@ nft_target_select_ops(const struct nft_ctx *ctx,
        else
                nft_target->ops.eval = nft_target_eval_xt;
 
-       list_add(&nft_target->head, &nft_target_list);
+       nft_target->listcnt = 0;
+       list_add(&nft_target->head, &cn->nft_target_list);
 
        return &nft_target->ops;
 err:
@@ -923,13 +970,74 @@ static struct nft_expr_type nft_target_type __read_mostly = {
        .owner          = THIS_MODULE,
 };
 
+static int __net_init nft_compat_init_net(struct net *net)
+{
+       struct nft_compat_net *cn = nft_compat_pernet(net);
+
+       INIT_LIST_HEAD(&cn->nft_target_list);
+       INIT_LIST_HEAD(&cn->nft_match_list);
+
+       return 0;
+}
+
+static void __net_exit nft_compat_exit_net(struct net *net)
+{
+       struct nft_compat_net *cn = nft_compat_pernet(net);
+       struct nft_xt *xt, *next;
+
+       if (list_empty(&cn->nft_match_list) &&
+           list_empty(&cn->nft_target_list))
+               return;
+
+       /* If there was an error that caused nft_xt expr to not be initialized
+        * fully and noone else requested the same expression later, the lists
+        * contain 0-refcount entries that still hold module reference.
+        *
+        * Clean them here.
+        */
+       mutex_lock(&net->nft.commit_mutex);
+       list_for_each_entry_safe(xt, next, &cn->nft_target_list, head) {
+               struct xt_target *target = xt->ops.data;
+
+               list_del_init(&xt->head);
+
+               if (refcount_read(&xt->refcnt))
+                       continue;
+               module_put(target->me);
+               kfree(xt);
+       }
+
+       list_for_each_entry_safe(xt, next, &cn->nft_match_list, head) {
+               struct xt_match *match = xt->ops.data;
+
+               list_del_init(&xt->head);
+
+               if (refcount_read(&xt->refcnt))
+                       continue;
+               module_put(match->me);
+               kfree(xt);
+       }
+       mutex_unlock(&net->nft.commit_mutex);
+}
+
+static struct pernet_operations nft_compat_net_ops = {
+       .init   = nft_compat_init_net,
+       .exit   = nft_compat_exit_net,
+       .id     = &nft_compat_net_id,
+       .size   = sizeof(struct nft_compat_net),
+};
+
 static int __init nft_compat_module_init(void)
 {
        int ret;
 
+       ret = register_pernet_subsys(&nft_compat_net_ops);
+       if (ret < 0)
+               goto err_target;
+
        ret = nft_register_expr(&nft_match_type);
        if (ret < 0)
-               return ret;
+               goto err_pernet;
 
        ret = nft_register_expr(&nft_target_type);
        if (ret < 0)
@@ -942,45 +1050,21 @@ static int __init nft_compat_module_init(void)
        }
 
        return ret;
-
 err_target:
        nft_unregister_expr(&nft_target_type);
 err_match:
        nft_unregister_expr(&nft_match_type);
+err_pernet:
+       unregister_pernet_subsys(&nft_compat_net_ops);
        return ret;
 }
 
 static void __exit nft_compat_module_exit(void)
 {
-       struct nft_xt *xt, *next;
-
-       /* list should be empty here, it can be non-empty only in case there
-        * was an error that caused nft_xt expr to not be initialized fully
-        * and noone else requested the same expression later.
-        *
-        * In this case, the lists contain 0-refcount entries that still
-        * hold module reference.
-        */
-       list_for_each_entry_safe(xt, next, &nft_target_list, head) {
-               struct xt_target *target = xt->ops.data;
-
-               if (WARN_ON_ONCE(xt->refcnt))
-                       continue;
-               module_put(target->me);
-               kfree(xt);
-       }
-
-       list_for_each_entry_safe(xt, next, &nft_match_list, head) {
-               struct xt_match *match = xt->ops.data;
-
-               if (WARN_ON_ONCE(xt->refcnt))
-                       continue;
-               module_put(match->me);
-               kfree(xt);
-       }
        nfnetlink_subsys_unregister(&nfnl_compat_subsys);
        nft_unregister_expr(&nft_target_type);
        nft_unregister_expr(&nft_match_type);
+       unregister_pernet_subsys(&nft_compat_net_ops);
 }
 
 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_NFT_COMPAT);
index 07d4efd..f1172f9 100644 (file)
@@ -235,20 +235,17 @@ err1:
        return err;
 }
 
-static void nft_dynset_activate(const struct nft_ctx *ctx,
-                               const struct nft_expr *expr)
-{
-       struct nft_dynset *priv = nft_expr_priv(expr);
-
-       nf_tables_rebind_set(ctx, priv->set, &priv->binding);
-}
-
 static void nft_dynset_deactivate(const struct nft_ctx *ctx,
-                                 const struct nft_expr *expr)
+                                 const struct nft_expr *expr,
+                                 enum nft_trans_phase phase)
 {
        struct nft_dynset *priv = nft_expr_priv(expr);
 
-       nf_tables_unbind_set(ctx, priv->set, &priv->binding);
+       if (phase == NFT_TRANS_PREPARE)
+               return;
+
+       nf_tables_unbind_set(ctx, priv->set, &priv->binding,
+                            phase == NFT_TRANS_COMMIT);
 }
 
 static void nft_dynset_destroy(const struct nft_ctx *ctx,
@@ -296,7 +293,6 @@ static const struct nft_expr_ops nft_dynset_ops = {
        .eval           = nft_dynset_eval,
        .init           = nft_dynset_init,
        .destroy        = nft_dynset_destroy,
-       .activate       = nft_dynset_activate,
        .deactivate     = nft_dynset_deactivate,
        .dump           = nft_dynset_dump,
 };
index 974525e..6e6b9ad 100644 (file)
@@ -12,6 +12,7 @@
 #include <net/netfilter/nf_conntrack_core.h>
 #include <linux/netfilter/nf_conntrack_common.h>
 #include <net/netfilter/nf_flow_table.h>
+#include <net/netfilter/nf_conntrack_helper.h>
 
 struct nft_flow_offload {
        struct nft_flowtable    *flowtable;
@@ -29,10 +30,12 @@ static int nft_flow_route(const struct nft_pktinfo *pkt,
        memset(&fl, 0, sizeof(fl));
        switch (nft_pf(pkt)) {
        case NFPROTO_IPV4:
-               fl.u.ip4.daddr = ct->tuplehash[!dir].tuple.dst.u3.ip;
+               fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip;
+               fl.u.ip4.flowi4_oif = nft_in(pkt)->ifindex;
                break;
        case NFPROTO_IPV6:
-               fl.u.ip6.daddr = ct->tuplehash[!dir].tuple.dst.u3.in6;
+               fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6;
+               fl.u.ip6.flowi6_oif = nft_in(pkt)->ifindex;
                break;
        }
 
@@ -41,9 +44,7 @@ static int nft_flow_route(const struct nft_pktinfo *pkt,
                return -ENOENT;
 
        route->tuple[dir].dst           = this_dst;
-       route->tuple[dir].ifindex       = nft_in(pkt)->ifindex;
        route->tuple[!dir].dst          = other_dst;
-       route->tuple[!dir].ifindex      = nft_out(pkt)->ifindex;
 
        return 0;
 }
@@ -66,6 +67,7 @@ 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;
+       const struct nf_conn_help *help;
        enum ip_conntrack_info ctinfo;
        struct nf_flow_route route;
        struct flow_offload *flow;
@@ -88,7 +90,8 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
                goto out;
        }
 
-       if (test_bit(IPS_HELPER_BIT, &ct->status))
+       help = nfct_help(ct);
+       if (help)
                goto out;
 
        if (ctinfo == IP_CT_NEW ||
index 0777a93..3f6d1d2 100644 (file)
@@ -72,10 +72,14 @@ static void nft_immediate_activate(const struct nft_ctx *ctx,
 }
 
 static void nft_immediate_deactivate(const struct nft_ctx *ctx,
-                                    const struct nft_expr *expr)
+                                    const struct nft_expr *expr,
+                                    enum nft_trans_phase phase)
 {
        const struct nft_immediate_expr *priv = nft_expr_priv(expr);
 
+       if (phase == NFT_TRANS_COMMIT)
+               return;
+
        return nft_data_release(&priv->data, nft_dreg_to_type(priv->dreg));
 }
 
index 227b2b1..14496da 100644 (file)
@@ -121,20 +121,17 @@ static int nft_lookup_init(const struct nft_ctx *ctx,
        return 0;
 }
 
-static void nft_lookup_activate(const struct nft_ctx *ctx,
-                               const struct nft_expr *expr)
-{
-       struct nft_lookup *priv = nft_expr_priv(expr);
-
-       nf_tables_rebind_set(ctx, priv->set, &priv->binding);
-}
-
 static void nft_lookup_deactivate(const struct nft_ctx *ctx,
-                                 const struct nft_expr *expr)
+                                 const struct nft_expr *expr,
+                                 enum nft_trans_phase phase)
 {
        struct nft_lookup *priv = nft_expr_priv(expr);
 
-       nf_tables_unbind_set(ctx, priv->set, &priv->binding);
+       if (phase == NFT_TRANS_PREPARE)
+               return;
+
+       nf_tables_unbind_set(ctx, priv->set, &priv->binding,
+                            phase == NFT_TRANS_COMMIT);
 }
 
 static void nft_lookup_destroy(const struct nft_ctx *ctx,
@@ -225,7 +222,6 @@ static const struct nft_expr_ops nft_lookup_ops = {
        .size           = NFT_EXPR_SIZE(sizeof(struct nft_lookup)),
        .eval           = nft_lookup_eval,
        .init           = nft_lookup_init,
-       .activate       = nft_lookup_activate,
        .deactivate     = nft_lookup_deactivate,
        .destroy        = nft_lookup_destroy,
        .dump           = nft_lookup_dump,
index a3185ca..ae178e9 100644 (file)
@@ -155,20 +155,17 @@ nla_put_failure:
        return -1;
 }
 
-static void nft_objref_map_activate(const struct nft_ctx *ctx,
-                                   const struct nft_expr *expr)
-{
-       struct nft_objref_map *priv = nft_expr_priv(expr);
-
-       nf_tables_rebind_set(ctx, priv->set, &priv->binding);
-}
-
 static void nft_objref_map_deactivate(const struct nft_ctx *ctx,
-                                     const struct nft_expr *expr)
+                                     const struct nft_expr *expr,
+                                     enum nft_trans_phase phase)
 {
        struct nft_objref_map *priv = nft_expr_priv(expr);
 
-       nf_tables_unbind_set(ctx, priv->set, &priv->binding);
+       if (phase == NFT_TRANS_PREPARE)
+               return;
+
+       nf_tables_unbind_set(ctx, priv->set, &priv->binding,
+                            phase == NFT_TRANS_COMMIT);
 }
 
 static void nft_objref_map_destroy(const struct nft_ctx *ctx,
@@ -185,7 +182,6 @@ static const struct nft_expr_ops nft_objref_map_ops = {
        .size           = NFT_EXPR_SIZE(sizeof(struct nft_objref_map)),
        .eval           = nft_objref_map_eval,
        .init           = nft_objref_map_init,
-       .activate       = nft_objref_map_activate,
        .deactivate     = nft_objref_map_deactivate,
        .destroy        = nft_objref_map_destroy,
        .dump           = nft_objref_map_dump,
index aecadd4..13e1ac3 100644 (file)
@@ -1899,7 +1899,7 @@ static int __init xt_init(void)
                seqcount_init(&per_cpu(xt_recseq, i));
        }
 
-       xt = kmalloc_array(NFPROTO_NUMPROTO, sizeof(struct xt_af), GFP_KERNEL);
+       xt = kcalloc(NFPROTO_NUMPROTO, sizeof(struct xt_af), GFP_KERNEL);
        if (!xt)
                return -ENOMEM;
 
index cbd51ed..908e53a 100644 (file)
@@ -52,21 +52,21 @@ void nr_start_t1timer(struct sock *sk)
 {
        struct nr_sock *nr = nr_sk(sk);
 
-       mod_timer(&nr->t1timer, jiffies + nr->t1);
+       sk_reset_timer(sk, &nr->t1timer, jiffies + nr->t1);
 }
 
 void nr_start_t2timer(struct sock *sk)
 {
        struct nr_sock *nr = nr_sk(sk);
 
-       mod_timer(&nr->t2timer, jiffies + nr->t2);
+       sk_reset_timer(sk, &nr->t2timer, jiffies + nr->t2);
 }
 
 void nr_start_t4timer(struct sock *sk)
 {
        struct nr_sock *nr = nr_sk(sk);
 
-       mod_timer(&nr->t4timer, jiffies + nr->t4);
+       sk_reset_timer(sk, &nr->t4timer, jiffies + nr->t4);
 }
 
 void nr_start_idletimer(struct sock *sk)
@@ -74,37 +74,37 @@ void nr_start_idletimer(struct sock *sk)
        struct nr_sock *nr = nr_sk(sk);
 
        if (nr->idle > 0)
-               mod_timer(&nr->idletimer, jiffies + nr->idle);
+               sk_reset_timer(sk, &nr->idletimer, jiffies + nr->idle);
 }
 
 void nr_start_heartbeat(struct sock *sk)
 {
-       mod_timer(&sk->sk_timer, jiffies + 5 * HZ);
+       sk_reset_timer(sk, &sk->sk_timer, jiffies + 5 * HZ);
 }
 
 void nr_stop_t1timer(struct sock *sk)
 {
-       del_timer(&nr_sk(sk)->t1timer);
+       sk_stop_timer(sk, &nr_sk(sk)->t1timer);
 }
 
 void nr_stop_t2timer(struct sock *sk)
 {
-       del_timer(&nr_sk(sk)->t2timer);
+       sk_stop_timer(sk, &nr_sk(sk)->t2timer);
 }
 
 void nr_stop_t4timer(struct sock *sk)
 {
-       del_timer(&nr_sk(sk)->t4timer);
+       sk_stop_timer(sk, &nr_sk(sk)->t4timer);
 }
 
 void nr_stop_idletimer(struct sock *sk)
 {
-       del_timer(&nr_sk(sk)->idletimer);
+       sk_stop_timer(sk, &nr_sk(sk)->idletimer);
 }
 
 void nr_stop_heartbeat(struct sock *sk)
 {
-       del_timer(&sk->sk_timer);
+       sk_stop_timer(sk, &sk->sk_timer);
 }
 
 int nr_t1timer_running(struct sock *sk)
index 57e0776..f54cf17 100644 (file)
@@ -276,10 +276,12 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
 
        nexthdr = ipv6_find_hdr(skb, &payload_ofs, -1, &frag_off, &flags);
        if (flags & IP6_FH_F_FRAG) {
-               if (frag_off)
+               if (frag_off) {
                        key->ip.frag = OVS_FRAG_TYPE_LATER;
-               else
-                       key->ip.frag = OVS_FRAG_TYPE_FIRST;
+                       key->ip.proto = nexthdr;
+                       return 0;
+               }
+               key->ip.frag = OVS_FRAG_TYPE_FIRST;
        } else {
                key->ip.frag = OVS_FRAG_TYPE_NONE;
        }
index 435a4bd..691da85 100644 (file)
@@ -500,7 +500,7 @@ static int __parse_flow_nlattrs(const struct nlattr *attr,
                        return -EINVAL;
                }
 
-               if (!nz || !is_all_zero(nla_data(nla), expected_len)) {
+               if (!nz || !is_all_zero(nla_data(nla), nla_len(nla))) {
                        attrs |= 1 << type;
                        a[type] = nla;
                }
index eedacde..1cd1d83 100644 (file)
@@ -2628,7 +2628,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
                addr    = saddr->sll_halen ? saddr->sll_addr : NULL;
                dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex);
                if (addr && dev && saddr->sll_halen < dev->addr_len)
-                       goto out;
+                       goto out_put;
        }
 
        err = -ENXIO;
@@ -2828,7 +2828,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
                addr    = saddr->sll_halen ? saddr->sll_addr : NULL;
                dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex);
                if (addr && dev && saddr->sll_halen < dev->addr_len)
-                       goto out;
+                       goto out_unlock;
        }
 
        err = -ENXIO;
@@ -2887,7 +2887,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
                        goto out_free;
        } else if (reserve) {
                skb_reserve(skb, -reserve);
-               if (len < reserve)
+               if (len < reserve + sizeof(struct ipv6hdr) &&
+                   dev->min_header_len != dev->hard_header_len)
                        skb_reset_network_header(skb);
        }
 
@@ -4291,7 +4292,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
                rb->frames_per_block = req->tp_block_size / req->tp_frame_size;
                if (unlikely(rb->frames_per_block == 0))
                        goto out;
-               if (unlikely(req->tp_block_size > UINT_MAX / req->tp_block_nr))
+               if (unlikely(rb->frames_per_block > UINT_MAX / req->tp_block_nr))
                        goto out;
                if (unlikely((rb->frames_per_block * req->tp_block_nr) !=
                                        req->tp_frame_nr))
index 762d2c6..17c9d9f 100644 (file)
@@ -78,10 +78,10 @@ struct rds_sock *rds_find_bound(const struct in6_addr *addr, __be16 port,
        __rds_create_bind_key(key, addr, port, scope_id);
        rcu_read_lock();
        rs = rhashtable_lookup(&bind_hash_table, key, ht_parms);
-       if (rs && !sock_flag(rds_rs_to_sk(rs), SOCK_DEAD))
-               rds_sock_addref(rs);
-       else
+       if (rs && (sock_flag(rds_rs_to_sk(rs), SOCK_DEAD) ||
+                  !refcount_inc_not_zero(&rds_rs_to_sk(rs)->sk_refcnt)))
                rs = NULL;
+
        rcu_read_unlock();
 
        rdsdebug("returning rs %p for %pI6c:%u\n", rs, addr,
index 2dcb555..4e0c36a 100644 (file)
@@ -522,7 +522,7 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm,
        if (be32_to_cpu(rm->m_inc.i_hdr.h_len) == 0)
                i = 1;
        else
-               i = ceil(be32_to_cpu(rm->m_inc.i_hdr.h_len), RDS_FRAG_SIZE);
+               i = DIV_ROUND_UP(be32_to_cpu(rm->m_inc.i_hdr.h_len), RDS_FRAG_SIZE);
 
        work_alloc = rds_ib_ring_alloc(&ic->i_send_ring, i, &pos);
        if (work_alloc == 0) {
@@ -879,7 +879,7 @@ int rds_ib_xmit_rdma(struct rds_connection *conn, struct rm_rdma_op *op)
         * Instead of knowing how to return a partial rdma read/write we insist that there
         * be enough work requests to send the entire message.
         */
-       i = ceil(op->op_count, max_sge);
+       i = DIV_ROUND_UP(op->op_count, max_sge);
 
        work_alloc = rds_ib_ring_alloc(&ic->i_send_ring, i, &pos);
        if (work_alloc != i) {
index f139420..50f13f1 100644 (file)
@@ -341,7 +341,7 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in
 {
        struct rds_message *rm;
        unsigned int i;
-       int num_sgs = ceil(total_len, PAGE_SIZE);
+       int num_sgs = DIV_ROUND_UP(total_len, PAGE_SIZE);
        int extra_bytes = num_sgs * sizeof(struct scatterlist);
        int ret;
 
@@ -351,7 +351,7 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in
 
        set_bit(RDS_MSG_PAGEVEC, &rm->m_flags);
        rm->m_inc.i_hdr.h_len = cpu_to_be32(total_len);
-       rm->data.op_nents = ceil(total_len, PAGE_SIZE);
+       rm->data.op_nents = DIV_ROUND_UP(total_len, PAGE_SIZE);
        rm->data.op_sg = rds_message_alloc_sgs(rm, num_sgs, &ret);
        if (!rm->data.op_sg) {
                rds_message_put(rm);
index 02ec4a3..4ffe100 100644 (file)
@@ -48,10 +48,6 @@ void rdsdebug(char *fmt, ...)
 }
 #endif
 
-/* XXX is there one of these somewhere? */
-#define ceil(x, y) \
-       ({ unsigned long __x = (x), __y = (y); (__x + __y - 1) / __y; })
-
 #define RDS_FRAG_SHIFT 12
 #define RDS_FRAG_SIZE  ((unsigned int)(1 << RDS_FRAG_SHIFT))
 
index 3d822ba..fd8b687 100644 (file)
@@ -1107,7 +1107,7 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
        size_t total_payload_len = payload_len, rdma_payload_len = 0;
        bool zcopy = ((msg->msg_flags & MSG_ZEROCOPY) &&
                      sock_flag(rds_rs_to_sk(rs), SOCK_ZEROCOPY));
-       int num_sgs = ceil(payload_len, PAGE_SIZE);
+       int num_sgs = DIV_ROUND_UP(payload_len, PAGE_SIZE);
        int namelen;
        struct rds_iov_vector_arr vct;
        int ind;
index 77e9f85..f2ff21d 100644 (file)
@@ -850,6 +850,7 @@ void rose_link_device_down(struct net_device *dev)
 
 /*
  *     Route a frame to an appropriate AX.25 connection.
+ *     A NULL ax25_cb indicates an internally generated frame.
  */
 int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 {
@@ -867,6 +868,10 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 
        if (skb->len < ROSE_MIN_LEN)
                return res;
+
+       if (!ax25)
+               return rose_loopback_queue(skb, NULL);
+
        frametype = skb->data[2];
        lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF);
        if (frametype == ROSE_CALL_REQUEST &&
index a2522f9..96f2952 100644 (file)
@@ -419,76 +419,6 @@ u32 rxrpc_kernel_get_epoch(struct socket *sock, struct rxrpc_call *call)
 EXPORT_SYMBOL(rxrpc_kernel_get_epoch);
 
 /**
- * rxrpc_kernel_check_call - Check a call's state
- * @sock: The socket the call is on
- * @call: The call to check
- * @_compl: Where to store the completion state
- * @_abort_code: Where to store any abort code
- *
- * Allow a kernel service to query the state of a call and find out the manner
- * of its termination if it has completed.  Returns -EINPROGRESS if the call is
- * still going, 0 if the call finished successfully, -ECONNABORTED if the call
- * was aborted and an appropriate error if the call failed in some other way.
- */
-int rxrpc_kernel_check_call(struct socket *sock, struct rxrpc_call *call,
-                           enum rxrpc_call_completion *_compl, u32 *_abort_code)
-{
-       if (call->state != RXRPC_CALL_COMPLETE)
-               return -EINPROGRESS;
-       smp_rmb();
-       *_compl = call->completion;
-       *_abort_code = call->abort_code;
-       return call->error;
-}
-EXPORT_SYMBOL(rxrpc_kernel_check_call);
-
-/**
- * rxrpc_kernel_retry_call - Allow a kernel service to retry a call
- * @sock: The socket the call is on
- * @call: The call to retry
- * @srx: The address of the peer to contact
- * @key: The security context to use (defaults to socket setting)
- *
- * Allow a kernel service to try resending a client call that failed due to a
- * network error to a new address.  The Tx queue is maintained intact, thereby
- * relieving the need to re-encrypt any request data that has already been
- * buffered.
- */
-int rxrpc_kernel_retry_call(struct socket *sock, struct rxrpc_call *call,
-                           struct sockaddr_rxrpc *srx, struct key *key)
-{
-       struct rxrpc_conn_parameters cp;
-       struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
-       int ret;
-
-       _enter("%d{%d}", call->debug_id, atomic_read(&call->usage));
-
-       if (!key)
-               key = rx->key;
-       if (key && !key->payload.data[0])
-               key = NULL; /* a no-security key */
-
-       memset(&cp, 0, sizeof(cp));
-       cp.local                = rx->local;
-       cp.key                  = key;
-       cp.security_level       = 0;
-       cp.exclusive            = false;
-       cp.service_id           = srx->srx_service;
-
-       mutex_lock(&call->user_mutex);
-
-       ret = rxrpc_prepare_call_for_retry(rx, call);
-       if (ret == 0)
-               ret = rxrpc_retry_client_call(rx, call, &cp, srx, GFP_KERNEL);
-
-       mutex_unlock(&call->user_mutex);
-       rxrpc_put_peer(cp.peer);
-       _leave(" = %d", ret);
-       return ret;
-}
-EXPORT_SYMBOL(rxrpc_kernel_retry_call);
-
-/**
  * rxrpc_kernel_new_call_notification - Get notifications of new calls
  * @sock: The socket to intercept received messages on
  * @notify_new_call: Function to be called when new calls appear
index bc628ac..4b1a534 100644 (file)
@@ -476,7 +476,6 @@ enum rxrpc_call_flag {
        RXRPC_CALL_EXPOSED,             /* The call was exposed to the world */
        RXRPC_CALL_RX_LAST,             /* Received the last packet (at rxtx_top) */
        RXRPC_CALL_TX_LAST,             /* Last packet in Tx buffer (at rxtx_top) */
-       RXRPC_CALL_TX_LASTQ,            /* Last packet has been queued */
        RXRPC_CALL_SEND_PING,           /* A ping will need to be sent */
        RXRPC_CALL_PINGING,             /* Ping in process */
        RXRPC_CALL_RETRANS_TIMEOUT,     /* Retransmission due to timeout occurred */
@@ -518,6 +517,18 @@ enum rxrpc_call_state {
 };
 
 /*
+ * Call completion condition (state == RXRPC_CALL_COMPLETE).
+ */
+enum rxrpc_call_completion {
+       RXRPC_CALL_SUCCEEDED,           /* - Normal termination */
+       RXRPC_CALL_REMOTELY_ABORTED,    /* - call aborted by peer */
+       RXRPC_CALL_LOCALLY_ABORTED,     /* - call aborted locally on error or close */
+       RXRPC_CALL_LOCAL_ERROR,         /* - call failed due to local error */
+       RXRPC_CALL_NETWORK_ERROR,       /* - call terminated by network error */
+       NR__RXRPC_CALL_COMPLETIONS
+};
+
+/*
  * Call Tx congestion management modes.
  */
 enum rxrpc_congest_mode {
@@ -761,15 +772,9 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *,
                                         struct sockaddr_rxrpc *,
                                         struct rxrpc_call_params *, gfp_t,
                                         unsigned int);
-int rxrpc_retry_client_call(struct rxrpc_sock *,
-                           struct rxrpc_call *,
-                           struct rxrpc_conn_parameters *,
-                           struct sockaddr_rxrpc *,
-                           gfp_t);
 void rxrpc_incoming_call(struct rxrpc_sock *, struct rxrpc_call *,
                         struct sk_buff *);
 void rxrpc_release_call(struct rxrpc_sock *, struct rxrpc_call *);
-int rxrpc_prepare_call_for_retry(struct rxrpc_sock *, struct rxrpc_call *);
 void rxrpc_release_calls_on_socket(struct rxrpc_sock *);
 bool __rxrpc_queue_call(struct rxrpc_call *);
 bool rxrpc_queue_call(struct rxrpc_call *);
index 8f1a8f8..8aa2937 100644 (file)
@@ -325,48 +325,6 @@ error:
 }
 
 /*
- * Retry a call to a new address.  It is expected that the Tx queue of the call
- * will contain data previously packaged for an old call.
- */
-int rxrpc_retry_client_call(struct rxrpc_sock *rx,
-                           struct rxrpc_call *call,
-                           struct rxrpc_conn_parameters *cp,
-                           struct sockaddr_rxrpc *srx,
-                           gfp_t gfp)
-{
-       const void *here = __builtin_return_address(0);
-       int ret;
-
-       /* Set up or get a connection record and set the protocol parameters,
-        * including channel number and call ID.
-        */
-       ret = rxrpc_connect_call(rx, call, cp, srx, gfp);
-       if (ret < 0)
-               goto error;
-
-       trace_rxrpc_call(call, rxrpc_call_connected, atomic_read(&call->usage),
-                        here, NULL);
-
-       rxrpc_start_call_timer(call);
-
-       _net("CALL new %d on CONN %d", call->debug_id, call->conn->debug_id);
-
-       if (!test_and_set_bit(RXRPC_CALL_EV_RESEND, &call->events))
-               rxrpc_queue_call(call);
-
-       _leave(" = 0");
-       return 0;
-
-error:
-       rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR,
-                                 RX_CALL_DEAD, ret);
-       trace_rxrpc_call(call, rxrpc_call_error, atomic_read(&call->usage),
-                        here, ERR_PTR(ret));
-       _leave(" = %d", ret);
-       return ret;
-}
-
-/*
  * Set up an incoming call.  call->conn points to the connection.
  * This is called in BH context and isn't allowed to fail.
  */
@@ -534,61 +492,6 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
 }
 
 /*
- * Prepare a kernel service call for retry.
- */
-int rxrpc_prepare_call_for_retry(struct rxrpc_sock *rx, struct rxrpc_call *call)
-{
-       const void *here = __builtin_return_address(0);
-       int i;
-       u8 last = 0;
-
-       _enter("{%d,%d}", call->debug_id, atomic_read(&call->usage));
-
-       trace_rxrpc_call(call, rxrpc_call_release, atomic_read(&call->usage),
-                        here, (const void *)call->flags);
-
-       ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE);
-       ASSERTCMP(call->completion, !=, RXRPC_CALL_REMOTELY_ABORTED);
-       ASSERTCMP(call->completion, !=, RXRPC_CALL_LOCALLY_ABORTED);
-       ASSERT(list_empty(&call->recvmsg_link));
-
-       del_timer_sync(&call->timer);
-
-       _debug("RELEASE CALL %p (%d CONN %p)", call, call->debug_id, call->conn);
-
-       if (call->conn)
-               rxrpc_disconnect_call(call);
-
-       if (rxrpc_is_service_call(call) ||
-           !call->tx_phase ||
-           call->tx_hard_ack != 0 ||
-           call->rx_hard_ack != 0 ||
-           call->rx_top != 0)
-               return -EINVAL;
-
-       call->state = RXRPC_CALL_UNINITIALISED;
-       call->completion = RXRPC_CALL_SUCCEEDED;
-       call->call_id = 0;
-       call->cid = 0;
-       call->cong_cwnd = 0;
-       call->cong_extra = 0;
-       call->cong_ssthresh = 0;
-       call->cong_mode = 0;
-       call->cong_dup_acks = 0;
-       call->cong_cumul_acks = 0;
-       call->acks_lowest_nak = 0;
-
-       for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) {
-               last |= call->rxtx_annotations[i];
-               call->rxtx_annotations[i] &= RXRPC_TX_ANNO_LAST;
-               call->rxtx_annotations[i] |= RXRPC_TX_ANNO_RETRANS;
-       }
-
-       _leave(" = 0");
-       return 0;
-}
-
-/*
  * release all the calls associated with a socket
  */
 void rxrpc_release_calls_on_socket(struct rxrpc_sock *rx)
index 521189f..b2adfa8 100644 (file)
@@ -562,10 +562,7 @@ static void rxrpc_activate_one_channel(struct rxrpc_connection *conn,
        clear_bit(RXRPC_CONN_FINAL_ACK_0 + channel, &conn->flags);
 
        write_lock_bh(&call->state_lock);
-       if (!test_bit(RXRPC_CALL_TX_LASTQ, &call->flags))
-               call->state = RXRPC_CALL_CLIENT_SEND_REQUEST;
-       else
-               call->state = RXRPC_CALL_CLIENT_AWAIT_REPLY;
+       call->state = RXRPC_CALL_CLIENT_SEND_REQUEST;
        write_unlock_bh(&call->state_lock);
 
        rxrpc_see_call(call);
index eaf19eb..3f7bb11 100644 (file)
@@ -596,6 +596,7 @@ error_requeue_call:
        }
 error_no_call:
        release_sock(&rx->sk);
+error_trace:
        trace_rxrpc_recvmsg(call, rxrpc_recvmsg_return, 0, 0, 0, ret);
        return ret;
 
@@ -604,7 +605,7 @@ wait_interrupted:
 wait_error:
        finish_wait(sk_sleep(&rx->sk), &wait);
        call = NULL;
-       goto error_no_call;
+       goto error_trace;
 }
 
 /**
index be01f9c..46c9312 100644 (file)
@@ -169,10 +169,8 @@ static void rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
 
        ASSERTCMP(seq, ==, call->tx_top + 1);
 
-       if (last) {
+       if (last)
                annotation |= RXRPC_TX_ANNO_LAST;
-               set_bit(RXRPC_CALL_TX_LASTQ, &call->flags);
-       }
 
        /* We have to set the timestamp before queueing as the retransmit
         * algorithm can see the packet as soon as we queue it.
@@ -386,6 +384,11 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
                                call->tx_total_len -= copy;
                }
 
+               /* check for the far side aborting the call or a network error
+                * occurring */
+               if (call->state == RXRPC_CALL_COMPLETE)
+                       goto call_terminated;
+
                /* add the packet to the send queue if it's now full */
                if (sp->remain <= 0 ||
                    (msg_data_left(msg) == 0 && !more)) {
@@ -425,16 +428,6 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
                                           notify_end_tx);
                        skb = NULL;
                }
-
-               /* Check for the far side aborting the call or a network error
-                * occurring.  If this happens, save any packet that was under
-                * construction so that in the case of a network error, the
-                * call can be retried or redirected.
-                */
-               if (call->state == RXRPC_CALL_COMPLETE) {
-                       ret = call->error;
-                       goto out;
-               }
        } while (msg_data_left(msg) > 0);
 
 success:
@@ -444,6 +437,11 @@ out:
        _leave(" = %d", ret);
        return ret;
 
+call_terminated:
+       rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
+       _leave(" = %d", call->error);
+       return call->error;
+
 maybe_error:
        if (copied)
                goto success;
index c3b90fa..8b43fe0 100644 (file)
@@ -197,6 +197,15 @@ static const struct nla_policy tunnel_key_policy[TCA_TUNNEL_KEY_MAX + 1] = {
        [TCA_TUNNEL_KEY_ENC_TTL]      = { .type = NLA_U8 },
 };
 
+static void tunnel_key_release_params(struct tcf_tunnel_key_params *p)
+{
+       if (!p)
+               return;
+       if (p->tcft_action == TCA_TUNNEL_KEY_ACT_SET)
+               dst_release(&p->tcft_enc_metadata->dst);
+       kfree_rcu(p, rcu);
+}
+
 static int tunnel_key_init(struct net *net, struct nlattr *nla,
                           struct nlattr *est, struct tc_action **a,
                           int ovr, int bind, bool rtnl_held,
@@ -360,8 +369,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
        rcu_swap_protected(t->params, params_new,
                           lockdep_is_held(&t->tcf_lock));
        spin_unlock_bh(&t->tcf_lock);
-       if (params_new)
-               kfree_rcu(params_new, rcu);
+       tunnel_key_release_params(params_new);
 
        if (ret == ACT_P_CREATED)
                tcf_idr_insert(tn, *a);
@@ -385,12 +393,7 @@ static void tunnel_key_release(struct tc_action *a)
        struct tcf_tunnel_key_params *params;
 
        params = rcu_dereference_protected(t->params, 1);
-       if (params) {
-               if (params->tcft_action == TCA_TUNNEL_KEY_ACT_SET)
-                       dst_release(&params->tcft_enc_metadata->dst);
-
-               kfree_rcu(params, rcu);
-       }
+       tunnel_key_release_params(params);
 }
 
 static int tunnel_key_geneve_opts_dump(struct sk_buff *skb,
index 8ce2a05..e2b5cb2 100644 (file)
@@ -1277,7 +1277,6 @@ EXPORT_SYMBOL(tcf_block_cb_unregister);
 int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
                 struct tcf_result *res, bool compat_mode)
 {
-       __be16 protocol = tc_skb_protocol(skb);
 #ifdef CONFIG_NET_CLS_ACT
        const int max_reclassify_loop = 4;
        const struct tcf_proto *orig_tp = tp;
@@ -1287,6 +1286,7 @@ int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 reclassify:
 #endif
        for (; tp; tp = rcu_dereference_bh(tp->next)) {
+               __be16 protocol = tc_skb_protocol(skb);
                int err;
 
                if (tp->protocol != protocol &&
@@ -1319,7 +1319,6 @@ reset:
        }
 
        tp = first_tp;
-       protocol = tc_skb_protocol(skb);
        goto reclassify;
 #endif
 }
index dad04e7..12ca9d1 100644 (file)
@@ -1290,17 +1290,23 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
        struct cls_fl_head *head = rtnl_dereference(tp->root);
        struct cls_fl_filter *fold = *arg;
        struct cls_fl_filter *fnew;
+       struct fl_flow_mask *mask;
        struct nlattr **tb;
-       struct fl_flow_mask mask = {};
        int err;
 
        if (!tca[TCA_OPTIONS])
                return -EINVAL;
 
-       tb = kcalloc(TCA_FLOWER_MAX + 1, sizeof(struct nlattr *), GFP_KERNEL);
-       if (!tb)
+       mask = kzalloc(sizeof(struct fl_flow_mask), GFP_KERNEL);
+       if (!mask)
                return -ENOBUFS;
 
+       tb = kcalloc(TCA_FLOWER_MAX + 1, sizeof(struct nlattr *), GFP_KERNEL);
+       if (!tb) {
+               err = -ENOBUFS;
+               goto errout_mask_alloc;
+       }
+
        err = nla_parse_nested(tb, TCA_FLOWER_MAX, tca[TCA_OPTIONS],
                               fl_policy, NULL);
        if (err < 0)
@@ -1343,12 +1349,12 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
                }
        }
 
-       err = fl_set_parms(net, tp, fnew, &mask, base, tb, tca[TCA_RATE], ovr,
+       err = fl_set_parms(net, tp, fnew, mask, base, tb, tca[TCA_RATE], ovr,
                           tp->chain->tmplt_priv, extack);
        if (err)
                goto errout_idr;
 
-       err = fl_check_assign_mask(head, fnew, fold, &mask);
+       err = fl_check_assign_mask(head, fnew, fold, mask);
        if (err)
                goto errout_idr;
 
@@ -1365,7 +1371,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
        if (!tc_skip_hw(fnew->flags)) {
                err = fl_hw_replace_filter(tp, fnew, extack);
                if (err)
-                       goto errout_mask;
+                       goto errout_mask_ht;
        }
 
        if (!tc_in_hw(fnew->flags))
@@ -1392,8 +1398,13 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
        }
 
        kfree(tb);
+       kfree(mask);
        return 0;
 
+errout_mask_ht:
+       rhashtable_remove_fast(&fnew->mask->ht, &fnew->ht_node,
+                              fnew->mask->filter_ht_params);
+
 errout_mask:
        fl_mask_put(head, fnew->mask, false);
 
@@ -1405,6 +1416,8 @@ errout:
        kfree(fnew);
 errout_tb:
        kfree(tb);
+errout_mask_alloc:
+       kfree(mask);
        return err;
 }
 
index 9ccc93f..38bb882 100644 (file)
@@ -48,7 +48,7 @@ struct tcindex_data {
        u32 hash;               /* hash table size; 0 if undefined */
        u32 alloc_hash;         /* allocated size */
        u32 fall_through;       /* 0: only classify if explicit match */
-       struct rcu_head rcu;
+       struct rcu_work rwork;
 };
 
 static inline int tcindex_filter_is_set(struct tcindex_filter_result *r)
@@ -221,17 +221,11 @@ found:
        return 0;
 }
 
-static int tcindex_destroy_element(struct tcf_proto *tp,
-                                  void *arg, struct tcf_walker *walker)
-{
-       bool last;
-
-       return tcindex_delete(tp, arg, &last, NULL);
-}
-
-static void __tcindex_destroy(struct rcu_head *head)
+static void tcindex_destroy_work(struct work_struct *work)
 {
-       struct tcindex_data *p = container_of(head, struct tcindex_data, rcu);
+       struct tcindex_data *p = container_of(to_rcu_work(work),
+                                             struct tcindex_data,
+                                             rwork);
 
        kfree(p->perfect);
        kfree(p->h);
@@ -258,9 +252,11 @@ static int tcindex_filter_result_init(struct tcindex_filter_result *r)
        return tcf_exts_init(&r->exts, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
 }
 
-static void __tcindex_partial_destroy(struct rcu_head *head)
+static void tcindex_partial_destroy_work(struct work_struct *work)
 {
-       struct tcindex_data *p = container_of(head, struct tcindex_data, rcu);
+       struct tcindex_data *p = container_of(to_rcu_work(work),
+                                             struct tcindex_data,
+                                             rwork);
 
        kfree(p->perfect);
        kfree(p);
@@ -275,7 +271,7 @@ static void tcindex_free_perfect_hash(struct tcindex_data *cp)
        kfree(cp->perfect);
 }
 
-static int tcindex_alloc_perfect_hash(struct tcindex_data *cp)
+static int tcindex_alloc_perfect_hash(struct net *net, struct tcindex_data *cp)
 {
        int i, err = 0;
 
@@ -289,6 +285,9 @@ static int tcindex_alloc_perfect_hash(struct tcindex_data *cp)
                                    TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
                if (err < 0)
                        goto errout;
+#ifdef CONFIG_NET_CLS_ACT
+               cp->perfect[i].exts.net = net;
+#endif
        }
 
        return 0;
@@ -305,9 +304,9 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
                  struct nlattr *est, bool ovr, struct netlink_ext_ack *extack)
 {
        struct tcindex_filter_result new_filter_result, *old_r = r;
-       struct tcindex_filter_result cr;
        struct tcindex_data *cp = NULL, *oldp;
        struct tcindex_filter *f = NULL; /* make gcc behave */
+       struct tcf_result cr = {};
        int err, balloc = 0;
        struct tcf_exts e;
 
@@ -337,7 +336,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        if (p->perfect) {
                int i;
 
-               if (tcindex_alloc_perfect_hash(cp) < 0)
+               if (tcindex_alloc_perfect_hash(net, cp) < 0)
                        goto errout;
                for (i = 0; i < cp->hash; i++)
                        cp->perfect[i].res = p->perfect[i].res;
@@ -348,11 +347,8 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        err = tcindex_filter_result_init(&new_filter_result);
        if (err < 0)
                goto errout1;
-       err = tcindex_filter_result_init(&cr);
-       if (err < 0)
-               goto errout1;
        if (old_r)
-               cr.res = r->res;
+               cr = r->res;
 
        if (tb[TCA_TCINDEX_HASH])
                cp->hash = nla_get_u32(tb[TCA_TCINDEX_HASH]);
@@ -406,7 +402,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        err = -ENOMEM;
        if (!cp->perfect && !cp->h) {
                if (valid_perfect_hash(cp)) {
-                       if (tcindex_alloc_perfect_hash(cp) < 0)
+                       if (tcindex_alloc_perfect_hash(net, cp) < 0)
                                goto errout_alloc;
                        balloc = 1;
                } else {
@@ -443,8 +439,8 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        }
 
        if (tb[TCA_TCINDEX_CLASSID]) {
-               cr.res.classid = nla_get_u32(tb[TCA_TCINDEX_CLASSID]);
-               tcf_bind_filter(tp, &cr.res, base);
+               cr.classid = nla_get_u32(tb[TCA_TCINDEX_CLASSID]);
+               tcf_bind_filter(tp, &cr, base);
        }
 
        if (old_r && old_r != r) {
@@ -456,7 +452,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        }
 
        oldp = p;
-       r->res = cr.res;
+       r->res = cr;
        tcf_exts_change(&r->exts, &e);
 
        rcu_assign_pointer(tp->root, cp);
@@ -475,10 +471,12 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
                                ; /* nothing */
 
                rcu_assign_pointer(*fp, f);
+       } else {
+               tcf_exts_destroy(&new_filter_result.exts);
        }
 
        if (oldp)
-               call_rcu(&oldp->rcu, __tcindex_partial_destroy);
+               tcf_queue_work(&oldp->rwork, tcindex_partial_destroy_work);
        return 0;
 
 errout_alloc:
@@ -487,7 +485,6 @@ errout_alloc:
        else if (balloc == 2)
                kfree(cp->h);
 errout1:
-       tcf_exts_destroy(&cr.exts);
        tcf_exts_destroy(&new_filter_result.exts);
 errout:
        kfree(cp);
@@ -562,15 +559,34 @@ static void tcindex_destroy(struct tcf_proto *tp,
                            struct netlink_ext_ack *extack)
 {
        struct tcindex_data *p = rtnl_dereference(tp->root);
-       struct tcf_walker walker;
+       int i;
 
        pr_debug("tcindex_destroy(tp %p),p %p\n", tp, p);
-       walker.count = 0;
-       walker.skip = 0;
-       walker.fn = tcindex_destroy_element;
-       tcindex_walk(tp, &walker);
 
-       call_rcu(&p->rcu, __tcindex_destroy);
+       if (p->perfect) {
+               for (i = 0; i < p->hash; i++) {
+                       struct tcindex_filter_result *r = p->perfect + i;
+
+                       tcf_unbind_filter(tp, &r->res);
+                       if (tcf_exts_get_net(&r->exts))
+                               tcf_queue_work(&r->rwork,
+                                              tcindex_destroy_rexts_work);
+                       else
+                               __tcindex_destroy_rexts(r);
+               }
+       }
+
+       for (i = 0; p->h && i < p->hash; i++) {
+               struct tcindex_filter *f, *next;
+               bool last;
+
+               for (f = rtnl_dereference(p->h[i]); f; f = next) {
+                       next = rtnl_dereference(f->next);
+                       tcindex_delete(tp, &f->result, &last, NULL);
+               }
+       }
+
+       tcf_queue_work(&p->rwork, tcindex_destroy_work);
 }
 
 
index b910cd5..7394029 100644 (file)
@@ -1667,7 +1667,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        if (skb_is_gso(skb) && q->rate_flags & CAKE_FLAG_SPLIT_GSO) {
                struct sk_buff *segs, *nskb;
                netdev_features_t features = netif_skb_features(skb);
-               unsigned int slen = 0;
+               unsigned int slen = 0, numsegs = 0;
 
                segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
                if (IS_ERR_OR_NULL(segs))
@@ -1683,6 +1683,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                        flow_queue_add(flow, segs);
 
                        sch->q.qlen++;
+                       numsegs++;
                        slen += segs->len;
                        q->buffer_used += segs->truesize;
                        b->packets++;
@@ -1696,7 +1697,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                sch->qstats.backlog += slen;
                q->avg_window_bytes += slen;
 
-               qdisc_tree_reduce_backlog(sch, 1len);
+               qdisc_tree_reduce_backlog(sch, 1-numsegs, len-slen);
                consume_skb(skb);
        } else {
                /* not splitting */
index e689e11..c6a5029 100644 (file)
@@ -88,13 +88,14 @@ static int cbs_child_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                             struct Qdisc *child,
                             struct sk_buff **to_free)
 {
+       unsigned int len = qdisc_pkt_len(skb);
        int err;
 
        err = child->ops->enqueue(skb, child, to_free);
        if (err != NET_XMIT_SUCCESS)
                return err;
 
-       qdisc_qstats_backlog_inc(sch, skb);
+       sch->qstats.backlog += len;
        sch->q.qlen++;
 
        return NET_XMIT_SUCCESS;
index cdebaed..09b8009 100644 (file)
@@ -350,9 +350,11 @@ static struct drr_class *drr_classify(struct sk_buff *skb, struct Qdisc *sch,
 static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                       struct sk_buff **to_free)
 {
+       unsigned int len = qdisc_pkt_len(skb);
        struct drr_sched *q = qdisc_priv(sch);
        struct drr_class *cl;
        int err = 0;
+       bool first;
 
        cl = drr_classify(skb, sch, &err);
        if (cl == NULL) {
@@ -362,6 +364,7 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                return err;
        }
 
+       first = !cl->qdisc->q.qlen;
        err = qdisc_enqueue(skb, cl->qdisc, to_free);
        if (unlikely(err != NET_XMIT_SUCCESS)) {
                if (net_xmit_drop_count(err)) {
@@ -371,12 +374,12 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                return err;
        }
 
-       if (cl->qdisc->q.qlen == 1) {
+       if (first) {
                list_add_tail(&cl->alist, &q->active);
                cl->deficit = cl->quantum;
        }
 
-       qdisc_qstats_backlog_inc(sch, skb);
+       sch->qstats.backlog += len;
        sch->q.qlen++;
        return err;
 }
index f6f4807..4247146 100644 (file)
@@ -199,6 +199,7 @@ static struct tcf_block *dsmark_tcf_block(struct Qdisc *sch, unsigned long cl,
 static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                          struct sk_buff **to_free)
 {
+       unsigned int len = qdisc_pkt_len(skb);
        struct dsmark_qdisc_data *p = qdisc_priv(sch);
        int err;
 
@@ -271,7 +272,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                return err;
        }
 
-       qdisc_qstats_backlog_inc(sch, skb);
+       sch->qstats.backlog += len;
        sch->q.qlen++;
 
        return NET_XMIT_SUCCESS;
index 66ba2ce..968a85f 100644 (file)
@@ -500,7 +500,7 @@ static void dev_watchdog_down(struct net_device *dev)
  *     netif_carrier_on - set carrier
  *     @dev: network device
  *
- * Device has detected that carrier.
+ * Device has detected acquisition of carrier.
  */
 void netif_carrier_on(struct net_device *dev)
 {
index b18ec1f..24cc220 100644 (file)
@@ -1539,8 +1539,10 @@ hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb)
 static int
 hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
 {
+       unsigned int len = qdisc_pkt_len(skb);
        struct hfsc_class *cl;
        int uninitialized_var(err);
+       bool first;
 
        cl = hfsc_classify(skb, sch, &err);
        if (cl == NULL) {
@@ -1550,6 +1552,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
                return err;
        }
 
+       first = !cl->qdisc->q.qlen;
        err = qdisc_enqueue(skb, cl->qdisc, to_free);
        if (unlikely(err != NET_XMIT_SUCCESS)) {
                if (net_xmit_drop_count(err)) {
@@ -1559,9 +1562,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
                return err;
        }
 
-       if (cl->qdisc->q.qlen == 1) {
-               unsigned int len = qdisc_pkt_len(skb);
-
+       if (first) {
                if (cl->cl_flags & HFSC_RSC)
                        init_ed(cl, len);
                if (cl->cl_flags & HFSC_FSC)
@@ -1576,7 +1577,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
 
        }
 
-       qdisc_qstats_backlog_inc(sch, skb);
+       sch->qstats.backlog += len;
        sch->q.qlen++;
 
        return NET_XMIT_SUCCESS;
index 58b4494..30f9da7 100644 (file)
@@ -581,6 +581,7 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                       struct sk_buff **to_free)
 {
        int uninitialized_var(ret);
+       unsigned int len = qdisc_pkt_len(skb);
        struct htb_sched *q = qdisc_priv(sch);
        struct htb_class *cl = htb_classify(skb, sch, &ret);
 
@@ -610,7 +611,7 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                htb_activate(q, cl);
        }
 
-       qdisc_qstats_backlog_inc(sch, skb);
+       sch->qstats.backlog += len;
        sch->q.qlen++;
        return NET_XMIT_SUCCESS;
 }
index cdf6870..847141c 100644 (file)
@@ -72,6 +72,7 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
 static int
 prio_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
 {
+       unsigned int len = qdisc_pkt_len(skb);
        struct Qdisc *qdisc;
        int ret;
 
@@ -88,7 +89,7 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
 
        ret = qdisc_enqueue(skb, qdisc, to_free);
        if (ret == NET_XMIT_SUCCESS) {
-               qdisc_qstats_backlog_inc(sch, skb);
+               sch->qstats.backlog += len;
                sch->q.qlen++;
                return NET_XMIT_SUCCESS;
        }
index dc37c4e..29f5c4a 100644 (file)
@@ -1210,10 +1210,12 @@ static struct qfq_aggregate *qfq_choose_next_agg(struct qfq_sched *q)
 static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                       struct sk_buff **to_free)
 {
+       unsigned int len = qdisc_pkt_len(skb), gso_segs;
        struct qfq_sched *q = qdisc_priv(sch);
        struct qfq_class *cl;
        struct qfq_aggregate *agg;
        int err = 0;
+       bool first;
 
        cl = qfq_classify(skb, sch, &err);
        if (cl == NULL) {
@@ -1224,17 +1226,18 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        }
        pr_debug("qfq_enqueue: cl = %x\n", cl->common.classid);
 
-       if (unlikely(cl->agg->lmax < qdisc_pkt_len(skb))) {
+       if (unlikely(cl->agg->lmax < len)) {
                pr_debug("qfq: increasing maxpkt from %u to %u for class %u",
-                        cl->agg->lmax, qdisc_pkt_len(skb), cl->common.classid);
-               err = qfq_change_agg(sch, cl, cl->agg->class_weight,
-                                    qdisc_pkt_len(skb));
+                        cl->agg->lmax, len, cl->common.classid);
+               err = qfq_change_agg(sch, cl, cl->agg->class_weight, len);
                if (err) {
                        cl->qstats.drops++;
                        return qdisc_drop(skb, sch, to_free);
                }
        }
 
+       gso_segs = skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 1;
+       first = !cl->qdisc->q.qlen;
        err = qdisc_enqueue(skb, cl->qdisc, to_free);
        if (unlikely(err != NET_XMIT_SUCCESS)) {
                pr_debug("qfq_enqueue: enqueue failed %d\n", err);
@@ -1245,16 +1248,17 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                return err;
        }
 
-       bstats_update(&cl->bstats, skb);
-       qdisc_qstats_backlog_inc(sch, skb);
+       cl->bstats.bytes += len;
+       cl->bstats.packets += gso_segs;
+       sch->qstats.backlog += len;
        ++sch->q.qlen;
 
        agg = cl->agg;
        /* if the queue was not empty, then done here */
-       if (cl->qdisc->q.qlen != 1) {
+       if (!first) {
                if (unlikely(skb == cl->qdisc->ops->peek(cl->qdisc)) &&
                    list_first_entry(&agg->active, struct qfq_class, alist)
-                   == cl && cl->deficit < qdisc_pkt_len(skb))
+                   == cl && cl->deficit < len)
                        list_move_tail(&cl->alist, &agg->active);
 
                return err;
index 942dcca..7f272a9 100644 (file)
@@ -185,6 +185,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                       struct sk_buff **to_free)
 {
        struct tbf_sched_data *q = qdisc_priv(sch);
+       unsigned int len = qdisc_pkt_len(skb);
        int ret;
 
        if (qdisc_pkt_len(skb) > q->max_size) {
@@ -200,7 +201,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                return ret;
        }
 
-       qdisc_qstats_backlog_inc(sch, skb);
+       sch->qstats.backlog += len;
        sch->q.qlen++;
        return NET_XMIT_SUCCESS;
 }
index 078f01a..435847d 100644 (file)
@@ -256,6 +256,7 @@ static size_t inet_assoc_attr_size(struct sctp_association *asoc)
                + nla_total_size(1) /* INET_DIAG_TOS */
                + nla_total_size(1) /* INET_DIAG_TCLASS */
                + nla_total_size(4) /* INET_DIAG_MARK */
+               + nla_total_size(4) /* INET_DIAG_CLASS_ID */
                + nla_total_size(addrlen * asoc->peer.transport_count)
                + nla_total_size(addrlen * addrcnt)
                + nla_total_size(sizeof(struct inet_diag_meminfo))
index b9ed271..6200cd2 100644 (file)
@@ -97,11 +97,9 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
 
        switch (ev) {
        case NETDEV_UP:
-               addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
+               addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
                if (addr) {
                        addr->a.v6.sin6_family = AF_INET6;
-                       addr->a.v6.sin6_port = 0;
-                       addr->a.v6.sin6_flowinfo = 0;
                        addr->a.v6.sin6_addr = ifa->addr;
                        addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex;
                        addr->valid = 1;
@@ -282,7 +280,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
 
        if (saddr) {
                fl6->saddr = saddr->v6.sin6_addr;
-               fl6->fl6_sport = saddr->v6.sin6_port;
+               if (!fl6->fl6_sport)
+                       fl6->fl6_sport = saddr->v6.sin6_port;
 
                pr_debug("src=%pI6 - ", &fl6->saddr);
        }
@@ -434,7 +433,6 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
                addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
                if (addr) {
                        addr->a.v6.sin6_family = AF_INET6;
-                       addr->a.v6.sin6_port = 0;
                        addr->a.v6.sin6_addr = ifp->addr;
                        addr->a.v6.sin6_scope_id = dev->ifindex;
                        addr->valid = 1;
index 123e9f2..edfcf16 100644 (file)
@@ -36,6 +36,7 @@ static __le32 sctp_gso_make_checksum(struct sk_buff *skb)
 {
        skb->ip_summed = CHECKSUM_NONE;
        skb->csum_not_inet = 0;
+       gso_reset_checksum(skb, ~0);
        return sctp_compute_cksum(skb, skb_transport_offset(skb));
 }
 
index d5878ae..6abc8b2 100644 (file)
@@ -101,7 +101,6 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
                addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
                if (addr) {
                        addr->a.v4.sin_family = AF_INET;
-                       addr->a.v4.sin_port = 0;
                        addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
                        addr->valid = 1;
                        INIT_LIST_HEAD(&addr->list);
@@ -441,7 +440,8 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
        }
        if (saddr) {
                fl4->saddr = saddr->v4.sin_addr.s_addr;
-               fl4->fl4_sport = saddr->v4.sin_port;
+               if (!fl4->fl4_sport)
+                       fl4->fl4_sport = saddr->v4.sin_port;
        }
 
        pr_debug("%s: dst:%pI4, src:%pI4 - ", __func__, &fl4->daddr,
@@ -776,10 +776,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
 
        switch (ev) {
        case NETDEV_UP:
-               addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
+               addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
                if (addr) {
                        addr->a.v4.sin_family = AF_INET;
-                       addr->a.v4.sin_port = 0;
                        addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
                        addr->valid = 1;
                        spin_lock_bh(&net->sctp.local_addr_lock);
index f4ac6c5..d05c576 100644 (file)
@@ -495,7 +495,10 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
         *
         * [INIT ACK back to where the INIT came from.]
         */
-       retval->transport = chunk->transport;
+       if (chunk->transport)
+               retval->transport =
+                       sctp_assoc_lookup_paddr(asoc,
+                                               &chunk->transport->ipaddr);
 
        retval->subh.init_hdr =
                sctp_addto_chunk(retval, sizeof(initack), &initack);
@@ -642,8 +645,10 @@ struct sctp_chunk *sctp_make_cookie_ack(const struct sctp_association *asoc,
         *
         * [COOKIE ACK back to where the COOKIE ECHO came from.]
         */
-       if (retval && chunk)
-               retval->transport = chunk->transport;
+       if (retval && chunk && chunk->transport)
+               retval->transport =
+                       sctp_assoc_lookup_paddr(asoc,
+                                               &chunk->transport->ipaddr);
 
        return retval;
 }
index f93c3cf..65d6d04 100644 (file)
@@ -2027,7 +2027,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
        struct sctp_endpoint *ep = sctp_sk(sk)->ep;
        struct sctp_transport *transport = NULL;
        struct sctp_sndrcvinfo _sinfo, *sinfo;
-       struct sctp_association *asoc;
+       struct sctp_association *asoc, *tmp;
        struct sctp_cmsgs cmsgs;
        union sctp_addr *daddr;
        bool new = false;
@@ -2053,7 +2053,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
 
        /* SCTP_SENDALL process */
        if ((sflags & SCTP_SENDALL) && sctp_style(sk, UDP)) {
-               list_for_each_entry(asoc, &ep->asocs, asocs) {
+               list_for_each_entry_safe(asoc, tmp, &ep->asocs, asocs) {
                        err = sctp_sendmsg_check_sflags(asoc, sflags, msg,
                                                        msg_len);
                        if (err == 0)
index 3892e76..2936ed1 100644 (file)
@@ -84,6 +84,19 @@ static void fa_zero(struct flex_array *fa, size_t index, size_t count)
        }
 }
 
+static size_t fa_index(struct flex_array *fa, void *elem, size_t count)
+{
+       size_t index = 0;
+
+       while (count--) {
+               if (elem == flex_array_get(fa, index))
+                       break;
+               index++;
+       }
+
+       return index;
+}
+
 /* Migrates chunks from stream queues to new stream queues if needed,
  * but not across associations. Also, removes those chunks to streams
  * higher than the new max.
@@ -131,8 +144,10 @@ static void sctp_stream_outq_migrate(struct sctp_stream *stream,
                }
        }
 
-       for (i = outcnt; i < stream->outcnt; i++)
+       for (i = outcnt; i < stream->outcnt; i++) {
                kfree(SCTP_SO(stream, i)->ext);
+               SCTP_SO(stream, i)->ext = NULL;
+       }
 }
 
 static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt,
@@ -147,6 +162,13 @@ static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt,
 
        if (stream->out) {
                fa_copy(out, stream->out, 0, min(outcnt, stream->outcnt));
+               if (stream->out_curr) {
+                       size_t index = fa_index(stream->out, stream->out_curr,
+                                               stream->outcnt);
+
+                       BUG_ON(index == stream->outcnt);
+                       stream->out_curr = flex_array_get(out, index);
+               }
                fa_free(stream->out);
        }
 
@@ -585,9 +607,9 @@ struct sctp_chunk *sctp_process_strreset_outreq(
        struct sctp_strreset_outreq *outreq = param.v;
        struct sctp_stream *stream = &asoc->stream;
        __u32 result = SCTP_STRRESET_DENIED;
-       __u16 i, nums, flags = 0;
        __be16 *str_p = NULL;
        __u32 request_seq;
+       __u16 i, nums;
 
        request_seq = ntohl(outreq->request_seq);
 
@@ -615,6 +637,15 @@ struct sctp_chunk *sctp_process_strreset_outreq(
        if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ))
                goto out;
 
+       nums = (ntohs(param.p->length) - sizeof(*outreq)) / sizeof(__u16);
+       str_p = outreq->list_of_streams;
+       for (i = 0; i < nums; i++) {
+               if (ntohs(str_p[i]) >= stream->incnt) {
+                       result = SCTP_STRRESET_ERR_WRONG_SSN;
+                       goto out;
+               }
+       }
+
        if (asoc->strreset_chunk) {
                if (!sctp_chunk_lookup_strreset_param(
                                asoc, outreq->response_seq,
@@ -637,32 +668,19 @@ struct sctp_chunk *sctp_process_strreset_outreq(
                        sctp_chunk_put(asoc->strreset_chunk);
                        asoc->strreset_chunk = NULL;
                }
-
-               flags = SCTP_STREAM_RESET_INCOMING_SSN;
        }
 
-       nums = (ntohs(param.p->length) - sizeof(*outreq)) / sizeof(__u16);
-       if (nums) {
-               str_p = outreq->list_of_streams;
-               for (i = 0; i < nums; i++) {
-                       if (ntohs(str_p[i]) >= stream->incnt) {
-                               result = SCTP_STRRESET_ERR_WRONG_SSN;
-                               goto out;
-                       }
-               }
-
+       if (nums)
                for (i = 0; i < nums; i++)
                        SCTP_SI(stream, ntohs(str_p[i]))->mid = 0;
-       } else {
+       else
                for (i = 0; i < stream->incnt; i++)
                        SCTP_SI(stream, i)->mid = 0;
-       }
 
        result = SCTP_STRRESET_PERFORMED;
 
        *evp = sctp_ulpevent_make_stream_reset_event(asoc,
-               flags | SCTP_STREAM_RESET_OUTGOING_SSN, nums, str_p,
-               GFP_ATOMIC);
+               SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC);
 
 out:
        sctp_update_strreset_result(asoc, result);
@@ -738,9 +756,6 @@ struct sctp_chunk *sctp_process_strreset_inreq(
 
        result = SCTP_STRRESET_PERFORMED;
 
-       *evp = sctp_ulpevent_make_stream_reset_event(asoc,
-               SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC);
-
 out:
        sctp_update_strreset_result(asoc, result);
 err:
@@ -873,6 +888,14 @@ struct sctp_chunk *sctp_process_strreset_addstrm_out(
        if (!(asoc->strreset_enable & SCTP_ENABLE_CHANGE_ASSOC_REQ))
                goto out;
 
+       in = ntohs(addstrm->number_of_streams);
+       incnt = stream->incnt + in;
+       if (!in || incnt > SCTP_MAX_STREAM)
+               goto out;
+
+       if (sctp_stream_alloc_in(stream, incnt, GFP_ATOMIC))
+               goto out;
+
        if (asoc->strreset_chunk) {
                if (!sctp_chunk_lookup_strreset_param(
                        asoc, 0, SCTP_PARAM_RESET_ADD_IN_STREAMS)) {
@@ -896,14 +919,6 @@ struct sctp_chunk *sctp_process_strreset_addstrm_out(
                }
        }
 
-       in = ntohs(addstrm->number_of_streams);
-       incnt = stream->incnt + in;
-       if (!in || incnt > SCTP_MAX_STREAM)
-               goto out;
-
-       if (sctp_stream_alloc_in(stream, incnt, GFP_ATOMIC))
-               goto out;
-
        stream->incnt = incnt;
 
        result = SCTP_STRRESET_PERFORMED;
@@ -973,9 +988,6 @@ struct sctp_chunk *sctp_process_strreset_addstrm_in(
 
        result = SCTP_STRRESET_PERFORMED;
 
-       *evp = sctp_ulpevent_make_stream_change_event(asoc,
-               0, 0, ntohs(addstrm->number_of_streams), GFP_ATOMIC);
-
 out:
        sctp_update_strreset_result(asoc, result);
 err:
@@ -1036,10 +1048,10 @@ struct sctp_chunk *sctp_process_strreset_resp(
                                        sout->mid_uo = 0;
                                }
                        }
-
-                       flags = SCTP_STREAM_RESET_OUTGOING_SSN;
                }
 
+               flags |= SCTP_STREAM_RESET_OUTGOING_SSN;
+
                for (i = 0; i < stream->outcnt; i++)
                        SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
 
@@ -1058,6 +1070,8 @@ struct sctp_chunk *sctp_process_strreset_resp(
                nums = (ntohs(inreq->param_hdr.length) - sizeof(*inreq)) /
                       sizeof(__u16);
 
+               flags |= SCTP_STREAM_RESET_INCOMING_SSN;
+
                *evp = sctp_ulpevent_make_stream_reset_event(asoc, flags,
                        nums, str_p, GFP_ATOMIC);
        } else if (req->type == SCTP_PARAM_RESET_TSN_REQUEST) {
index c4da4a7..b04a813 100644 (file)
@@ -146,6 +146,9 @@ static int smc_release(struct socket *sock)
                sock_set_flag(sk, SOCK_DEAD);
                sk->sk_shutdown |= SHUTDOWN_MASK;
        }
+
+       sk->sk_prot->unhash(sk);
+
        if (smc->clcsock) {
                if (smc->use_fallback && sk->sk_state == SMC_LISTEN) {
                        /* wake up clcsock accept */
@@ -170,7 +173,6 @@ static int smc_release(struct socket *sock)
                smc_conn_free(&smc->conn);
        release_sock(sk);
 
-       sk->sk_prot->unhash(sk);
        sock_put(sk); /* final sock_put */
 out:
        return rc;
@@ -1503,6 +1505,11 @@ static int smc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 
        smc = smc_sk(sk);
        lock_sock(sk);
+       if (sk->sk_state == SMC_CLOSED && (sk->sk_shutdown & RCV_SHUTDOWN)) {
+               /* socket was connected before, no more data to read */
+               rc = 0;
+               goto out;
+       }
        if ((sk->sk_state == SMC_INIT) ||
            (sk->sk_state == SMC_LISTEN) ||
            (sk->sk_state == SMC_CLOSED))
@@ -1838,7 +1845,11 @@ static ssize_t smc_splice_read(struct socket *sock, loff_t *ppos,
 
        smc = smc_sk(sk);
        lock_sock(sk);
-
+       if (sk->sk_state == SMC_CLOSED && (sk->sk_shutdown & RCV_SHUTDOWN)) {
+               /* socket was connected before, no more data to read */
+               rc = 0;
+               goto out;
+       }
        if (sk->sk_state == SMC_INIT ||
            sk->sk_state == SMC_LISTEN ||
            sk->sk_state == SMC_CLOSED)
index db83332..fb07ad8 100644 (file)
 
 /********************************** send *************************************/
 
-struct smc_cdc_tx_pend {
-       struct smc_connection   *conn;          /* socket connection */
-       union smc_host_cursor   cursor; /* tx sndbuf cursor sent */
-       union smc_host_cursor   p_cursor;       /* rx RMBE cursor produced */
-       u16                     ctrl_seq;       /* conn. tx sequence # */
-};
-
 /* handler for send/transmission completion of a CDC msg */
 static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd,
                               struct smc_link *link,
@@ -61,12 +54,14 @@ static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd,
 
 int smc_cdc_get_free_slot(struct smc_connection *conn,
                          struct smc_wr_buf **wr_buf,
+                         struct smc_rdma_wr **wr_rdma_buf,
                          struct smc_cdc_tx_pend **pend)
 {
        struct smc_link *link = &conn->lgr->lnk[SMC_SINGLE_LINK];
        int rc;
 
        rc = smc_wr_tx_get_free_slot(link, smc_cdc_tx_handler, wr_buf,
+                                    wr_rdma_buf,
                                     (struct smc_wr_tx_pend_priv **)pend);
        if (!conn->alert_token_local)
                /* abnormal termination */
@@ -96,6 +91,7 @@ int smc_cdc_msg_send(struct smc_connection *conn,
                     struct smc_wr_buf *wr_buf,
                     struct smc_cdc_tx_pend *pend)
 {
+       union smc_host_cursor cfed;
        struct smc_link *link;
        int rc;
 
@@ -105,12 +101,10 @@ int smc_cdc_msg_send(struct smc_connection *conn,
 
        conn->tx_cdc_seq++;
        conn->local_tx_ctrl.seqno = conn->tx_cdc_seq;
-       smc_host_msg_to_cdc((struct smc_cdc_msg *)wr_buf,
-                           &conn->local_tx_ctrl, conn);
+       smc_host_msg_to_cdc((struct smc_cdc_msg *)wr_buf, conn, &cfed);
        rc = smc_wr_tx_send(link, (struct smc_wr_tx_pend_priv *)pend);
        if (!rc)
-               smc_curs_copy(&conn->rx_curs_confirmed,
-                             &conn->local_tx_ctrl.cons, conn);
+               smc_curs_copy(&conn->rx_curs_confirmed, &cfed, conn);
 
        return rc;
 }
@@ -121,11 +115,14 @@ static int smcr_cdc_get_slot_and_msg_send(struct smc_connection *conn)
        struct smc_wr_buf *wr_buf;
        int rc;
 
-       rc = smc_cdc_get_free_slot(conn, &wr_buf, &pend);
+       rc = smc_cdc_get_free_slot(conn, &wr_buf, NULL, &pend);
        if (rc)
                return rc;
 
-       return smc_cdc_msg_send(conn, wr_buf, pend);
+       spin_lock_bh(&conn->send_lock);
+       rc = smc_cdc_msg_send(conn, wr_buf, pend);
+       spin_unlock_bh(&conn->send_lock);
+       return rc;
 }
 
 int smc_cdc_get_slot_and_msg_send(struct smc_connection *conn)
index b5bfe38..f1cdde9 100644 (file)
@@ -160,7 +160,9 @@ static inline void smcd_curs_copy(union smcd_cdc_cursor *tgt,
 #endif
 }
 
-/* calculate cursor difference between old and new, where old <= new */
+/* calculate cursor difference between old and new, where old <= new and
+ * difference cannot exceed size
+ */
 static inline int smc_curs_diff(unsigned int size,
                                union smc_host_cursor *old,
                                union smc_host_cursor *new)
@@ -185,28 +187,51 @@ static inline int smc_curs_comp(unsigned int size,
        return smc_curs_diff(size, old, new);
 }
 
+/* calculate cursor difference between old and new, where old <= new and
+ * difference may exceed size
+ */
+static inline int smc_curs_diff_large(unsigned int size,
+                                     union smc_host_cursor *old,
+                                     union smc_host_cursor *new)
+{
+       if (old->wrap < new->wrap)
+               return min_t(int,
+                            (size - old->count) + new->count +
+                            (new->wrap - old->wrap - 1) * size,
+                            size);
+
+       if (old->wrap > new->wrap) /* wrap has switched from 0xffff to 0x0000 */
+               return min_t(int,
+                            (size - old->count) + new->count +
+                            (new->wrap + 0xffff - old->wrap) * size,
+                            size);
+
+       return max_t(int, 0, (new->count - old->count));
+}
+
 static inline void smc_host_cursor_to_cdc(union smc_cdc_cursor *peer,
                                          union smc_host_cursor *local,
+                                         union smc_host_cursor *save,
                                          struct smc_connection *conn)
 {
-       union smc_host_cursor temp;
-
-       smc_curs_copy(&temp, local, conn);
-       peer->count = htonl(temp.count);
-       peer->wrap = htons(temp.wrap);
+       smc_curs_copy(save, local, conn);
+       peer->count = htonl(save->count);
+       peer->wrap = htons(save->wrap);
        /* peer->reserved = htons(0); must be ensured by caller */
 }
 
 static inline void smc_host_msg_to_cdc(struct smc_cdc_msg *peer,
-                                      struct smc_host_cdc_msg *local,
-                                      struct smc_connection *conn)
+                                      struct smc_connection *conn,
+                                      union smc_host_cursor *save)
 {
+       struct smc_host_cdc_msg *local = &conn->local_tx_ctrl;
+
        peer->common.type = local->common.type;
        peer->len = local->len;
        peer->seqno = htons(local->seqno);
        peer->token = htonl(local->token);
-       smc_host_cursor_to_cdc(&peer->prod, &local->prod, conn);
-       smc_host_cursor_to_cdc(&peer->cons, &local->cons, conn);
+       smc_host_cursor_to_cdc(&peer->prod, &local->prod, save, conn);
+       smc_host_cursor_to_cdc(&peer->cons, &local->cons, save, conn);
        peer->prod_flags = local->prod_flags;
        peer->conn_state_flags = local->conn_state_flags;
 }
@@ -270,10 +295,16 @@ static inline void smc_cdc_msg_to_host(struct smc_host_cdc_msg *local,
                smcr_cdc_msg_to_host(local, peer, conn);
 }
 
-struct smc_cdc_tx_pend;
+struct smc_cdc_tx_pend {
+       struct smc_connection   *conn;          /* socket connection */
+       union smc_host_cursor   cursor;         /* tx sndbuf cursor sent */
+       union smc_host_cursor   p_cursor;       /* rx RMBE cursor produced */
+       u16                     ctrl_seq;       /* conn. tx sequence # */
+};
 
 int smc_cdc_get_free_slot(struct smc_connection *conn,
                          struct smc_wr_buf **wr_buf,
+                         struct smc_rdma_wr **wr_rdma_buf,
                          struct smc_cdc_tx_pend **pend);
 void smc_cdc_tx_dismiss_slots(struct smc_connection *conn);
 int smc_cdc_msg_send(struct smc_connection *conn, struct smc_wr_buf *wr_buf,
index 776e9df..d53fd58 100644 (file)
@@ -378,7 +378,7 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info)
        vec.iov_len = sizeof(struct smc_clc_msg_decline);
        len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1,
                             sizeof(struct smc_clc_msg_decline));
-       if (len < sizeof(struct smc_clc_msg_decline))
+       if (len < 0 || len < sizeof(struct smc_clc_msg_decline))
                len = -EPROTO;
        return len > 0 ? 0 : len;
 }
index ea2b87f..e39cadd 100644 (file)
@@ -345,14 +345,7 @@ static void smc_close_passive_work(struct work_struct *work)
 
        switch (sk->sk_state) {
        case SMC_INIT:
-               if (atomic_read(&conn->bytes_to_rcv) ||
-                   (rxflags->peer_done_writing &&
-                    !smc_cdc_rxed_any_close(conn))) {
-                       sk->sk_state = SMC_APPCLOSEWAIT1;
-               } else {
-                       sk->sk_state = SMC_CLOSED;
-                       sock_put(sk); /* passive closing */
-               }
+               sk->sk_state = SMC_APPCLOSEWAIT1;
                break;
        case SMC_ACTIVE:
                sk->sk_state = SMC_APPCLOSEWAIT1;
index 35c1cdc..aa1c551 100644 (file)
@@ -128,6 +128,8 @@ static void smc_lgr_unregister_conn(struct smc_connection *conn)
 {
        struct smc_link_group *lgr = conn->lgr;
 
+       if (!lgr)
+               return;
        write_lock_bh(&lgr->conns_lock);
        if (conn->alert_token_local) {
                __smc_lgr_unregister_conn(conn);
@@ -300,13 +302,13 @@ static void smc_buf_unuse(struct smc_connection *conn,
                conn->sndbuf_desc->used = 0;
        if (conn->rmb_desc) {
                if (!conn->rmb_desc->regerr) {
-                       conn->rmb_desc->used = 0;
                        if (!lgr->is_smcd) {
                                /* unregister rmb with peer */
                                smc_llc_do_delete_rkey(
                                                &lgr->lnk[SMC_SINGLE_LINK],
                                                conn->rmb_desc);
                        }
+                       conn->rmb_desc->used = 0;
                } else {
                        /* buf registration failed, reuse not possible */
                        write_lock_bh(&lgr->rmbs_lock);
@@ -628,6 +630,8 @@ int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
                        local_contact = SMC_REUSE_CONTACT;
                        conn->lgr = lgr;
                        smc_lgr_register_conn(conn); /* add smc conn to lgr */
+                       if (delayed_work_pending(&lgr->free_work))
+                               cancel_delayed_work(&lgr->free_work);
                        write_unlock_bh(&lgr->conns_lock);
                        break;
                }
index b002879..8806d2a 100644 (file)
@@ -52,6 +52,24 @@ enum smc_wr_reg_state {
        FAILED          /* ib_wr_reg_mr response: failure */
 };
 
+struct smc_rdma_sge {                          /* sges for RDMA writes */
+       struct ib_sge           wr_tx_rdma_sge[SMC_IB_MAX_SEND_SGE];
+};
+
+#define SMC_MAX_RDMA_WRITES    2               /* max. # of RDMA writes per
+                                                * message send
+                                                */
+
+struct smc_rdma_sges {                         /* sges per message send */
+       struct smc_rdma_sge     tx_rdma_sge[SMC_MAX_RDMA_WRITES];
+};
+
+struct smc_rdma_wr {                           /* work requests per message
+                                                * send
+                                                */
+       struct ib_rdma_wr       wr_tx_rdma[SMC_MAX_RDMA_WRITES];
+};
+
 struct smc_link {
        struct smc_ib_device    *smcibdev;      /* ib-device */
        u8                      ibport;         /* port - values 1 | 2 */
@@ -64,6 +82,8 @@ struct smc_link {
        struct smc_wr_buf       *wr_tx_bufs;    /* WR send payload buffers */
        struct ib_send_wr       *wr_tx_ibs;     /* WR send meta data */
        struct ib_sge           *wr_tx_sges;    /* WR send gather meta data */
+       struct smc_rdma_sges    *wr_tx_rdma_sges;/*RDMA WRITE gather meta data*/
+       struct smc_rdma_wr      *wr_tx_rdmas;   /* WR RDMA WRITE */
        struct smc_wr_tx_pend   *wr_tx_pends;   /* WR send waiting for CQE */
        /* above four vectors have wr_tx_cnt elements and use the same index */
        dma_addr_t              wr_tx_dma_addr; /* DMA address of wr_tx_bufs */
index e519ef2..76487a1 100644 (file)
@@ -289,8 +289,8 @@ int smc_ib_create_protection_domain(struct smc_link *lnk)
 
 static void smc_ib_qp_event_handler(struct ib_event *ibevent, void *priv)
 {
-       struct smc_ib_device *smcibdev =
-               (struct smc_ib_device *)ibevent->device;
+       struct smc_link *lnk = (struct smc_link *)priv;
+       struct smc_ib_device *smcibdev = lnk->smcibdev;
        u8 port_idx;
 
        switch (ibevent->event) {
@@ -298,7 +298,7 @@ static void smc_ib_qp_event_handler(struct ib_event *ibevent, void *priv)
        case IB_EVENT_GID_CHANGE:
        case IB_EVENT_PORT_ERR:
        case IB_EVENT_QP_ACCESS_ERR:
-               port_idx = ibevent->element.port_num - 1;
+               port_idx = ibevent->element.qp->port - 1;
                set_bit(port_idx, &smcibdev->port_event_mask);
                schedule_work(&smcibdev->port_event_work);
                break;
index a6d3623..4fd60c5 100644 (file)
@@ -166,7 +166,8 @@ static int smc_llc_add_pending_send(struct smc_link *link,
 {
        int rc;
 
-       rc = smc_wr_tx_get_free_slot(link, smc_llc_tx_handler, wr_buf, pend);
+       rc = smc_wr_tx_get_free_slot(link, smc_llc_tx_handler, wr_buf, NULL,
+                                    pend);
        if (rc < 0)
                return rc;
        BUILD_BUG_ON_MSG(
index 7cb3e4f..632c310 100644 (file)
@@ -27,7 +27,7 @@
 static struct nla_policy smc_pnet_policy[SMC_PNETID_MAX + 1] = {
        [SMC_PNETID_NAME] = {
                .type = NLA_NUL_STRING,
-               .len = SMC_MAX_PNETID_LEN - 1
+               .len = SMC_MAX_PNETID_LEN
        },
        [SMC_PNETID_ETHNAME] = {
                .type = NLA_NUL_STRING,
index d8366ed..f93f358 100644 (file)
@@ -165,12 +165,11 @@ int smc_tx_sendmsg(struct smc_sock *smc, struct msghdr *msg, size_t len)
                        conn->local_tx_ctrl.prod_flags.urg_data_pending = 1;
 
                if (!atomic_read(&conn->sndbuf_space) || conn->urg_tx_pend) {
+                       if (send_done)
+                               return send_done;
                        rc = smc_tx_wait(smc, msg->msg_flags);
-                       if (rc) {
-                               if (send_done)
-                                       return send_done;
+                       if (rc)
                                goto out_err;
-                       }
                        continue;
                }
 
@@ -267,27 +266,23 @@ int smcd_tx_ism_write(struct smc_connection *conn, void *data, size_t len,
 
 /* sndbuf consumer: actual data transfer of one target chunk with RDMA write */
 static int smc_tx_rdma_write(struct smc_connection *conn, int peer_rmbe_offset,
-                            int num_sges, struct ib_sge sges[])
+                            int num_sges, struct ib_rdma_wr *rdma_wr)
 {
        struct smc_link_group *lgr = conn->lgr;
-       struct ib_rdma_wr rdma_wr;
        struct smc_link *link;
        int rc;
 
-       memset(&rdma_wr, 0, sizeof(rdma_wr));
        link = &lgr->lnk[SMC_SINGLE_LINK];
-       rdma_wr.wr.wr_id = smc_wr_tx_get_next_wr_id(link);
-       rdma_wr.wr.sg_list = sges;
-       rdma_wr.wr.num_sge = num_sges;
-       rdma_wr.wr.opcode = IB_WR_RDMA_WRITE;
-       rdma_wr.remote_addr =
+       rdma_wr->wr.wr_id = smc_wr_tx_get_next_wr_id(link);
+       rdma_wr->wr.num_sge = num_sges;
+       rdma_wr->remote_addr =
                lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].dma_addr +
                /* RMBE within RMB */
                conn->tx_off +
                /* offset within RMBE */
                peer_rmbe_offset;
-       rdma_wr.rkey = lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].rkey;
-       rc = ib_post_send(link->roce_qp, &rdma_wr.wr, NULL);
+       rdma_wr->rkey = lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].rkey;
+       rc = ib_post_send(link->roce_qp, &rdma_wr->wr, NULL);
        if (rc) {
                conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1;
                smc_lgr_terminate(lgr);
@@ -314,24 +309,25 @@ static inline void smc_tx_advance_cursors(struct smc_connection *conn,
 /* SMC-R helper for smc_tx_rdma_writes() */
 static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len,
                               size_t src_off, size_t src_len,
-                              size_t dst_off, size_t dst_len)
+                              size_t dst_off, size_t dst_len,
+                              struct smc_rdma_wr *wr_rdma_buf)
 {
        dma_addr_t dma_addr =
                sg_dma_address(conn->sndbuf_desc->sgt[SMC_SINGLE_LINK].sgl);
-       struct smc_link *link = &conn->lgr->lnk[SMC_SINGLE_LINK];
        int src_len_sum = src_len, dst_len_sum = dst_len;
-       struct ib_sge sges[SMC_IB_MAX_SEND_SGE];
        int sent_count = src_off;
        int srcchunk, dstchunk;
        int num_sges;
        int rc;
 
        for (dstchunk = 0; dstchunk < 2; dstchunk++) {
+               struct ib_sge *sge =
+                       wr_rdma_buf->wr_tx_rdma[dstchunk].wr.sg_list;
+
                num_sges = 0;
                for (srcchunk = 0; srcchunk < 2; srcchunk++) {
-                       sges[srcchunk].addr = dma_addr + src_off;
-                       sges[srcchunk].length = src_len;
-                       sges[srcchunk].lkey = link->roce_pd->local_dma_lkey;
+                       sge[srcchunk].addr = dma_addr + src_off;
+                       sge[srcchunk].length = src_len;
                        num_sges++;
 
                        src_off += src_len;
@@ -344,7 +340,8 @@ static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len,
                        src_len = dst_len - src_len; /* remainder */
                        src_len_sum += src_len;
                }
-               rc = smc_tx_rdma_write(conn, dst_off, num_sges, sges);
+               rc = smc_tx_rdma_write(conn, dst_off, num_sges,
+                                      &wr_rdma_buf->wr_tx_rdma[dstchunk]);
                if (rc)
                        return rc;
                if (dst_len_sum == len)
@@ -403,7 +400,8 @@ static int smcd_tx_rdma_writes(struct smc_connection *conn, size_t len,
 /* sndbuf consumer: prepare all necessary (src&dst) chunks of data transmit;
  * usable snd_wnd as max transmit
  */
-static int smc_tx_rdma_writes(struct smc_connection *conn)
+static int smc_tx_rdma_writes(struct smc_connection *conn,
+                             struct smc_rdma_wr *wr_rdma_buf)
 {
        size_t len, src_len, dst_off, dst_len; /* current chunk values */
        union smc_host_cursor sent, prep, prod, cons;
@@ -464,7 +462,7 @@ static int smc_tx_rdma_writes(struct smc_connection *conn)
                                         dst_off, dst_len);
        else
                rc = smcr_tx_rdma_writes(conn, len, sent.count, src_len,
-                                        dst_off, dst_len);
+                                        dst_off, dst_len, wr_rdma_buf);
        if (rc)
                return rc;
 
@@ -485,31 +483,30 @@ static int smc_tx_rdma_writes(struct smc_connection *conn)
 static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn)
 {
        struct smc_cdc_producer_flags *pflags;
+       struct smc_rdma_wr *wr_rdma_buf;
        struct smc_cdc_tx_pend *pend;
        struct smc_wr_buf *wr_buf;
        int rc;
 
-       spin_lock_bh(&conn->send_lock);
-       rc = smc_cdc_get_free_slot(conn, &wr_buf, &pend);
+       rc = smc_cdc_get_free_slot(conn, &wr_buf, &wr_rdma_buf, &pend);
        if (rc < 0) {
                if (rc == -EBUSY) {
                        struct smc_sock *smc =
                                container_of(conn, struct smc_sock, conn);
 
-                       if (smc->sk.sk_err == ECONNABORTED) {
-                               rc = sock_error(&smc->sk);
-                               goto out_unlock;
-                       }
+                       if (smc->sk.sk_err == ECONNABORTED)
+                               return sock_error(&smc->sk);
                        rc = 0;
                        if (conn->alert_token_local) /* connection healthy */
                                mod_delayed_work(system_wq, &conn->tx_work,
                                                 SMC_TX_WORK_DELAY);
                }
-               goto out_unlock;
+               return rc;
        }
 
+       spin_lock_bh(&conn->send_lock);
        if (!conn->local_tx_ctrl.prod_flags.urg_data_present) {
-               rc = smc_tx_rdma_writes(conn);
+               rc = smc_tx_rdma_writes(conn, wr_rdma_buf);
                if (rc) {
                        smc_wr_tx_put_slot(&conn->lgr->lnk[SMC_SINGLE_LINK],
                                           (struct smc_wr_tx_pend_priv *)pend);
@@ -536,7 +533,7 @@ static int smcd_tx_sndbuf_nonempty(struct smc_connection *conn)
 
        spin_lock_bh(&conn->send_lock);
        if (!pflags->urg_data_present)
-               rc = smc_tx_rdma_writes(conn);
+               rc = smc_tx_rdma_writes(conn, NULL);
        if (!rc)
                rc = smcd_cdc_msg_send(conn);
 
@@ -598,7 +595,8 @@ void smc_tx_consumer_update(struct smc_connection *conn, bool force)
        if (to_confirm > conn->rmbe_update_limit) {
                smc_curs_copy(&prod, &conn->local_rx_ctrl.prod, conn);
                sender_free = conn->rmb_desc->len -
-                             smc_curs_diff(conn->rmb_desc->len, &prod, &cfed);
+                             smc_curs_diff_large(conn->rmb_desc->len,
+                                                 &cfed, &prod);
        }
 
        if (conn->local_rx_ctrl.prod_flags.cons_curs_upd_req ||
index c269475..253aa75 100644 (file)
@@ -160,6 +160,7 @@ static inline int smc_wr_tx_get_free_slot_index(struct smc_link *link, u32 *idx)
  * @link:              Pointer to smc_link used to later send the message.
  * @handler:           Send completion handler function pointer.
  * @wr_buf:            Out value returns pointer to message buffer.
+ * @wr_rdma_buf:       Out value returns pointer to rdma work request.
  * @wr_pend_priv:      Out value returns pointer serving as handler context.
  *
  * Return: 0 on success, or -errno on error.
@@ -167,6 +168,7 @@ static inline int smc_wr_tx_get_free_slot_index(struct smc_link *link, u32 *idx)
 int smc_wr_tx_get_free_slot(struct smc_link *link,
                            smc_wr_tx_handler handler,
                            struct smc_wr_buf **wr_buf,
+                           struct smc_rdma_wr **wr_rdma_buf,
                            struct smc_wr_tx_pend_priv **wr_pend_priv)
 {
        struct smc_wr_tx_pend *wr_pend;
@@ -204,6 +206,8 @@ int smc_wr_tx_get_free_slot(struct smc_link *link,
        wr_ib = &link->wr_tx_ibs[idx];
        wr_ib->wr_id = wr_id;
        *wr_buf = &link->wr_tx_bufs[idx];
+       if (wr_rdma_buf)
+               *wr_rdma_buf = &link->wr_tx_rdmas[idx];
        *wr_pend_priv = &wr_pend->priv;
        return 0;
 }
@@ -218,10 +222,10 @@ int smc_wr_tx_put_slot(struct smc_link *link,
                u32 idx = pend->idx;
 
                /* clear the full struct smc_wr_tx_pend including .priv */
-               memset(&link->wr_tx_pends[pend->idx], 0,
-                      sizeof(link->wr_tx_pends[pend->idx]));
-               memset(&link->wr_tx_bufs[pend->idx], 0,
-                      sizeof(link->wr_tx_bufs[pend->idx]));
+               memset(&link->wr_tx_pends[idx], 0,
+                      sizeof(link->wr_tx_pends[idx]));
+               memset(&link->wr_tx_bufs[idx], 0,
+                      sizeof(link->wr_tx_bufs[idx]));
                test_and_clear_bit(idx, link->wr_tx_mask);
                return 1;
        }
@@ -465,12 +469,26 @@ static void smc_wr_init_sge(struct smc_link *lnk)
                        lnk->wr_tx_dma_addr + i * SMC_WR_BUF_SIZE;
                lnk->wr_tx_sges[i].length = SMC_WR_TX_SIZE;
                lnk->wr_tx_sges[i].lkey = lnk->roce_pd->local_dma_lkey;
+               lnk->wr_tx_rdma_sges[i].tx_rdma_sge[0].wr_tx_rdma_sge[0].lkey =
+                       lnk->roce_pd->local_dma_lkey;
+               lnk->wr_tx_rdma_sges[i].tx_rdma_sge[0].wr_tx_rdma_sge[1].lkey =
+                       lnk->roce_pd->local_dma_lkey;
+               lnk->wr_tx_rdma_sges[i].tx_rdma_sge[1].wr_tx_rdma_sge[0].lkey =
+                       lnk->roce_pd->local_dma_lkey;
+               lnk->wr_tx_rdma_sges[i].tx_rdma_sge[1].wr_tx_rdma_sge[1].lkey =
+                       lnk->roce_pd->local_dma_lkey;
                lnk->wr_tx_ibs[i].next = NULL;
                lnk->wr_tx_ibs[i].sg_list = &lnk->wr_tx_sges[i];
                lnk->wr_tx_ibs[i].num_sge = 1;
                lnk->wr_tx_ibs[i].opcode = IB_WR_SEND;
                lnk->wr_tx_ibs[i].send_flags =
                        IB_SEND_SIGNALED | IB_SEND_SOLICITED;
+               lnk->wr_tx_rdmas[i].wr_tx_rdma[0].wr.opcode = IB_WR_RDMA_WRITE;
+               lnk->wr_tx_rdmas[i].wr_tx_rdma[1].wr.opcode = IB_WR_RDMA_WRITE;
+               lnk->wr_tx_rdmas[i].wr_tx_rdma[0].wr.sg_list =
+                       lnk->wr_tx_rdma_sges[i].tx_rdma_sge[0].wr_tx_rdma_sge;
+               lnk->wr_tx_rdmas[i].wr_tx_rdma[1].wr.sg_list =
+                       lnk->wr_tx_rdma_sges[i].tx_rdma_sge[1].wr_tx_rdma_sge;
        }
        for (i = 0; i < lnk->wr_rx_cnt; i++) {
                lnk->wr_rx_sges[i].addr =
@@ -521,8 +539,12 @@ void smc_wr_free_link_mem(struct smc_link *lnk)
        lnk->wr_tx_mask = NULL;
        kfree(lnk->wr_tx_sges);
        lnk->wr_tx_sges = NULL;
+       kfree(lnk->wr_tx_rdma_sges);
+       lnk->wr_tx_rdma_sges = NULL;
        kfree(lnk->wr_rx_sges);
        lnk->wr_rx_sges = NULL;
+       kfree(lnk->wr_tx_rdmas);
+       lnk->wr_tx_rdmas = NULL;
        kfree(lnk->wr_rx_ibs);
        lnk->wr_rx_ibs = NULL;
        kfree(lnk->wr_tx_ibs);
@@ -552,10 +574,20 @@ int smc_wr_alloc_link_mem(struct smc_link *link)
                                  GFP_KERNEL);
        if (!link->wr_rx_ibs)
                goto no_mem_wr_tx_ibs;
+       link->wr_tx_rdmas = kcalloc(SMC_WR_BUF_CNT,
+                                   sizeof(link->wr_tx_rdmas[0]),
+                                   GFP_KERNEL);
+       if (!link->wr_tx_rdmas)
+               goto no_mem_wr_rx_ibs;
+       link->wr_tx_rdma_sges = kcalloc(SMC_WR_BUF_CNT,
+                                       sizeof(link->wr_tx_rdma_sges[0]),
+                                       GFP_KERNEL);
+       if (!link->wr_tx_rdma_sges)
+               goto no_mem_wr_tx_rdmas;
        link->wr_tx_sges = kcalloc(SMC_WR_BUF_CNT, sizeof(link->wr_tx_sges[0]),
                                   GFP_KERNEL);
        if (!link->wr_tx_sges)
-               goto no_mem_wr_rx_ibs;
+               goto no_mem_wr_tx_rdma_sges;
        link->wr_rx_sges = kcalloc(SMC_WR_BUF_CNT * 3,
                                   sizeof(link->wr_rx_sges[0]),
                                   GFP_KERNEL);
@@ -579,6 +611,10 @@ no_mem_wr_rx_sges:
        kfree(link->wr_rx_sges);
 no_mem_wr_tx_sges:
        kfree(link->wr_tx_sges);
+no_mem_wr_tx_rdma_sges:
+       kfree(link->wr_tx_rdma_sges);
+no_mem_wr_tx_rdmas:
+       kfree(link->wr_tx_rdmas);
 no_mem_wr_rx_ibs:
        kfree(link->wr_rx_ibs);
 no_mem_wr_tx_ibs:
index 1d85bb1..09bf32f 100644 (file)
@@ -85,6 +85,7 @@ void smc_wr_add_dev(struct smc_ib_device *smcibdev);
 
 int smc_wr_tx_get_free_slot(struct smc_link *link, smc_wr_tx_handler handler,
                            struct smc_wr_buf **wr_buf,
+                           struct smc_rdma_wr **wrs,
                            struct smc_wr_tx_pend_priv **wr_pend_priv);
 int smc_wr_tx_put_slot(struct smc_link *link,
                       struct smc_wr_tx_pend_priv *wr_pend_priv);
index e89884e..d80d87a 100644 (file)
@@ -941,8 +941,7 @@ void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
 EXPORT_SYMBOL(dlci_ioctl_set);
 
 static long sock_do_ioctl(struct net *net, struct socket *sock,
-                         unsigned int cmd, unsigned long arg,
-                         unsigned int ifreq_size)
+                         unsigned int cmd, unsigned long arg)
 {
        int err;
        void __user *argp = (void __user *)arg;
@@ -968,11 +967,11 @@ static long sock_do_ioctl(struct net *net, struct socket *sock,
        } else {
                struct ifreq ifr;
                bool need_copyout;
-               if (copy_from_user(&ifr, argp, ifreq_size))
+               if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
                        return -EFAULT;
                err = dev_ioctl(net, cmd, &ifr, &need_copyout);
                if (!err && need_copyout)
-                       if (copy_to_user(argp, &ifr, ifreq_size))
+                       if (copy_to_user(argp, &ifr, sizeof(struct ifreq)))
                                return -EFAULT;
        }
        return err;
@@ -1071,8 +1070,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
                        err = open_related_ns(&net->ns, get_net_ns);
                        break;
                default:
-                       err = sock_do_ioctl(net, sock, cmd, arg,
-                                           sizeof(struct ifreq));
+                       err = sock_do_ioctl(net, sock, cmd, arg);
                        break;
                }
        return err;
@@ -2780,8 +2778,7 @@ static int do_siocgstamp(struct net *net, struct socket *sock,
        int err;
 
        set_fs(KERNEL_DS);
-       err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv,
-                           sizeof(struct compat_ifreq));
+       err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
        set_fs(old_fs);
        if (!err)
                err = compat_put_timeval(&ktv, up);
@@ -2797,8 +2794,7 @@ static int do_siocgstampns(struct net *net, struct socket *sock,
        int err;
 
        set_fs(KERNEL_DS);
-       err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts,
-                           sizeof(struct compat_ifreq));
+       err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
        set_fs(old_fs);
        if (!err)
                err = compat_put_timespec(&kts, up);
@@ -2994,6 +2990,54 @@ static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
        return dev_ioctl(net, cmd, &ifreq, NULL);
 }
 
+static int compat_ifreq_ioctl(struct net *net, struct socket *sock,
+                             unsigned int cmd,
+                             struct compat_ifreq __user *uifr32)
+{
+       struct ifreq __user *uifr;
+       int err;
+
+       /* Handle the fact that while struct ifreq has the same *layout* on
+        * 32/64 for everything but ifreq::ifru_ifmap and ifreq::ifru_data,
+        * which are handled elsewhere, it still has different *size* due to
+        * ifreq::ifru_ifmap (which is 16 bytes on 32 bit, 24 bytes on 64-bit,
+        * resulting in struct ifreq being 32 and 40 bytes respectively).
+        * As a result, if the struct happens to be at the end of a page and
+        * the next page isn't readable/writable, we get a fault. To prevent
+        * that, copy back and forth to the full size.
+        */
+
+       uifr = compat_alloc_user_space(sizeof(*uifr));
+       if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
+               return -EFAULT;
+
+       err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
+
+       if (!err) {
+               switch (cmd) {
+               case SIOCGIFFLAGS:
+               case SIOCGIFMETRIC:
+               case SIOCGIFMTU:
+               case SIOCGIFMEM:
+               case SIOCGIFHWADDR:
+               case SIOCGIFINDEX:
+               case SIOCGIFADDR:
+               case SIOCGIFBRDADDR:
+               case SIOCGIFDSTADDR:
+               case SIOCGIFNETMASK:
+               case SIOCGIFPFLAGS:
+               case SIOCGIFTXQLEN:
+               case SIOCGMIIPHY:
+               case SIOCGMIIREG:
+               case SIOCGIFNAME:
+                       if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
+                               err = -EFAULT;
+                       break;
+               }
+       }
+       return err;
+}
+
 static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
                        struct compat_ifreq __user *uifr32)
 {
@@ -3109,8 +3153,7 @@ static int routing_ioctl(struct net *net, struct socket *sock,
        }
 
        set_fs(KERNEL_DS);
-       ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r,
-                           sizeof(struct compat_ifreq));
+       ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
        set_fs(old_fs);
 
 out:
@@ -3210,21 +3253,22 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
        case SIOCSIFTXQLEN:
        case SIOCBRADDIF:
        case SIOCBRDELIF:
+       case SIOCGIFNAME:
        case SIOCSIFNAME:
        case SIOCGMIIPHY:
        case SIOCGMIIREG:
        case SIOCSMIIREG:
-       case SIOCSARP:
-       case SIOCGARP:
-       case SIOCDARP:
-       case SIOCATMARK:
        case SIOCBONDENSLAVE:
        case SIOCBONDRELEASE:
        case SIOCBONDSETHWADDR:
        case SIOCBONDCHANGEACTIVE:
-       case SIOCGIFNAME:
-               return sock_do_ioctl(net, sock, cmd, arg,
-                                    sizeof(struct compat_ifreq));
+               return compat_ifreq_ioctl(net, sock, cmd, argp);
+
+       case SIOCSARP:
+       case SIOCGARP:
+       case SIOCDARP:
+       case SIOCATMARK:
+               return sock_do_ioctl(net, sock, cmd, arg);
        }
 
        return -ENOIOCTLCMD;
index 1ff9768..f3023bb 100644 (file)
@@ -41,6 +41,9 @@ static unsigned long number_cred_unused;
 
 static struct cred machine_cred = {
        .usage = ATOMIC_INIT(1),
+#ifdef CONFIG_DEBUG_CREDENTIALS
+       .magic = CRED_MAGIC,
+#endif
 };
 
 /*
index dc86713..1531b02 100644 (file)
@@ -1549,8 +1549,10 @@ gss_marshal(struct rpc_task *task, __be32 *p)
        cred_len = p++;
 
        spin_lock(&ctx->gc_seq_lock);
-       req->rq_seqno = ctx->gc_seq++;
+       req->rq_seqno = (ctx->gc_seq < MAXSEQ) ? ctx->gc_seq++ : MAXSEQ;
        spin_unlock(&ctx->gc_seq_lock);
+       if (req->rq_seqno == MAXSEQ)
+               goto out_expired;
 
        *p++ = htonl((u32) RPC_GSS_VERSION);
        *p++ = htonl((u32) ctx->gc_proc);
@@ -1572,14 +1574,18 @@ gss_marshal(struct rpc_task *task, __be32 *p)
        mic.data = (u8 *)(p + 1);
        maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
        if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
-               clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+               goto out_expired;
        } else if (maj_stat != 0) {
-               printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
+               pr_warn("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
+               task->tk_status = -EIO;
                goto out_put_ctx;
        }
        p = xdr_encode_opaque(p, NULL, mic.len);
        gss_put_ctx(ctx);
        return p;
+out_expired:
+       clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+       task->tk_status = -EKEYEXPIRED;
 out_put_ctx:
        gss_put_ctx(ctx);
        return NULL;
index fb66562..5071051 100644 (file)
@@ -44,7 +44,7 @@ krb5_make_rc4_seq_num(struct krb5_ctx *kctx, int direction, s32 seqnum,
                      unsigned char *cksum, unsigned char *buf)
 {
        struct crypto_sync_skcipher *cipher;
-       unsigned char plain[8];
+       unsigned char *plain;
        s32 code;
 
        dprintk("RPC:       %s:\n", __func__);
@@ -52,6 +52,10 @@ krb5_make_rc4_seq_num(struct krb5_ctx *kctx, int direction, s32 seqnum,
        if (IS_ERR(cipher))
                return PTR_ERR(cipher);
 
+       plain = kmalloc(8, GFP_NOFS);
+       if (!plain)
+               return -ENOMEM;
+
        plain[0] = (unsigned char) ((seqnum >> 24) & 0xff);
        plain[1] = (unsigned char) ((seqnum >> 16) & 0xff);
        plain[2] = (unsigned char) ((seqnum >> 8) & 0xff);
@@ -67,6 +71,7 @@ krb5_make_rc4_seq_num(struct krb5_ctx *kctx, int direction, s32 seqnum,
 
        code = krb5_encrypt(cipher, cksum, plain, buf, 8);
 out:
+       kfree(plain);
        crypto_free_sync_skcipher(cipher);
        return code;
 }
@@ -77,12 +82,17 @@ krb5_make_seq_num(struct krb5_ctx *kctx,
                u32 seqnum,
                unsigned char *cksum, unsigned char *buf)
 {
-       unsigned char plain[8];
+       unsigned char *plain;
+       s32 code;
 
        if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC)
                return krb5_make_rc4_seq_num(kctx, direction, seqnum,
                                             cksum, buf);
 
+       plain = kmalloc(8, GFP_NOFS);
+       if (!plain)
+               return -ENOMEM;
+
        plain[0] = (unsigned char) (seqnum & 0xff);
        plain[1] = (unsigned char) ((seqnum >> 8) & 0xff);
        plain[2] = (unsigned char) ((seqnum >> 16) & 0xff);
@@ -93,7 +103,9 @@ krb5_make_seq_num(struct krb5_ctx *kctx,
        plain[6] = direction;
        plain[7] = direction;
 
-       return krb5_encrypt(key, cksum, plain, buf, 8);
+       code = krb5_encrypt(key, cksum, plain, buf, 8);
+       kfree(plain);
+       return code;
 }
 
 static s32
@@ -101,7 +113,7 @@ krb5_get_rc4_seq_num(struct krb5_ctx *kctx, unsigned char *cksum,
                     unsigned char *buf, int *direction, s32 *seqnum)
 {
        struct crypto_sync_skcipher *cipher;
-       unsigned char plain[8];
+       unsigned char *plain;
        s32 code;
 
        dprintk("RPC:       %s:\n", __func__);
@@ -113,20 +125,28 @@ krb5_get_rc4_seq_num(struct krb5_ctx *kctx, unsigned char *cksum,
        if (code)
                goto out;
 
+       plain = kmalloc(8, GFP_NOFS);
+       if (!plain) {
+               code = -ENOMEM;
+               goto out;
+       }
+
        code = krb5_decrypt(cipher, cksum, buf, plain, 8);
        if (code)
-               goto out;
+               goto out_plain;
 
        if ((plain[4] != plain[5]) || (plain[4] != plain[6])
                                   || (plain[4] != plain[7])) {
                code = (s32)KG_BAD_SEQ;
-               goto out;
+               goto out_plain;
        }
 
        *direction = plain[4];
 
        *seqnum = ((plain[0] << 24) | (plain[1] << 16) |
                                        (plain[2] << 8) | (plain[3]));
+out_plain:
+       kfree(plain);
 out:
        crypto_free_sync_skcipher(cipher);
        return code;
@@ -139,7 +159,7 @@ krb5_get_seq_num(struct krb5_ctx *kctx,
               int *direction, u32 *seqnum)
 {
        s32 code;
-       unsigned char plain[8];
+       unsigned char *plain;
        struct crypto_sync_skcipher *key = kctx->seq;
 
        dprintk("RPC:       krb5_get_seq_num:\n");
@@ -147,18 +167,25 @@ krb5_get_seq_num(struct krb5_ctx *kctx,
        if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC)
                return krb5_get_rc4_seq_num(kctx, cksum, buf,
                                            direction, seqnum);
+       plain = kmalloc(8, GFP_NOFS);
+       if (!plain)
+               return -ENOMEM;
 
        if ((code = krb5_decrypt(key, cksum, buf, plain, 8)))
-               return code;
+               goto out;
 
        if ((plain[4] != plain[5]) || (plain[4] != plain[6]) ||
-           (plain[4] != plain[7]))
-               return (s32)KG_BAD_SEQ;
+           (plain[4] != plain[7])) {
+               code = (s32)KG_BAD_SEQ;
+               goto out;
+       }
 
        *direction = plain[4];
 
        *seqnum = ((plain[0]) |
                   (plain[1] << 8) | (plain[2] << 16) | (plain[3] << 24));
 
-       return 0;
+out:
+       kfree(plain);
+       return code;
 }
index 71d9599..d7ec613 100644 (file)
@@ -1739,14 +1739,10 @@ rpc_xdr_encode(struct rpc_task *task)
        xdr_buf_init(&req->rq_rcv_buf,
                     req->rq_rbuffer,
                     req->rq_rcvsize);
-       req->rq_bytes_sent = 0;
 
        p = rpc_encode_header(task);
-       if (p == NULL) {
-               printk(KERN_INFO "RPC: couldn't encode RPC header, exit EIO\n");
-               rpc_exit(task, -EIO);
+       if (p == NULL)
                return;
-       }
 
        encode = task->tk_msg.rpc_proc->p_encode;
        if (encode == NULL)
@@ -1771,10 +1767,17 @@ call_encode(struct rpc_task *task)
        /* Did the encode result in an error condition? */
        if (task->tk_status != 0) {
                /* Was the error nonfatal? */
-               if (task->tk_status == -EAGAIN || task->tk_status == -ENOMEM)
+               switch (task->tk_status) {
+               case -EAGAIN:
+               case -ENOMEM:
                        rpc_delay(task, HZ >> 4);
-               else
+                       break;
+               case -EKEYEXPIRED:
+                       task->tk_action = call_refresh;
+                       break;
+               default:
                        rpc_exit(task, task->tk_status);
+               }
                return;
        }
 
@@ -2336,7 +2339,8 @@ rpc_encode_header(struct rpc_task *task)
        *p++ = htonl(clnt->cl_vers);    /* program version */
        *p++ = htonl(task->tk_msg.rpc_proc->p_proc);    /* procedure */
        p = rpcauth_marshcred(task, p);
-       req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p);
+       if (p)
+               req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p);
        return p;
 }
 
index 45a0333..19bb356 100644 (file)
@@ -146,7 +146,7 @@ rpc_clnt_debugfs_register(struct rpc_clnt *clnt)
        rcu_read_lock();
        xprt = rcu_dereference(clnt->cl_xprt);
        /* no "debugfs" dentry? Don't bother with the symlink. */
-       if (!xprt->debugfs) {
+       if (IS_ERR_OR_NULL(xprt->debugfs)) {
                rcu_read_unlock();
                return;
        }
index 73547d1..f1ec211 100644 (file)
@@ -1151,6 +1151,7 @@ xprt_request_enqueue_transmit(struct rpc_task *task)
        struct rpc_xprt *xprt = req->rq_xprt;
 
        if (xprt_request_need_enqueue_transmit(task, req)) {
+               req->rq_bytes_sent = 0;
                spin_lock(&xprt->queue_lock);
                /*
                 * Requests that carry congestion control credits are added
@@ -1177,7 +1178,7 @@ xprt_request_enqueue_transmit(struct rpc_task *task)
                                INIT_LIST_HEAD(&req->rq_xmit2);
                                goto out;
                        }
-               } else {
+               } else if (!req->rq_seqno) {
                        list_for_each_entry(pos, &xprt->xmit_queue, rq_xmit) {
                                if (pos->rq_task->tk_owner != task->tk_owner)
                                        continue;
index cf51b8f..1f20011 100644 (file)
@@ -537,6 +537,99 @@ void svc_rdma_sync_reply_hdr(struct svcxprt_rdma *rdma,
                                      DMA_TO_DEVICE);
 }
 
+/* If the xdr_buf has more elements than the device can
+ * transmit in a single RDMA Send, then the reply will
+ * have to be copied into a bounce buffer.
+ */
+static bool svc_rdma_pull_up_needed(struct svcxprt_rdma *rdma,
+                                   struct xdr_buf *xdr,
+                                   __be32 *wr_lst)
+{
+       int elements;
+
+       /* xdr->head */
+       elements = 1;
+
+       /* xdr->pages */
+       if (!wr_lst) {
+               unsigned int remaining;
+               unsigned long pageoff;
+
+               pageoff = xdr->page_base & ~PAGE_MASK;
+               remaining = xdr->page_len;
+               while (remaining) {
+                       ++elements;
+                       remaining -= min_t(u32, PAGE_SIZE - pageoff,
+                                          remaining);
+                       pageoff = 0;
+               }
+       }
+
+       /* xdr->tail */
+       if (xdr->tail[0].iov_len)
+               ++elements;
+
+       /* assume 1 SGE is needed for the transport header */
+       return elements >= rdma->sc_max_send_sges;
+}
+
+/* The device is not capable of sending the reply directly.
+ * Assemble the elements of @xdr into the transport header
+ * buffer.
+ */
+static int svc_rdma_pull_up_reply_msg(struct svcxprt_rdma *rdma,
+                                     struct svc_rdma_send_ctxt *ctxt,
+                                     struct xdr_buf *xdr, __be32 *wr_lst)
+{
+       unsigned char *dst, *tailbase;
+       unsigned int taillen;
+
+       dst = ctxt->sc_xprt_buf;
+       dst += ctxt->sc_sges[0].length;
+
+       memcpy(dst, xdr->head[0].iov_base, xdr->head[0].iov_len);
+       dst += xdr->head[0].iov_len;
+
+       tailbase = xdr->tail[0].iov_base;
+       taillen = xdr->tail[0].iov_len;
+       if (wr_lst) {
+               u32 xdrpad;
+
+               xdrpad = xdr_padsize(xdr->page_len);
+               if (taillen && xdrpad) {
+                       tailbase += xdrpad;
+                       taillen -= xdrpad;
+               }
+       } else {
+               unsigned int len, remaining;
+               unsigned long pageoff;
+               struct page **ppages;
+
+               ppages = xdr->pages + (xdr->page_base >> PAGE_SHIFT);
+               pageoff = xdr->page_base & ~PAGE_MASK;
+               remaining = xdr->page_len;
+               while (remaining) {
+                       len = min_t(u32, PAGE_SIZE - pageoff, remaining);
+
+                       memcpy(dst, page_address(*ppages), len);
+                       remaining -= len;
+                       dst += len;
+                       pageoff = 0;
+               }
+       }
+
+       if (taillen)
+               memcpy(dst, tailbase, taillen);
+
+       ctxt->sc_sges[0].length += xdr->len;
+       ib_dma_sync_single_for_device(rdma->sc_pd->device,
+                                     ctxt->sc_sges[0].addr,
+                                     ctxt->sc_sges[0].length,
+                                     DMA_TO_DEVICE);
+
+       return 0;
+}
+
 /* svc_rdma_map_reply_msg - Map the buffer holding RPC message
  * @rdma: controlling transport
  * @ctxt: send_ctxt for the Send WR
@@ -559,8 +652,10 @@ int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
        u32 xdr_pad;
        int ret;
 
-       if (++ctxt->sc_cur_sge_no >= rdma->sc_max_send_sges)
-               return -EIO;
+       if (svc_rdma_pull_up_needed(rdma, xdr, wr_lst))
+               return svc_rdma_pull_up_reply_msg(rdma, ctxt, xdr, wr_lst);
+
+       ++ctxt->sc_cur_sge_no;
        ret = svc_rdma_dma_map_buf(rdma, ctxt,
                                   xdr->head[0].iov_base,
                                   xdr->head[0].iov_len);
@@ -591,8 +686,7 @@ int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
        while (remaining) {
                len = min_t(u32, PAGE_SIZE - page_off, remaining);
 
-               if (++ctxt->sc_cur_sge_no >= rdma->sc_max_send_sges)
-                       return -EIO;
+               ++ctxt->sc_cur_sge_no;
                ret = svc_rdma_dma_map_page(rdma, ctxt, *ppages++,
                                            page_off, len);
                if (ret < 0)
@@ -606,8 +700,7 @@ int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
        len = xdr->tail[0].iov_len;
 tail:
        if (len) {
-               if (++ctxt->sc_cur_sge_no >= rdma->sc_max_send_sges)
-                       return -EIO;
+               ++ctxt->sc_cur_sge_no;
                ret = svc_rdma_dma_map_buf(rdma, ctxt, base, len);
                if (ret < 0)
                        return ret;
index 924c17d..57f86c6 100644 (file)
@@ -419,12 +419,9 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
        /* Transport header, head iovec, tail iovec */
        newxprt->sc_max_send_sges = 3;
        /* Add one SGE per page list entry */
-       newxprt->sc_max_send_sges += svcrdma_max_req_size / PAGE_SIZE;
-       if (newxprt->sc_max_send_sges > dev->attrs.max_send_sge) {
-               pr_err("svcrdma: too few Send SGEs available (%d needed)\n",
-                      newxprt->sc_max_send_sges);
-               goto errout;
-       }
+       newxprt->sc_max_send_sges += (svcrdma_max_req_size / PAGE_SIZE) + 1;
+       if (newxprt->sc_max_send_sges > dev->attrs.max_send_sge)
+               newxprt->sc_max_send_sges = dev->attrs.max_send_sge;
        newxprt->sc_max_req_size = svcrdma_max_req_size;
        newxprt->sc_max_requests = svcrdma_max_requests;
        newxprt->sc_max_bc_requests = svcrdma_max_bc_requests;
index 7749a2b..21113bf 100644 (file)
@@ -527,7 +527,8 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia,
 
        sendcq = ib_alloc_cq(ia->ri_device, NULL,
                             ep->rep_attr.cap.max_send_wr + 1,
-                            1, IB_POLL_WORKQUEUE);
+                            ia->ri_device->num_comp_vectors > 1 ? 1 : 0,
+                            IB_POLL_WORKQUEUE);
        if (IS_ERR(sendcq)) {
                rc = PTR_ERR(sendcq);
                goto out1;
@@ -845,17 +846,13 @@ static int rpcrdma_sendctxs_create(struct rpcrdma_xprt *r_xprt)
        for (i = 0; i <= buf->rb_sc_last; i++) {
                sc = rpcrdma_sendctx_create(&r_xprt->rx_ia);
                if (!sc)
-                       goto out_destroy;
+                       return -ENOMEM;
 
                sc->sc_xprt = r_xprt;
                buf->rb_sc_ctxs[i] = sc;
        }
 
        return 0;
-
-out_destroy:
-       rpcrdma_sendctxs_destroy(buf);
-       return -ENOMEM;
 }
 
 /* The sendctx queue is not guaranteed to have a size that is a
@@ -1113,8 +1110,10 @@ rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
                                                WQ_MEM_RECLAIM | WQ_HIGHPRI,
                                                0,
                        r_xprt->rx_xprt.address_strings[RPC_DISPLAY_ADDR]);
-       if (!buf->rb_completion_wq)
+       if (!buf->rb_completion_wq) {
+               rc = -ENOMEM;
                goto out;
+       }
 
        return 0;
 out:
index 13559e6..7754aa3 100644 (file)
@@ -48,6 +48,7 @@
 #include <net/udp.h>
 #include <net/tcp.h>
 #include <linux/bvec.h>
+#include <linux/highmem.h>
 #include <linux/uio.h>
 
 #include <trace/events/sunrpc.h>
@@ -376,6 +377,26 @@ xs_read_discard(struct socket *sock, struct msghdr *msg, int flags,
        return sock_recvmsg(sock, msg, flags);
 }
 
+#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
+static void
+xs_flush_bvec(const struct bio_vec *bvec, size_t count, size_t seek)
+{
+       struct bvec_iter bi = {
+               .bi_size = count,
+       };
+       struct bio_vec bv;
+
+       bvec_iter_advance(bvec, &bi, seek & PAGE_MASK);
+       for_each_bvec(bv, bvec, bi, bi)
+               flush_dcache_page(bv.bv_page);
+}
+#else
+static inline void
+xs_flush_bvec(const struct bio_vec *bvec, size_t count, size_t seek)
+{
+}
+#endif
+
 static ssize_t
 xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
                struct xdr_buf *buf, size_t count, size_t seek, size_t *read)
@@ -409,6 +430,7 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
                                seek + buf->page_base);
                if (ret <= 0)
                        goto sock_err;
+               xs_flush_bvec(buf->bvec, ret, seek + buf->page_base);
                offset += ret - buf->page_base;
                if (offset == count || msg->msg_flags & (MSG_EOR|MSG_TRUNC))
                        goto out;
index 2792a3c..85ad5c0 100644 (file)
@@ -1145,7 +1145,7 @@ static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb,
        default:
                pr_warn("Dropping received illegal msg type\n");
                kfree_skb(skb);
-               return false;
+               return true;
        };
 }
 
@@ -1425,6 +1425,10 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
                l->rcv_unacked = 0;
        } else {
                /* RESET_MSG or ACTIVATE_MSG */
+               if (mtyp == ACTIVATE_MSG) {
+                       msg_set_dest_session_valid(hdr, 1);
+                       msg_set_dest_session(hdr, l->peer_session);
+               }
                msg_set_max_pkt(hdr, l->advertised_mtu);
                strcpy(data, l->if_name);
                msg_set_size(hdr, INT_H_SIZE + TIPC_MAX_IF_NAME);
@@ -1642,6 +1646,17 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
                        rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT);
                        break;
                }
+
+               /* If this endpoint was re-created while peer was ESTABLISHING
+                * it doesn't know current session number. Force re-synch.
+                */
+               if (mtyp == ACTIVATE_MSG && msg_dest_session_valid(hdr) &&
+                   l->session != msg_dest_session(hdr)) {
+                       if (less(l->session, msg_dest_session(hdr)))
+                               l->session = msg_dest_session(hdr) + 1;
+                       break;
+               }
+
                /* ACTIVATE_MSG serves as PEER_RESET if link is already down */
                if (mtyp == RESET_MSG || !link_is_up(l))
                        rc = tipc_link_fsm_evt(l, LINK_PEER_RESET_EVT);
index a092495..d7e4b8b 100644 (file)
@@ -360,6 +360,28 @@ static inline void msg_set_bcast_ack(struct tipc_msg *m, u16 n)
        msg_set_bits(m, 1, 0, 0xffff, n);
 }
 
+/* Note: reusing bits in word 1 for ACTIVATE_MSG only, to re-synch
+ * link peer session number
+ */
+static inline bool msg_dest_session_valid(struct tipc_msg *m)
+{
+       return msg_bits(m, 1, 16, 0x1);
+}
+
+static inline void msg_set_dest_session_valid(struct tipc_msg *m, bool valid)
+{
+       msg_set_bits(m, 1, 16, 0x1, valid);
+}
+
+static inline u16 msg_dest_session(struct tipc_msg *m)
+{
+       return msg_bits(m, 1, 0, 0xffff);
+}
+
+static inline void msg_set_dest_session(struct tipc_msg *m, u16 n)
+{
+       msg_set_bits(m, 1, 0, 0xffff, n);
+}
 
 /*
  * Word 2
index 40f5cae..4ad3586 100644 (file)
@@ -87,6 +87,11 @@ static int tipc_skb_tailroom(struct sk_buff *skb)
        return limit;
 }
 
+static inline int TLV_GET_DATA_LEN(struct tlv_desc *tlv)
+{
+       return TLV_GET_LEN(tlv) - TLV_SPACE(0);
+}
+
 static int tipc_add_tlv(struct sk_buff *skb, u16 type, void *data, u16 len)
 {
        struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(skb);
@@ -166,6 +171,11 @@ static struct sk_buff *tipc_get_err_tlv(char *str)
        return buf;
 }
 
+static inline bool string_is_valid(char *s, int len)
+{
+       return memchr(s, '\0', len) ? true : false;
+}
+
 static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd,
                                   struct tipc_nl_compat_msg *msg,
                                   struct sk_buff *arg)
@@ -379,6 +389,7 @@ static int tipc_nl_compat_bearer_enable(struct tipc_nl_compat_cmd_doit *cmd,
        struct nlattr *prop;
        struct nlattr *bearer;
        struct tipc_bearer_config *b;
+       int len;
 
        b = (struct tipc_bearer_config *)TLV_DATA(msg->req);
 
@@ -386,6 +397,10 @@ static int tipc_nl_compat_bearer_enable(struct tipc_nl_compat_cmd_doit *cmd,
        if (!bearer)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_BEARER_NAME);
+       if (!string_is_valid(b->name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, b->name))
                return -EMSGSIZE;
 
@@ -411,6 +426,7 @@ static int tipc_nl_compat_bearer_disable(struct tipc_nl_compat_cmd_doit *cmd,
 {
        char *name;
        struct nlattr *bearer;
+       int len;
 
        name = (char *)TLV_DATA(msg->req);
 
@@ -418,6 +434,10 @@ static int tipc_nl_compat_bearer_disable(struct tipc_nl_compat_cmd_doit *cmd,
        if (!bearer)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_BEARER_NAME);
+       if (!string_is_valid(name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, name))
                return -EMSGSIZE;
 
@@ -478,6 +498,7 @@ static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg,
        struct nlattr *prop[TIPC_NLA_PROP_MAX + 1];
        struct nlattr *stats[TIPC_NLA_STATS_MAX + 1];
        int err;
+       int len;
 
        if (!attrs[TIPC_NLA_LINK])
                return -EINVAL;
@@ -504,6 +525,11 @@ static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg,
                return err;
 
        name = (char *)TLV_DATA(msg->req);
+
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME);
+       if (!string_is_valid(name, len))
+               return -EINVAL;
+
        if (strcmp(name, nla_data(link[TIPC_NLA_LINK_NAME])) != 0)
                return 0;
 
@@ -644,6 +670,7 @@ static int tipc_nl_compat_media_set(struct sk_buff *skb,
        struct nlattr *prop;
        struct nlattr *media;
        struct tipc_link_config *lc;
+       int len;
 
        lc = (struct tipc_link_config *)TLV_DATA(msg->req);
 
@@ -651,6 +678,10 @@ static int tipc_nl_compat_media_set(struct sk_buff *skb,
        if (!media)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_MEDIA_NAME);
+       if (!string_is_valid(lc->name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_MEDIA_NAME, lc->name))
                return -EMSGSIZE;
 
@@ -671,6 +702,7 @@ static int tipc_nl_compat_bearer_set(struct sk_buff *skb,
        struct nlattr *prop;
        struct nlattr *bearer;
        struct tipc_link_config *lc;
+       int len;
 
        lc = (struct tipc_link_config *)TLV_DATA(msg->req);
 
@@ -678,6 +710,10 @@ static int tipc_nl_compat_bearer_set(struct sk_buff *skb,
        if (!bearer)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_MEDIA_NAME);
+       if (!string_is_valid(lc->name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, lc->name))
                return -EMSGSIZE;
 
@@ -726,9 +762,14 @@ static int tipc_nl_compat_link_set(struct tipc_nl_compat_cmd_doit *cmd,
        struct tipc_link_config *lc;
        struct tipc_bearer *bearer;
        struct tipc_media *media;
+       int len;
 
        lc = (struct tipc_link_config *)TLV_DATA(msg->req);
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME);
+       if (!string_is_valid(lc->name, len))
+               return -EINVAL;
+
        media = tipc_media_find(lc->name);
        if (media) {
                cmd->doit = &__tipc_nl_media_set;
@@ -750,6 +791,7 @@ static int tipc_nl_compat_link_reset_stats(struct tipc_nl_compat_cmd_doit *cmd,
 {
        char *name;
        struct nlattr *link;
+       int len;
 
        name = (char *)TLV_DATA(msg->req);
 
@@ -757,6 +799,10 @@ static int tipc_nl_compat_link_reset_stats(struct tipc_nl_compat_cmd_doit *cmd,
        if (!link)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME);
+       if (!string_is_valid(name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_LINK_NAME, name))
                return -EMSGSIZE;
 
@@ -778,6 +824,8 @@ static int tipc_nl_compat_name_table_dump_header(struct tipc_nl_compat_msg *msg)
        };
 
        ntq = (struct tipc_name_table_query *)TLV_DATA(msg->req);
+       if (TLV_GET_DATA_LEN(msg->req) < sizeof(struct tipc_name_table_query))
+               return -EINVAL;
 
        depth = ntohl(ntq->depth);
 
@@ -904,8 +952,10 @@ static int tipc_nl_compat_publ_dump(struct tipc_nl_compat_msg *msg, u32 sock)
 
        hdr = genlmsg_put(args, 0, 0, &tipc_genl_family, NLM_F_MULTI,
                          TIPC_NL_PUBL_GET);
-       if (!hdr)
+       if (!hdr) {
+               kfree_skb(args);
                return -EMSGSIZE;
+       }
 
        nest = nla_nest_start(args, TIPC_NLA_SOCK);
        if (!nest) {
@@ -1206,7 +1256,7 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info)
        }
 
        len = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN);
-       if (len && !TLV_OK(msg.req, len)) {
+       if (!len || !TLV_OK(msg.req, len)) {
                msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED);
                err = -EOPNOTSUPP;
                goto send;
index db2a6c3..2dc4919 100644 (file)
@@ -830,15 +830,16 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete)
        tipc_node_write_lock(n);
        if (!tipc_link_is_establishing(l)) {
                __tipc_node_link_down(n, &bearer_id, &xmitq, &maddr);
-               if (delete) {
-                       kfree(l);
-                       le->link = NULL;
-                       n->link_cnt--;
-               }
        } else {
                /* Defuse pending tipc_node_link_up() */
+               tipc_link_reset(l);
                tipc_link_fsm_evt(l, LINK_RESET_EVT);
        }
+       if (delete) {
+               kfree(l);
+               le->link = NULL;
+               n->link_cnt--;
+       }
        trace_tipc_node_link_down(n, true, "node link down or deleted!");
        tipc_node_write_unlock(n);
        if (delete)
index efb16f6..a457c0f 100644 (file)
@@ -398,7 +398,7 @@ static int tipc_conn_rcv_from_sock(struct tipc_conn *con)
        ret = sock_recvmsg(con->sock, &msg, MSG_DONTWAIT);
        if (ret == -EWOULDBLOCK)
                return -EWOULDBLOCK;
-       if (ret > 0) {
+       if (ret == sizeof(s)) {
                read_lock_bh(&sk->sk_callback_lock);
                ret = tipc_conn_rcv_sub(srv, con, &s);
                read_unlock_bh(&sk->sk_callback_lock);
index 11cdc8f..bf5b54b 100644 (file)
@@ -439,6 +439,8 @@ static int tls_do_encryption(struct sock *sk,
        struct scatterlist *sge = sk_msg_elem(msg_en, start);
        int rc;
 
+       memcpy(rec->iv_data, tls_ctx->tx.iv, sizeof(rec->iv_data));
+
        sge->offset += tls_ctx->tx.prepend_size;
        sge->length -= tls_ctx->tx.prepend_size;
 
@@ -448,7 +450,7 @@ static int tls_do_encryption(struct sock *sk,
        aead_request_set_ad(aead_req, TLS_AAD_SPACE_SIZE);
        aead_request_set_crypt(aead_req, rec->sg_aead_in,
                               rec->sg_aead_out,
-                              data_len, tls_ctx->tx.iv);
+                              data_len, rec->iv_data);
 
        aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG,
                                  tls_encrypt_done, sk);
@@ -1792,7 +1794,9 @@ 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);
index 5d3cce9..15eb5d3 100644 (file)
@@ -75,6 +75,9 @@ static u32 virtio_transport_get_local_cid(void)
 {
        struct virtio_vsock *vsock = virtio_vsock_get();
 
+       if (!vsock)
+               return VMADDR_CID_ANY;
+
        return vsock->guest_cid;
 }
 
@@ -584,10 +587,6 @@ static int virtio_vsock_probe(struct virtio_device *vdev)
 
        virtio_vsock_update_guest_cid(vsock);
 
-       ret = vsock_core_init(&virtio_transport.transport);
-       if (ret < 0)
-               goto out_vqs;
-
        vsock->rx_buf_nr = 0;
        vsock->rx_buf_max_nr = 0;
        atomic_set(&vsock->queued_replies, 0);
@@ -618,8 +617,6 @@ static int virtio_vsock_probe(struct virtio_device *vdev)
        mutex_unlock(&the_virtio_vsock_mutex);
        return 0;
 
-out_vqs:
-       vsock->vdev->config->del_vqs(vsock->vdev);
 out:
        kfree(vsock);
        mutex_unlock(&the_virtio_vsock_mutex);
@@ -637,6 +634,9 @@ static void virtio_vsock_remove(struct virtio_device *vdev)
        flush_work(&vsock->event_work);
        flush_work(&vsock->send_pkt_work);
 
+       /* Reset all connected sockets when the device disappear */
+       vsock_for_each_connected_socket(virtio_vsock_reset_sock);
+
        vdev->config->reset(vdev);
 
        mutex_lock(&vsock->rx_lock);
@@ -669,7 +669,6 @@ static void virtio_vsock_remove(struct virtio_device *vdev)
 
        mutex_lock(&the_virtio_vsock_mutex);
        the_virtio_vsock = NULL;
-       vsock_core_exit();
        mutex_unlock(&the_virtio_vsock_mutex);
 
        vdev->config->del_vqs(vdev);
@@ -702,14 +701,28 @@ static int __init virtio_vsock_init(void)
        virtio_vsock_workqueue = alloc_workqueue("virtio_vsock", 0, 0);
        if (!virtio_vsock_workqueue)
                return -ENOMEM;
+
        ret = register_virtio_driver(&virtio_vsock_driver);
        if (ret)
-               destroy_workqueue(virtio_vsock_workqueue);
+               goto out_wq;
+
+       ret = vsock_core_init(&virtio_transport.transport);
+       if (ret)
+               goto out_vdr;
+
+       return 0;
+
+out_vdr:
+       unregister_virtio_driver(&virtio_vsock_driver);
+out_wq:
+       destroy_workqueue(virtio_vsock_workqueue);
        return ret;
+
 }
 
 static void __exit virtio_vsock_exit(void)
 {
+       vsock_core_exit();
        unregister_virtio_driver(&virtio_vsock_driver);
        destroy_workqueue(virtio_vsock_workqueue);
 }
index c361ce7..c3d5ab0 100644 (file)
@@ -1651,6 +1651,10 @@ static void vmci_transport_cleanup(struct work_struct *work)
 
 static void vmci_transport_destruct(struct vsock_sock *vsk)
 {
+       /* transport can be NULL if we hit a failure at init() time */
+       if (!vmci_trans(vsk))
+               return;
+
        /* Ensure that the detach callback doesn't use the sk/vsk
         * we are about to destruct.
         */
index 882d97b..550ac9d 100644 (file)
@@ -41,6 +41,8 @@ int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
                cfg80211_sched_dfs_chan_update(rdev);
        }
 
+       schedule_work(&cfg80211_disconnect_work);
+
        return err;
 }
 
index 623dfe5..b36ad8e 100644 (file)
@@ -1068,6 +1068,8 @@ static void __cfg80211_unregister_wdev(struct wireless_dev *wdev, bool sync)
 
        ASSERT_RTNL();
 
+       flush_work(&wdev->pmsr_free_wk);
+
        nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE);
 
        list_del_rcu(&wdev->list);
index c5d6f34..f6b4056 100644 (file)
@@ -445,6 +445,8 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev);
 bool cfg80211_does_bw_fit_range(const struct ieee80211_freq_range *freq_range,
                                u32 center_freq_khz, u32 bw_khz);
 
+extern struct work_struct cfg80211_disconnect_work;
+
 /**
  * cfg80211_chandef_dfs_usable - checks if chandef is DFS usable
  * @wiphy: the wiphy to validate against
index 5e49492..d91a408 100644 (file)
@@ -250,7 +250,7 @@ nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
        [NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION] =
                NLA_POLICY_MAX(NLA_U8, 15),
        [NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST] =
-               NLA_POLICY_MAX(NLA_U8, 15),
+               NLA_POLICY_MAX(NLA_U8, 31),
        [NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES] = { .type = NLA_U8 },
        [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI] = { .type = NLA_FLAG },
        [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC] = { .type = NLA_FLAG },
@@ -555,7 +555,7 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        },
        [NL80211_ATTR_TIMEOUT] = NLA_POLICY_MIN(NLA_U32, 1),
        [NL80211_ATTR_PEER_MEASUREMENTS] =
-               NLA_POLICY_NESTED(NL80211_PMSR_FTM_REQ_ATTR_MAX,
+               NLA_POLICY_NESTED(NL80211_PMSR_ATTR_MAX,
                                  nl80211_pmsr_attr_policy),
 };
 
index de92867..0216ab5 100644 (file)
@@ -256,8 +256,7 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info)
                if (err)
                        goto out_err;
        } else {
-               memcpy(req->mac_addr, nla_data(info->attrs[NL80211_ATTR_MAC]),
-                      ETH_ALEN);
+               memcpy(req->mac_addr, wdev_address(wdev), ETH_ALEN);
                memset(req->mac_addr_mask, 0xff, ETH_ALEN);
        }
 
@@ -272,6 +271,7 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info)
 
        req->n_peers = count;
        req->cookie = cfg80211_assign_cookie(rdev);
+       req->nl_portid = info->snd_portid;
 
        err = rdev_start_pmsr(rdev, wdev, req);
        if (err)
@@ -530,14 +530,14 @@ free:
 }
 EXPORT_SYMBOL_GPL(cfg80211_pmsr_report);
 
-void cfg80211_pmsr_free_wk(struct work_struct *work)
+static void cfg80211_pmsr_process_abort(struct wireless_dev *wdev)
 {
-       struct wireless_dev *wdev = container_of(work, struct wireless_dev,
-                                                pmsr_free_wk);
        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
        struct cfg80211_pmsr_request *req, *tmp;
        LIST_HEAD(free_list);
 
+       lockdep_assert_held(&wdev->mtx);
+
        spin_lock_bh(&wdev->pmsr_lock);
        list_for_each_entry_safe(req, tmp, &wdev->pmsr_list, list) {
                if (req->nl_portid)
@@ -547,14 +547,22 @@ void cfg80211_pmsr_free_wk(struct work_struct *work)
        spin_unlock_bh(&wdev->pmsr_lock);
 
        list_for_each_entry_safe(req, tmp, &free_list, list) {
-               wdev_lock(wdev);
                rdev_abort_pmsr(rdev, wdev, req);
-               wdev_unlock(wdev);
 
                kfree(req);
        }
 }
 
+void cfg80211_pmsr_free_wk(struct work_struct *work)
+{
+       struct wireless_dev *wdev = container_of(work, struct wireless_dev,
+                                                pmsr_free_wk);
+
+       wdev_lock(wdev);
+       cfg80211_pmsr_process_abort(wdev);
+       wdev_unlock(wdev);
+}
+
 void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev)
 {
        struct cfg80211_pmsr_request *req;
@@ -568,8 +576,8 @@ void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev)
        spin_unlock_bh(&wdev->pmsr_lock);
 
        if (found)
-               schedule_work(&wdev->pmsr_free_wk);
-       flush_work(&wdev->pmsr_free_wk);
+               cfg80211_pmsr_process_abort(wdev);
+
        WARN_ON(!list_empty(&wdev->pmsr_list));
 }
 
index ecfb1a0..dd58b99 100644 (file)
@@ -1024,8 +1024,13 @@ static void regdb_fw_cb(const struct firmware *fw, void *context)
        }
 
        rtnl_lock();
-       if (WARN_ON(regdb && !IS_ERR(regdb))) {
-               /* just restore and free new db */
+       if (regdb && !IS_ERR(regdb)) {
+               /* negative case - a bug
+                * positive case - can happen due to race in case of multiple cb's in
+                * queue, due to usage of asynchronous callback
+                *
+                * Either case, just restore and free new db.
+                */
        } else if (set_error) {
                regdb = ERR_PTR(set_error);
        } else if (fw) {
@@ -1255,7 +1260,7 @@ static bool is_valid_rd(const struct ieee80211_regdomain *rd)
  * definitions (the "2.4 GHz band", the "5 GHz band" and the "60GHz band"),
  * however it is safe for now to assume that a frequency rule should not be
  * part of a frequency's band if the start freq or end freq are off by more
- * than 2 GHz for the 2.4 and 5 GHz bands, and by more than 10 GHz for the
+ * than 2 GHz for the 2.4 and 5 GHz bands, and by more than 20 GHz for the
  * 60 GHz band.
  * This resolution can be lowered and should be considered as we add
  * regulatory rule support for other "bands".
@@ -1270,7 +1275,7 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range,
         * with the Channel starting frequency above 45 GHz.
         */
        u32 limit = freq_khz > 45 * ONE_GHZ_IN_KHZ ?
-                       10 * ONE_GHZ_IN_KHZ : 2 * ONE_GHZ_IN_KHZ;
+                       20 * ONE_GHZ_IN_KHZ : 2 * ONE_GHZ_IN_KHZ;
        if (abs(freq_khz - freq_range->start_freq_khz) <= limit)
                return true;
        if (abs(freq_khz - freq_range->end_freq_khz) <= limit)
index f741d83..7d34cb8 100644 (file)
@@ -667,7 +667,7 @@ static void disconnect_work(struct work_struct *work)
        rtnl_unlock();
 }
 
-static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
+DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
 
 
 /*
index cd48cdd..ec30e37 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright 2017      Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018-2019 Intel Corporation
  */
 #include <linux/export.h>
 #include <linux/bitops.h>
@@ -19,6 +19,7 @@
 #include <linux/mpls.h>
 #include <linux/gcd.h>
 #include <linux/bitfield.h>
+#include <linux/nospec.h>
 #include "core.h"
 #include "rdev-ops.h"
 
@@ -715,20 +716,25 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
 {
        unsigned int dscp;
        unsigned char vlan_priority;
+       unsigned int ret;
 
        /* skb->priority values from 256->263 are magic values to
         * directly indicate a specific 802.1d priority.  This is used
         * to allow 802.1d priority to be passed directly in from VLAN
         * tags, etc.
         */
-       if (skb->priority >= 256 && skb->priority <= 263)
-               return skb->priority - 256;
+       if (skb->priority >= 256 && skb->priority <= 263) {
+               ret = skb->priority - 256;
+               goto out;
+       }
 
        if (skb_vlan_tag_present(skb)) {
                vlan_priority = (skb_vlan_tag_get(skb) & VLAN_PRIO_MASK)
                        >> VLAN_PRIO_SHIFT;
-               if (vlan_priority > 0)
-                       return vlan_priority;
+               if (vlan_priority > 0) {
+                       ret = vlan_priority;
+                       goto out;
+               }
        }
 
        switch (skb->protocol) {
@@ -747,8 +753,9 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
                if (!mpls)
                        return 0;
 
-               return (ntohl(mpls->entry) & MPLS_LS_TC_MASK)
+               ret = (ntohl(mpls->entry) & MPLS_LS_TC_MASK)
                        >> MPLS_LS_TC_SHIFT;
+               goto out;
        }
        case htons(ETH_P_80221):
                /* 802.21 is always network control traffic */
@@ -761,18 +768,24 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
                unsigned int i, tmp_dscp = dscp >> 2;
 
                for (i = 0; i < qos_map->num_des; i++) {
-                       if (tmp_dscp == qos_map->dscp_exception[i].dscp)
-                               return qos_map->dscp_exception[i].up;
+                       if (tmp_dscp == qos_map->dscp_exception[i].dscp) {
+                               ret = qos_map->dscp_exception[i].up;
+                               goto out;
+                       }
                }
 
                for (i = 0; i < 8; i++) {
                        if (tmp_dscp >= qos_map->up[i].low &&
-                           tmp_dscp <= qos_map->up[i].high)
-                               return i;
+                           tmp_dscp <= qos_map->up[i].high) {
+                               ret = i;
+                               goto out;
+                       }
                }
        }
 
-       return dscp >> 5;
+       ret = dscp >> 5;
+out:
+       return array_index_nospec(ret, IEEE80211_NUM_TIDS);
 }
 EXPORT_SYMBOL(cfg80211_classify8021d);
 
index 5121729..ec3a828 100644 (file)
@@ -352,17 +352,15 @@ static unsigned int x25_new_lci(struct x25_neigh *nb)
        unsigned int lci = 1;
        struct sock *sk;
 
-       read_lock_bh(&x25_list_lock);
-
-       while ((sk = __x25_find_socket(lci, nb)) != NULL) {
+       while ((sk = x25_find_socket(lci, nb)) != NULL) {
                sock_put(sk);
                if (++lci == 4096) {
                        lci = 0;
                        break;
                }
+               cond_resched();
        }
 
-       read_unlock_bh(&x25_list_lock);
        return lci;
 }
 
index a264cf2..d4de871 100644 (file)
@@ -41,13 +41,20 @@ void xdp_del_sk_umem(struct xdp_umem *umem, struct xdp_sock *xs)
  * not know if the device has more tx queues than rx, or the opposite.
  * This might also change during run time.
  */
-static void xdp_reg_umem_at_qid(struct net_device *dev, struct xdp_umem *umem,
-                               u16 queue_id)
+static int xdp_reg_umem_at_qid(struct net_device *dev, struct xdp_umem *umem,
+                              u16 queue_id)
 {
+       if (queue_id >= max_t(unsigned int,
+                             dev->real_num_rx_queues,
+                             dev->real_num_tx_queues))
+               return -EINVAL;
+
        if (queue_id < dev->real_num_rx_queues)
                dev->_rx[queue_id].umem = umem;
        if (queue_id < dev->real_num_tx_queues)
                dev->_tx[queue_id].umem = umem;
+
+       return 0;
 }
 
 struct xdp_umem *xdp_get_umem_from_qid(struct net_device *dev,
@@ -88,7 +95,10 @@ int xdp_umem_assign_dev(struct xdp_umem *umem, struct net_device *dev,
                goto out_rtnl_unlock;
        }
 
-       xdp_reg_umem_at_qid(dev, umem, queue_id);
+       err = xdp_reg_umem_at_qid(dev, umem, queue_id);
+       if (err)
+               goto out_rtnl_unlock;
+
        umem->dev = dev;
        umem->queue_id = queue_id;
        if (force_copy)
index 934492b..ba0a404 100644 (file)
@@ -680,16 +680,6 @@ static void xfrm_hash_resize(struct work_struct *work)
        mutex_unlock(&hash_resize_mutex);
 }
 
-static void xfrm_hash_reset_inexact_table(struct net *net)
-{
-       struct xfrm_pol_inexact_bin *b;
-
-       lockdep_assert_held(&net->xfrm.xfrm_policy_lock);
-
-       list_for_each_entry(b, &net->xfrm.inexact_bins, inexact_bins)
-               INIT_HLIST_HEAD(&b->hhead);
-}
-
 /* Make sure *pol can be inserted into fastbin.
  * Useful to check that later insert requests will be sucessful
  * (provided xfrm_policy_lock is held throughout).
@@ -833,13 +823,13 @@ static void xfrm_policy_inexact_list_reinsert(struct net *net,
                                              u16 family)
 {
        unsigned int matched_s, matched_d;
-       struct hlist_node *newpos = NULL;
        struct xfrm_policy *policy, *p;
 
        matched_s = 0;
        matched_d = 0;
 
        list_for_each_entry_reverse(policy, &net->xfrm.policy_all, walk.all) {
+               struct hlist_node *newpos = NULL;
                bool matches_s, matches_d;
 
                if (!policy->bydst_reinsert)
@@ -849,16 +839,19 @@ static void xfrm_policy_inexact_list_reinsert(struct net *net,
 
                policy->bydst_reinsert = false;
                hlist_for_each_entry(p, &n->hhead, bydst) {
-                       if (policy->priority >= p->priority)
+                       if (policy->priority > p->priority)
+                               newpos = &p->bydst;
+                       else if (policy->priority == p->priority &&
+                                policy->pos > p->pos)
                                newpos = &p->bydst;
                        else
                                break;
                }
 
                if (newpos)
-                       hlist_add_behind(&policy->bydst, newpos);
+                       hlist_add_behind_rcu(&policy->bydst, newpos);
                else
-                       hlist_add_head(&policy->bydst, &n->hhead);
+                       hlist_add_head_rcu(&policy->bydst, &n->hhead);
 
                /* paranoia checks follow.
                 * Check that the reinserted policy matches at least
@@ -893,12 +886,13 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net,
                                              struct rb_root *new,
                                              u16 family)
 {
-       struct rb_node **p, *parent = NULL;
        struct xfrm_pol_inexact_node *node;
+       struct rb_node **p, *parent;
 
        /* we should not have another subtree here */
        WARN_ON_ONCE(!RB_EMPTY_ROOT(&n->root));
-
+restart:
+       parent = NULL;
        p = &new->rb_node;
        while (*p) {
                u8 prefixlen;
@@ -918,12 +912,11 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net,
                } else {
                        struct xfrm_policy *tmp;
 
-                       hlist_for_each_entry(tmp, &node->hhead, bydst)
-                               tmp->bydst_reinsert = true;
-                       hlist_for_each_entry(tmp, &n->hhead, bydst)
+                       hlist_for_each_entry(tmp, &n->hhead, bydst) {
                                tmp->bydst_reinsert = true;
+                               hlist_del_rcu(&tmp->bydst);
+                       }
 
-                       INIT_HLIST_HEAD(&node->hhead);
                        xfrm_policy_inexact_list_reinsert(net, node, family);
 
                        if (node->prefixlen == n->prefixlen) {
@@ -935,8 +928,7 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net,
                        kfree_rcu(n, rcu);
                        n = node;
                        n->prefixlen = prefixlen;
-                       *p = new->rb_node;
-                       parent = NULL;
+                       goto restart;
                }
        }
 
@@ -965,12 +957,11 @@ static void xfrm_policy_inexact_node_merge(struct net *net,
                                                  family);
        }
 
-       hlist_for_each_entry(tmp, &v->hhead, bydst)
-               tmp->bydst_reinsert = true;
-       hlist_for_each_entry(tmp, &n->hhead, bydst)
+       hlist_for_each_entry(tmp, &v->hhead, bydst) {
                tmp->bydst_reinsert = true;
+               hlist_del_rcu(&tmp->bydst);
+       }
 
-       INIT_HLIST_HEAD(&n->hhead);
        xfrm_policy_inexact_list_reinsert(net, n, family);
 }
 
@@ -1235,6 +1226,7 @@ static void xfrm_hash_rebuild(struct work_struct *work)
        } while (read_seqretry(&net->xfrm.policy_hthresh.lock, seq));
 
        spin_lock_bh(&net->xfrm.xfrm_policy_lock);
+       write_seqcount_begin(&xfrm_policy_hash_generation);
 
        /* make sure that we can insert the indirect policies again before
         * we start with destructive action.
@@ -1278,10 +1270,14 @@ static void xfrm_hash_rebuild(struct work_struct *work)
        }
 
        /* reset the bydst and inexact table in all directions */
-       xfrm_hash_reset_inexact_table(net);
-
        for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
-               INIT_HLIST_HEAD(&net->xfrm.policy_inexact[dir]);
+               struct hlist_node *n;
+
+               hlist_for_each_entry_safe(policy, n,
+                                         &net->xfrm.policy_inexact[dir],
+                                         bydst_inexact_list)
+                       hlist_del_init(&policy->bydst_inexact_list);
+
                hmask = net->xfrm.policy_bydst[dir].hmask;
                odst = net->xfrm.policy_bydst[dir].table;
                for (i = hmask; i >= 0; i--)
@@ -1313,6 +1309,9 @@ static void xfrm_hash_rebuild(struct work_struct *work)
                newpos = NULL;
                chain = policy_hash_bysel(net, &policy->selector,
                                          policy->family, dir);
+
+               hlist_del_rcu(&policy->bydst);
+
                if (!chain) {
                        void *p = xfrm_policy_inexact_insert(policy, dir, 0);
 
@@ -1334,6 +1333,7 @@ static void xfrm_hash_rebuild(struct work_struct *work)
 
 out_unlock:
        __xfrm_policy_inexact_flush(net);
+       write_seqcount_end(&xfrm_policy_hash_generation);
        spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
 
        mutex_unlock(&hash_resize_mutex);
@@ -2600,7 +2600,10 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
                dst_copy_metrics(dst1, dst);
 
                if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
-                       __u32 mark = xfrm_smark_get(fl->flowi_mark, xfrm[i]);
+                       __u32 mark = 0;
+
+                       if (xfrm[i]->props.smark.v || xfrm[i]->props.smark.m)
+                               mark = xfrm_smark_get(fl->flowi_mark, xfrm[i]);
 
                        family = xfrm[i]->props.family;
                        dst = xfrm_dst_lookup(xfrm[i], tos, fl->flowi_oif,
index 277c1c4..c6d26af 100644 (file)
@@ -1488,10 +1488,15 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)
                if (!ut[i].family)
                        ut[i].family = family;
 
-               if ((ut[i].mode == XFRM_MODE_TRANSPORT) &&
-                   (ut[i].family != prev_family))
-                       return -EINVAL;
-
+               switch (ut[i].mode) {
+               case XFRM_MODE_TUNNEL:
+               case XFRM_MODE_BEET:
+                       break;
+               default:
+                       if (ut[i].family != prev_family)
+                               return -EINVAL;
+                       break;
+               }
                if (ut[i].mode >= XFRM_MODE_MAX)
                        return -EINVAL;
 
index 66ae15f..db1a91d 100644 (file)
@@ -279,6 +279,7 @@ $(obj)/%.o: $(src)/%.c
                -Wno-gnu-variable-sized-type-not-at-end \
                -Wno-address-of-packed-member -Wno-tautological-compare \
                -Wno-unknown-warning-option $(CLANG_ARCH_ARGS) \
+               -I$(srctree)/samples/bpf/ -include asm_goto_workaround.h \
                -O2 -emit-llvm -c $< -o -| $(LLC) -march=bpf $(LLC_FLAGS) -filetype=obj -o $@
 ifeq ($(DWARF2BTF),y)
        $(BTF_PAHOLE) -J $@
diff --git a/samples/bpf/asm_goto_workaround.h b/samples/bpf/asm_goto_workaround.h
new file mode 100644 (file)
index 0000000..5cd7c1d
--- /dev/null
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2019 Facebook */
+#ifndef __ASM_GOTO_WORKAROUND_H
+#define __ASM_GOTO_WORKAROUND_H
+
+/* this will bring in asm_volatile_goto macro definition
+ * if enabled by compiler and config options.
+ */
+#include <linux/types.h>
+
+#ifdef asm_volatile_goto
+#undef asm_volatile_goto
+#define asm_volatile_goto(x...) asm volatile("invalid use of asm_volatile_goto")
+#endif
+
+#endif
index d7b68ef..0bb6507 100644 (file)
@@ -77,7 +77,7 @@ static int test_foo_bar(void)
 
        /* Create cgroup /foo, get fd, and join it */
        foo = create_and_get_cgroup(FOO);
-       if (!foo)
+       if (foo < 0)
                goto err;
 
        if (join_cgroup(FOO))
@@ -94,7 +94,7 @@ static int test_foo_bar(void)
 
        /* Create cgroup /foo/bar, get fd, and join it */
        bar = create_and_get_cgroup(BAR);
-       if (!bar)
+       if (bar < 0)
                goto err;
 
        if (join_cgroup(BAR))
@@ -298,19 +298,19 @@ static int test_multiprog(void)
                goto err;
 
        cg1 = create_and_get_cgroup("/cg1");
-       if (!cg1)
+       if (cg1 < 0)
                goto err;
        cg2 = create_and_get_cgroup("/cg1/cg2");
-       if (!cg2)
+       if (cg2 < 0)
                goto err;
        cg3 = create_and_get_cgroup("/cg1/cg2/cg3");
-       if (!cg3)
+       if (cg3 < 0)
                goto err;
        cg4 = create_and_get_cgroup("/cg1/cg2/cg3/cg4");
-       if (!cg4)
+       if (cg4 < 0)
                goto err;
        cg5 = create_and_get_cgroup("/cg1/cg2/cg3/cg4/cg5");
-       if (!cg5)
+       if (cg5 < 0)
                goto err;
 
        if (join_cgroup("/cg1/cg2/cg3/cg4/cg5"))
index 2259f99..f082d6a 100644 (file)
@@ -32,7 +32,7 @@ int main(int argc, char **argv)
 
        cg2 = create_and_get_cgroup(CGROUP_PATH);
 
-       if (!cg2)
+       if (cg2 < 0)
                goto err;
 
        if (bpf_map_update_elem(map_fd[0], &idx, &cg2, BPF_ANY)) {
index 0a197f8..8bfda95 100644 (file)
@@ -103,7 +103,7 @@ int main(int argc, char **argv)
                return 1;
        }
 
-       ifindex = if_nametoindex(argv[1]);
+       ifindex = if_nametoindex(argv[optind]);
        if (!ifindex) {
                perror("if_nametoindex");
                return 1;
index 33e67bd..3223448 100644 (file)
@@ -117,7 +117,7 @@ static bool mei_init(struct mei *me, const uuid_le *guid,
 
        me->verbose = verbose;
 
-       me->fd = open("/dev/mei", O_RDWR);
+       me->fd = open("/dev/mei0", O_RDWR);
        if (me->fd == -1) {
                mei_err(me, "Cannot establish a handle to the Intel MEI driver\n");
                goto err;
index 4920903..fb43a81 100644 (file)
@@ -34,6 +34,7 @@ HOSTCFLAGS_bpf-direct.o += $(MFLAG)
 HOSTCFLAGS_dropper.o += $(MFLAG)
 HOSTCFLAGS_bpf-helper.o += $(MFLAG)
 HOSTCFLAGS_bpf-fancy.o += $(MFLAG)
+HOSTCFLAGS_user-trap.o += $(MFLAG)
 HOSTLDLIBS_bpf-direct += $(MFLAG)
 HOSTLDLIBS_bpf-fancy += $(MFLAG)
 HOSTLDLIBS_dropper += $(MFLAG)
index 525bff6..3081603 100644 (file)
@@ -24,10 +24,6 @@ depfile = $(subst $(comma),_,$(dot-target).d)
 basetarget = $(basename $(notdir $@))
 
 ###
-# filename of first prerequisite with directory and extension stripped
-baseprereq = $(basename $(notdir $<))
-
-###
 # Escape single quote for use in echo statements
 escsq = $(subst $(squote),'\$(squote)',$1)
 
index 408ee38..18fedf7 100644 (file)
@@ -32,7 +32,7 @@ type T;
   (T *)
   \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
    kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\|
-   dma_alloc_coherent\|dma_zalloc_coherent\|devm_kmalloc\|devm_kzalloc\|
+   dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\|
    kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\|
    pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\|
    kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...)
@@ -55,7 +55,7 @@ type r1.T;
 * (T *)
   \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
    kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\|
-   dma_alloc_coherent\|dma_zalloc_coherent\|devm_kmalloc\|devm_kzalloc\|
+   dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\|
    kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\|
    pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\|
    kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...)
@@ -78,7 +78,7 @@ type r1.T;
 - (T *)
   \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
    kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\|
-   dma_alloc_coherent\|dma_zalloc_coherent\|devm_kmalloc\|devm_kzalloc\|
+   dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\|
    kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\|
    pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\|
    kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...)
@@ -95,7 +95,7 @@ position p;
  (T@p *)
   \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
    kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\|
-   dma_alloc_coherent\|dma_zalloc_coherent\|devm_kmalloc\|devm_kzalloc\|
+   dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\|
    kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\|
    pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\|
    kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...)
index d819275..5cd1991 100644 (file)
@@ -69,15 +69,6 @@ statement S;
 - x = (T)vmalloc(E1);
 + x = (T)vzalloc(E1);
 |
-- x = dma_alloc_coherent(E2,E1,E3,E4);
-+ x = dma_zalloc_coherent(E2,E1,E3,E4);
-|
-- x = (T *)dma_alloc_coherent(E2,E1,E3,E4);
-+ x = dma_zalloc_coherent(E2,E1,E3,E4);
-|
-- x = (T)dma_alloc_coherent(E2,E1,E3,E4);
-+ x = (T)dma_zalloc_coherent(E2,E1,E3,E4);
-|
 - x = kmalloc_node(E1,E2,E3);
 + x = kzalloc_node(E1,E2,E3);
 |
@@ -225,7 +216,7 @@ p << r2.p;
 x << r2.x;
 @@
 
-msg="WARNING: dma_zalloc_coherent should be used for %s, instead of dma_alloc_coherent/memset" % (x)
+msg="WARNING: dma_alloc_coherent use in %s already zeroes out memory,  so memset is not needed" % (x)
 coccilib.report.print_report(p[0], msg)
 
 //-----------------------------------------------------------------
index de70b84..89c47f5 100644 (file)
@@ -13,7 +13,7 @@ static unsigned int arm_pertask_ssp_rtl_execute(void)
        for (insn = get_insns(); insn; insn = NEXT_INSN(insn)) {
                const char *sym;
                rtx body;
-               rtx masked_sp;
+               rtx mask, masked_sp;
 
                /*
                 * Find a SET insn involving a SYMBOL_REF to __stack_chk_guard
@@ -33,12 +33,13 @@ static unsigned int arm_pertask_ssp_rtl_execute(void)
                 * produces the address of the copy of the stack canary value
                 * stored in struct thread_info
                 */
+               mask = GEN_INT(sext_hwi(sp_mask, GET_MODE_PRECISION(Pmode)));
                masked_sp = gen_reg_rtx(Pmode);
 
                emit_insn_before(gen_rtx_SET(masked_sp,
                                             gen_rtx_AND(Pmode,
                                                         stack_pointer_rtx,
-                                                        GEN_INT(sp_mask))),
+                                                        mask)),
                                 insn);
 
                SET_SRC(body) = gen_rtx_PLUS(Pmode, masked_sp,
@@ -52,6 +53,19 @@ static unsigned int arm_pertask_ssp_rtl_execute(void)
 #define NO_GATE
 #include "gcc-generate-rtl-pass.h"
 
+#if BUILDING_GCC_VERSION >= 9000
+static bool no(void)
+{
+       return false;
+}
+
+static void arm_pertask_ssp_start_unit(void *gcc_data, void *user_data)
+{
+       targetm.have_stack_protect_combined_set = no;
+       targetm.have_stack_protect_combined_test = no;
+}
+#endif
+
 __visible int plugin_init(struct plugin_name_args *plugin_info,
                          struct plugin_gcc_version *version)
 {
@@ -99,5 +113,10 @@ __visible int plugin_init(struct plugin_name_args *plugin_info,
        register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP,
                          NULL, &arm_pertask_ssp_rtl_pass_info);
 
+#if BUILDING_GCC_VERSION >= 9000
+       register_callback(plugin_info->base_name, PLUGIN_START_UNIT,
+                         arm_pertask_ssp_start_unit, NULL);
+#endif
+
        return 0;
 }
index c05ab00..1819735 100644 (file)
@@ -206,4 +206,4 @@ filechk_conf_cfg = $(CONFIG_SHELL) $<
 $(obj)/%conf-cfg: $(src)/%conf-cfg.sh FORCE
        $(call filechk,conf_cfg)
 
-clean-files += conf-cfg
+clean-files += *conf-cfg
index 0de2fb2..26bf886 100644 (file)
@@ -2185,7 +2185,7 @@ static void add_intree_flag(struct buffer *b, int is_intree)
 /* Cannot check for assembler */
 static void add_retpoline(struct buffer *b)
 {
-       buf_printf(b, "\n#ifdef RETPOLINE\n");
+       buf_printf(b, "\n#ifdef CONFIG_RETPOLINE\n");
        buf_printf(b, "MODULE_INFO(retpoline, \"Y\");\n");
        buf_printf(b, "#endif\n");
 }
index 08c88de..11975ec 100644 (file)
@@ -1444,7 +1444,10 @@ check:
                        new = aa_label_merge(label, target, GFP_KERNEL);
                if (IS_ERR_OR_NULL(new)) {
                        info = "failed to build target label";
-                       error = PTR_ERR(new);
+                       if (!new)
+                               error = -ENOMEM;
+                       else
+                               error = PTR_ERR(new);
                        new = NULL;
                        perms.allow = 0;
                        goto audit;
index 2c01087..8db1731 100644 (file)
@@ -1599,12 +1599,14 @@ static unsigned int apparmor_ipv4_postroute(void *priv,
        return apparmor_ip_postroute(priv, skb, state);
 }
 
+#if IS_ENABLED(CONFIG_IPV6)
 static unsigned int apparmor_ipv6_postroute(void *priv,
                                            struct sk_buff *skb,
                                            const struct nf_hook_state *state)
 {
        return apparmor_ip_postroute(priv, skb, state);
 }
+#endif
 
 static const struct nf_hook_ops apparmor_nf_ops[] = {
        {
index f1b8d25..55bc490 100644 (file)
@@ -1027,6 +1027,13 @@ int security_cred_alloc_blank(struct cred *cred, gfp_t gfp)
 
 void security_cred_free(struct cred *cred)
 {
+       /*
+        * There is a failure case in prepare_creds() that
+        * may result in a call here with ->security being NULL.
+        */
+       if (unlikely(cred->security == NULL))
+               return;
+
        call_void_hook(cred_free, cred);
 }
 
index a50d625..c1c31e3 100644 (file)
@@ -732,7 +732,8 @@ static int sens_destroy(void *key, void *datum, void *p)
        kfree(key);
        if (datum) {
                levdatum = datum;
-               ebitmap_destroy(&levdatum->level->cat);
+               if (levdatum->level)
+                       ebitmap_destroy(&levdatum->level->cat);
                kfree(levdatum->level);
        }
        kfree(datum);
index ffda91a..02514fe 100644 (file)
@@ -368,7 +368,9 @@ static int yama_ptrace_access_check(struct task_struct *child,
                        break;
                case YAMA_SCOPE_RELATIONAL:
                        rcu_read_lock();
-                       if (!task_is_descendant(current, child) &&
+                       if (!pid_alive(child))
+                               rc = -EPERM;
+                       if (!rc && !task_is_descendant(current, child) &&
                            !ptracer_exception_found(current, child) &&
                            !ns_capable(__task_cred(child)->user_ns, CAP_SYS_PTRACE))
                                rc = -EPERM;
index c3f57a3..40ebde2 100644 (file)
@@ -47,8 +47,8 @@ static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
        /* We use the PCI APIs for now until the generic one gets fixed
         * enough or until we get some macio-specific versions
         */
-       r->space = dma_zalloc_coherent(&macio_get_pci_dev(i2sdev->macio)->dev,
-                                      r->size, &r->bus_addr, GFP_KERNEL);
+       r->space = dma_alloc_coherent(&macio_get_pci_dev(i2sdev->macio)->dev,
+                                     r->size, &r->bus_addr, GFP_KERNEL);
        if (!r->space)
                return -ENOMEM;
 
index a5b09e7..f7d2b37 100644 (file)
@@ -541,7 +541,8 @@ static int snd_compress_check_input(struct snd_compr_params *params)
 {
        /* first let's check the buffer parameter's */
        if (params->buffer.fragment_size == 0 ||
-           params->buffer.fragments > INT_MAX / params->buffer.fragment_size)
+           params->buffer.fragments > INT_MAX / params->buffer.fragment_size ||
+           params->buffer.fragments == 0)
                return -EINVAL;
 
        /* now codec parameters */
index 40013b2..6c0b303 100644 (file)
@@ -2177,16 +2177,11 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
                snd_pcm_update_hw_ptr(substream);
 
        if (!is_playback &&
-           runtime->status->state == SNDRV_PCM_STATE_PREPARED) {
-               if (size >= runtime->start_threshold) {
-                       err = snd_pcm_start(substream);
-                       if (err < 0)
-                               goto _end_unlock;
-               } else {
-                       /* nothing to do */
-                       err = 0;
+           runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
+           size >= runtime->start_threshold) {
+               err = snd_pcm_start(substream);
+               if (err < 0)
                        goto _end_unlock;
-               }
        }
 
        avail = snd_pcm_avail(substream);
index 598d140..5fc497c 100644 (file)
@@ -903,6 +903,9 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip)
        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
        int i;
 
+       if (!ins)
+               return 0;
+
        snd_info_free_entry(ins->proc_sym_info_entry);
        ins->proc_sym_info_entry = NULL;
 
index 9174f1b..1ec706c 100644 (file)
@@ -115,7 +115,8 @@ static int hda_codec_driver_probe(struct device *dev)
        err = snd_hda_codec_build_controls(codec);
        if (err < 0)
                goto error_module;
-       if (codec->card->registered) {
+       /* only register after the bus probe finished; otherwise it's racy */
+       if (!codec->bus->bus_probing && codec->card->registered) {
                err = snd_card_register(codec->card);
                if (err < 0)
                        goto error_module;
index e784130..e5c4900 100644 (file)
@@ -2185,6 +2185,7 @@ static int azx_probe_continue(struct azx *chip)
        int dev = chip->dev_index;
        int err;
 
+       to_hda_bus(bus)->bus_probing = 1;
        hda->probe_continued = 1;
 
        /* bind with i915 if needed */
@@ -2269,6 +2270,7 @@ out_free:
        if (err < 0)
                hda->init_failed = 1;
        complete_all(&hda->probe_wait);
+       to_hda_bus(bus)->bus_probing = 0;
        return err;
 }
 
index e5bdbc2..29882bd 100644 (file)
@@ -8451,8 +8451,10 @@ static void ca0132_free(struct hda_codec *codec)
        ca0132_exit_chip(codec);
 
        snd_hda_power_down(codec);
-       if (IS_ENABLED(CONFIG_PCI) && spec->mem_base)
+#ifdef CONFIG_PCI
+       if (spec->mem_base)
                pci_iounmap(codec->bus->pci, spec->mem_base);
+#endif
        kfree(spec->spec_init_verbs);
        kfree(codec->spec);
 }
index 51cc658..a4ee765 100644 (file)
@@ -924,6 +924,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x103c, 0x807C, "HP EliteBook 820 G3", CXT_FIXUP_HP_DOCK),
        SND_PCI_QUIRK(0x103c, 0x80FD, "HP ProBook 640 G2", CXT_FIXUP_HP_DOCK),
        SND_PCI_QUIRK(0x103c, 0x828c, "HP EliteBook 840 G4", CXT_FIXUP_HP_DOCK),
+       SND_PCI_QUIRK(0x103c, 0x83b2, "HP EliteBook 840 G5", CXT_FIXUP_HP_DOCK),
        SND_PCI_QUIRK(0x103c, 0x83b3, "HP EliteBook 830 G5", CXT_FIXUP_HP_DOCK),
        SND_PCI_QUIRK(0x103c, 0x83d3, "HP ProBook 640 G4", CXT_FIXUP_HP_DOCK),
        SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE),
@@ -931,6 +932,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x103c, 0x814f, "HP ZBook 15u G3", CXT_FIXUP_MUTE_LED_GPIO),
        SND_PCI_QUIRK(0x103c, 0x822e, "HP ProBook 440 G4", CXT_FIXUP_MUTE_LED_GPIO),
        SND_PCI_QUIRK(0x103c, 0x836e, "HP ProBook 455 G5", CXT_FIXUP_MUTE_LED_GPIO),
+       SND_PCI_QUIRK(0x103c, 0x837f, "HP ProBook 470 G5", CXT_FIXUP_MUTE_LED_GPIO),
        SND_PCI_QUIRK(0x103c, 0x8299, "HP 800 G3 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x829a, "HP 800 G3 DM", CXT_FIXUP_HP_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x8455, "HP Z2 G4", CXT_FIXUP_HP_MIC_NO_PRESENCE),
index aee4cbd..6df758a 100644 (file)
@@ -117,6 +117,7 @@ struct alc_spec {
        int codec_variant;      /* flag for other variants */
        unsigned int has_alc5505_dsp:1;
        unsigned int no_depop_delay:1;
+       unsigned int done_hp_init:1;
 
        /* for PLL fix */
        hda_nid_t pll_nid;
@@ -514,6 +515,15 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
        }
 }
 
+/* get a primary headphone pin if available */
+static hda_nid_t alc_get_hp_pin(struct alc_spec *spec)
+{
+       if (spec->gen.autocfg.hp_pins[0])
+               return spec->gen.autocfg.hp_pins[0];
+       if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT)
+               return spec->gen.autocfg.line_out_pins[0];
+       return 0;
+}
 
 /*
  * Realtek SSID verification
@@ -724,9 +734,7 @@ do_sku:
         * 15   : 1 --> enable the function "Mute internal speaker
         *              when the external headphone out jack is plugged"
         */
-       if (!spec->gen.autocfg.hp_pins[0] &&
-           !(spec->gen.autocfg.line_out_pins[0] &&
-             spec->gen.autocfg.line_out_type == AUTO_PIN_HP_OUT)) {
+       if (!alc_get_hp_pin(spec)) {
                hda_nid_t nid;
                tmp = (ass >> 11) & 0x3;        /* HP to chassis */
                nid = ports[tmp];
@@ -2958,7 +2966,7 @@ static void alc282_restore_default_value(struct hda_codec *codec)
 static void alc282_init(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
        int coef78;
 
@@ -2995,7 +3003,7 @@ static void alc282_init(struct hda_codec *codec)
 static void alc282_shutup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
        int coef78;
 
@@ -3073,14 +3081,9 @@ static void alc283_restore_default_value(struct hda_codec *codec)
 static void alc283_init(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
 
-       if (!spec->gen.autocfg.hp_outs) {
-               if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT)
-                       hp_pin = spec->gen.autocfg.line_out_pins[0];
-       }
-
        alc283_restore_default_value(codec);
 
        if (!hp_pin)
@@ -3114,14 +3117,9 @@ static void alc283_init(struct hda_codec *codec)
 static void alc283_shutup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
 
-       if (!spec->gen.autocfg.hp_outs) {
-               if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT)
-                       hp_pin = spec->gen.autocfg.line_out_pins[0];
-       }
-
        if (!hp_pin) {
                alc269_shutup(codec);
                return;
@@ -3155,7 +3153,7 @@ static void alc283_shutup(struct hda_codec *codec)
 static void alc256_init(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
 
        if (!hp_pin)
@@ -3191,7 +3189,7 @@ static void alc256_init(struct hda_codec *codec)
 static void alc256_shutup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
 
        if (!hp_pin) {
@@ -3227,7 +3225,7 @@ static void alc256_shutup(struct hda_codec *codec)
 static void alc225_init(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp1_pin_sense, hp2_pin_sense;
 
        if (!hp_pin)
@@ -3270,7 +3268,7 @@ static void alc225_init(struct hda_codec *codec)
 static void alc225_shutup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp1_pin_sense, hp2_pin_sense;
 
        if (!hp_pin) {
@@ -3314,7 +3312,7 @@ static void alc225_shutup(struct hda_codec *codec)
 static void alc_default_init(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
 
        if (!hp_pin)
@@ -3343,7 +3341,7 @@ static void alc_default_init(struct hda_codec *codec)
 static void alc_default_shutup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
 
        if (!hp_pin) {
@@ -3372,6 +3370,48 @@ static void alc_default_shutup(struct hda_codec *codec)
        snd_hda_shutup_pins(codec);
 }
 
+static void alc294_hp_init(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
+       int i, val;
+
+       if (!hp_pin)
+               return;
+
+       snd_hda_codec_write(codec, hp_pin, 0,
+                           AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
+
+       msleep(100);
+
+       snd_hda_codec_write(codec, hp_pin, 0,
+                           AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
+
+       alc_update_coef_idx(codec, 0x6f, 0x000f, 0);/* Set HP depop to manual mode */
+       alc_update_coefex_idx(codec, 0x58, 0x00, 0x8000, 0x8000); /* HP depop procedure start */
+
+       /* Wait for depop procedure finish  */
+       val = alc_read_coefex_idx(codec, 0x58, 0x01);
+       for (i = 0; i < 20 && val & 0x0080; i++) {
+               msleep(50);
+               val = alc_read_coefex_idx(codec, 0x58, 0x01);
+       }
+       /* Set HP depop to auto mode */
+       alc_update_coef_idx(codec, 0x6f, 0x000f, 0x000b);
+       msleep(50);
+}
+
+static void alc294_init(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+
+       if (!spec->done_hp_init) {
+               alc294_hp_init(codec);
+               spec->done_hp_init = true;
+       }
+       alc_default_init(codec);
+}
+
 static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg,
                             unsigned int val)
 {
@@ -4102,6 +4142,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
        case 0x10ec0295:
        case 0x10ec0289:
        case 0x10ec0299:
+               alc_process_coef_fw(codec, alc225_pre_hsmode);
                alc_process_coef_fw(codec, coef0225);
                break;
        case 0x10ec0867:
@@ -4736,7 +4777,7 @@ static void alc_update_headset_mode(struct hda_codec *codec)
        struct alc_spec *spec = codec->spec;
 
        hda_nid_t mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]];
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
 
        int new_headset_mode;
 
@@ -5015,7 +5056,7 @@ static void alc_fixup_tpt470_dock(struct hda_codec *codec,
 static void alc_shutup_dell_xps13(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       int hp_pin = spec->gen.autocfg.hp_pins[0];
+       int hp_pin = alc_get_hp_pin(spec);
 
        /* Prevent pop noises when headphones are plugged in */
        snd_hda_codec_write(codec, hp_pin, 0,
@@ -5108,7 +5149,7 @@ static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
 
        if (action == HDA_FIXUP_ACT_PROBE) {
                int mic_pin = find_ext_mic_pin(codec);
-               int hp_pin = spec->gen.autocfg.hp_pins[0];
+               int hp_pin = alc_get_hp_pin(spec);
 
                if (snd_BUG_ON(!mic_pin || !hp_pin))
                        return;
@@ -5440,6 +5481,13 @@ static void alc_fixup_headset_jack(struct hda_codec *codec,
        }
 }
 
+static void alc_fixup_disable_mic_vref(struct hda_codec *codec,
+                                 const struct hda_fixup *fix, int action)
+{
+       if (action == HDA_FIXUP_ACT_PRE_PROBE)
+               snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ);
+}
+
 /* for hda_fixup_thinkpad_acpi() */
 #include "thinkpad_helper.c"
 
@@ -5549,6 +5597,7 @@ enum {
        ALC293_FIXUP_LENOVO_SPK_NOISE,
        ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY,
        ALC255_FIXUP_DELL_SPK_NOISE,
+       ALC225_FIXUP_DISABLE_MIC_VREF,
        ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
        ALC295_FIXUP_DISABLE_DAC3,
        ALC280_FIXUP_HP_HEADSET_MIC,
@@ -5582,6 +5631,7 @@ enum {
        ALC294_FIXUP_ASUS_HEADSET_MIC,
        ALC294_FIXUP_ASUS_SPK,
        ALC225_FIXUP_HEADSET_JACK,
+       ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -6268,6 +6318,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
        },
+       [ALC225_FIXUP_DISABLE_MIC_VREF] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_disable_mic_vref,
+               .chained = true,
+               .chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE
+       },
        [ALC225_FIXUP_DELL1_MIC_NO_PRESENCE] = {
                .type = HDA_FIXUP_VERBS,
                .v.verbs = (const struct hda_verb[]) {
@@ -6277,7 +6333,7 @@ static const struct hda_fixup alc269_fixups[] = {
                        {}
                },
                .chained = true,
-               .chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE
+               .chain_id = ALC225_FIXUP_DISABLE_MIC_VREF
        },
        [ALC280_FIXUP_HP_HEADSET_MIC] = {
                .type = HDA_FIXUP_FUNC,
@@ -6522,6 +6578,15 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_headset_jack,
        },
+       [ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x1a, 0x01a1913c }, /* 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[] = {
@@ -6584,6 +6649,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0871, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
        SND_PCI_QUIRK(0x1028, 0x0872, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
        SND_PCI_QUIRK(0x1028, 0x0873, "Dell Precision 3930", ALC255_FIXUP_DUMMY_LINEOUT_VERB),
+       SND_PCI_QUIRK(0x1028, 0x0935, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
        SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -6699,6 +6765,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1558, 0x1325, "System76 Darter Pro (darp5)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
@@ -6910,7 +6977,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {.id = ALC293_FIXUP_LENOVO_SPK_NOISE, .name = "lenovo-spk-noise"},
        {.id = ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY, .name = "lenovo-hotkey"},
        {.id = ALC255_FIXUP_DELL_SPK_NOISE, .name = "dell-spk-noise"},
-       {.id = ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc255-dell1"},
+       {.id = ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc225-dell1"},
        {.id = ALC295_FIXUP_DISABLE_DAC3, .name = "alc295-disable-dac3"},
        {.id = ALC280_FIXUP_HP_HEADSET_MIC, .name = "alc280-hp-headset"},
        {.id = ALC221_FIXUP_HP_FRONT_MIC, .name = "alc221-hp-mic"},
@@ -7357,37 +7424,6 @@ static void alc269_fill_coef(struct hda_codec *codec)
        alc_update_coef_idx(codec, 0x4, 0, 1<<11);
 }
 
-static void alc294_hp_init(struct hda_codec *codec)
-{
-       struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
-       int i, val;
-
-       if (!hp_pin)
-               return;
-
-       snd_hda_codec_write(codec, hp_pin, 0,
-                           AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
-       msleep(100);
-
-       snd_hda_codec_write(codec, hp_pin, 0,
-                           AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
-
-       alc_update_coef_idx(codec, 0x6f, 0x000f, 0);/* Set HP depop to manual mode */
-       alc_update_coefex_idx(codec, 0x58, 0x00, 0x8000, 0x8000); /* HP depop procedure start */
-
-       /* Wait for depop procedure finish  */
-       val = alc_read_coefex_idx(codec, 0x58, 0x01);
-       for (i = 0; i < 20 && val & 0x0080; i++) {
-               msleep(50);
-               val = alc_read_coefex_idx(codec, 0x58, 0x01);
-       }
-       /* Set HP depop to auto mode */
-       alc_update_coef_idx(codec, 0x6f, 0x000f, 0x000b);
-       msleep(50);
-}
-
 /*
  */
 static int patch_alc269(struct hda_codec *codec)
@@ -7513,7 +7549,7 @@ static int patch_alc269(struct hda_codec *codec)
                spec->codec_variant = ALC269_TYPE_ALC294;
                spec->gen.mixer_nid = 0; /* ALC2x4 does not have any loopback mixer path */
                alc_update_coef_idx(codec, 0x6b, 0x0018, (1<<4) | (1<<3)); /* UAJ MIC Vref control by verb */
-               alc294_hp_init(codec);
+               spec->init_hook = alc294_init;
                break;
        case 0x10ec0300:
                spec->codec_variant = ALC269_TYPE_ALC300;
@@ -7525,7 +7561,7 @@ static int patch_alc269(struct hda_codec *codec)
                spec->codec_variant = ALC269_TYPE_ALC700;
                spec->gen.mixer_nid = 0; /* ALC700 does not have any loopback mixer path */
                alc_update_coef_idx(codec, 0x4a, 1 << 15, 0); /* Combo jack auto trigger control */
-               alc294_hp_init(codec);
+               spec->init_hook = alc294_init;
                break;
 
        }
index 022a891..3d58338 100644 (file)
@@ -611,14 +611,16 @@ static int acp3x_audio_probe(struct platform_device *pdev)
        }
        irqflags = *((unsigned int *)(pdev->dev.platform_data));
 
-       adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
-                            GFP_KERNEL);
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
                        return -ENODEV;
        }
 
+       adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
+       if (!adata)
+               return -ENOMEM;
+
        adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
                                         resource_size(res));
 
index 3ab2949..b19d7a3 100644 (file)
@@ -1890,51 +1890,31 @@ static void hdmi_codec_remove(struct snd_soc_component *component)
        pm_runtime_disable(&hdev->dev);
 }
 
-#ifdef CONFIG_PM
-static int hdmi_codec_prepare(struct device *dev)
-{
-       struct hdac_device *hdev = dev_to_hdac_dev(dev);
-
-       pm_runtime_get_sync(&hdev->dev);
-
-       /*
-        * Power down afg.
-        * codec_read is preferred over codec_write to set the power state.
-        * This way verb is send to set the power state and response
-        * is received. So setting power state is ensured without using loop
-        * to read the state.
-        */
-       snd_hdac_codec_read(hdev, hdev->afg, 0, AC_VERB_SET_POWER_STATE,
-                                                       AC_PWRST_D3);
-
-       return 0;
-}
-
-static void hdmi_codec_complete(struct device *dev)
+#ifdef CONFIG_PM_SLEEP
+static int hdmi_codec_resume(struct device *dev)
 {
        struct hdac_device *hdev = dev_to_hdac_dev(dev);
        struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
+       int ret;
 
-       /* Power up afg */
-       snd_hdac_codec_read(hdev, hdev->afg, 0, AC_VERB_SET_POWER_STATE,
-                                                       AC_PWRST_D0);
-
-       hdac_hdmi_skl_enable_all_pins(hdev);
-       hdac_hdmi_skl_enable_dp12(hdev);
-
+       ret = pm_runtime_force_resume(dev);
+       if (ret < 0)
+               return ret;
        /*
         * As the ELD notify callback request is not entertained while the
         * device is in suspend state. Need to manually check detection of
         * all pins here. pin capablity change is not support, so use the
         * already set pin caps.
+        *
+        * NOTE: this is safe to call even if the codec doesn't actually resume.
+        * The pin check involves only with DRM audio component hooks, so it
+        * works even if the HD-audio side is still dreaming peacefully.
         */
        hdac_hdmi_present_sense_all_pins(hdev, hdmi, false);
-
-       pm_runtime_put_sync(&hdev->dev);
+       return 0;
 }
 #else
-#define hdmi_codec_prepare NULL
-#define hdmi_codec_complete NULL
+#define hdmi_codec_resume NULL
 #endif
 
 static const struct snd_soc_component_driver hdmi_hda_codec = {
@@ -2135,75 +2115,6 @@ static int hdac_hdmi_dev_remove(struct hdac_device *hdev)
 }
 
 #ifdef CONFIG_PM
-/*
- * Power management sequences
- * ==========================
- *
- * The following explains the PM handling of HDAC HDMI with its parent
- * device SKL and display power usage
- *
- * Probe
- * -----
- * In SKL probe,
- * 1. skl_probe_work() powers up the display (refcount++ -> 1)
- * 2. enumerates the codecs on the link
- * 3. powers down the display  (refcount-- -> 0)
- *
- * In HDAC HDMI probe,
- * 1. hdac_hdmi_dev_probe() powers up the display (refcount++ -> 1)
- * 2. probe the codec
- * 3. put the HDAC HDMI device to runtime suspend
- * 4. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0)
- *
- * Once children are runtime suspended, SKL device also goes to runtime
- * suspend
- *
- * HDMI Playback
- * -------------
- * Open HDMI device,
- * 1. skl_runtime_resume() invoked
- * 2. hdac_hdmi_runtime_resume() powers up the display (refcount++ -> 1)
- *
- * Close HDMI device,
- * 1. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0)
- * 2. skl_runtime_suspend() invoked
- *
- * S0/S3 Cycle with playback in progress
- * -------------------------------------
- * When the device is opened for playback, the device is runtime active
- * already and the display refcount is 1 as explained above.
- *
- * Entering to S3,
- * 1. hdmi_codec_prepare() invoke the runtime resume of codec which just
- *    increments the PM runtime usage count of the codec since the device
- *    is in use already
- * 2. skl_suspend() powers down the display (refcount-- -> 0)
- *
- * Wakeup from S3,
- * 1. skl_resume() powers up the display (refcount++ -> 1)
- * 2. hdmi_codec_complete() invokes the runtime suspend of codec which just
- *    decrements the PM runtime usage count of the codec since the device
- *    is in use already
- *
- * Once playback is stopped, the display refcount is set to 0 as explained
- * above in the HDMI playback sequence. The PM handlings are designed in
- * such way that to balance the refcount of display power when the codec
- * device put to S3 while playback is going on.
- *
- * S0/S3 Cycle without playback in progress
- * ----------------------------------------
- * Entering to S3,
- * 1. hdmi_codec_prepare() invoke the runtime resume of codec
- * 2. skl_runtime_resume() invoked
- * 3. hdac_hdmi_runtime_resume() powers up the display (refcount++ -> 1)
- * 4. skl_suspend() powers down the display (refcount-- -> 0)
- *
- * Wakeup from S3,
- * 1. skl_resume() powers up the display (refcount++ -> 1)
- * 2. hdmi_codec_complete() invokes the runtime suspend of codec
- * 3. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0)
- * 4. skl_runtime_suspend() invoked
- */
 static int hdac_hdmi_runtime_suspend(struct device *dev)
 {
        struct hdac_device *hdev = dev_to_hdac_dev(dev);
@@ -2277,8 +2188,7 @@ static int hdac_hdmi_runtime_resume(struct device *dev)
 
 static const struct dev_pm_ops hdac_hdmi_pm = {
        SET_RUNTIME_PM_OPS(hdac_hdmi_runtime_suspend, hdac_hdmi_runtime_resume, NULL)
-       .prepare = hdmi_codec_prepare,
-       .complete = hdmi_codec_complete,
+       SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, hdmi_codec_resume)
 };
 
 static const struct hda_device_id hdmi_list[] = {
index d00734d..e5b6769 100644 (file)
@@ -795,6 +795,8 @@ static int hdmi_codec_probe(struct platform_device *pdev)
        if (hcd->spdif)
                hcp->daidrv[i] = hdmi_spdif_dai;
 
+       dev_set_drvdata(dev, hcp);
+
        ret = devm_snd_soc_register_component(dev, &hdmi_driver, hcp->daidrv,
                                     dai_count);
        if (ret) {
@@ -802,8 +804,6 @@ static int hdmi_codec_probe(struct platform_device *pdev)
                        __func__, ret);
                return ret;
        }
-
-       dev_set_drvdata(dev, hcp);
        return 0;
 }
 
index 6cb1653..4cc24a5 100644 (file)
@@ -1400,24 +1400,20 @@ static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute)
                if (ret != 0) {
                        dev_err(component->dev,
                                "Failed to set digital mute: %d\n", ret);
-                       mutex_unlock(&pcm512x->mutex);
-                       return ret;
+                       goto unlock;
                }
 
                regmap_read_poll_timeout(pcm512x->regmap,
                                         PCM512x_ANALOG_MUTE_DET,
                                         mute_det, (mute_det & 0x3) == 0,
                                         200, 10000);
-
-               mutex_unlock(&pcm512x->mutex);
        } else {
                pcm512x->mute &= ~0x1;
                ret = pcm512x_update_mute(pcm512x);
                if (ret != 0) {
                        dev_err(component->dev,
                                "Failed to update digital mute: %d\n", ret);
-                       mutex_unlock(&pcm512x->mutex);
-                       return ret;
+                       goto unlock;
                }
 
                regmap_read_poll_timeout(pcm512x->regmap,
@@ -1428,9 +1424,10 @@ static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute)
                                         200, 10000);
        }
 
+unlock:
        mutex_unlock(&pcm512x->mutex);
 
-       return 0;
+       return ret;
 }
 
 static const struct snd_soc_dai_ops pcm512x_dai_ops = {
index 0ef966d..e2855ab 100644 (file)
@@ -1128,8 +1128,11 @@ static int rt274_i2c_probe(struct i2c_client *i2c,
                return ret;
        }
 
-       regmap_read(rt274->regmap,
+       ret = regmap_read(rt274->regmap,
                RT274_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &val);
+       if (ret)
+               return ret;
+
        if (val != RT274_VENDOR_ID) {
                dev_err(&i2c->dev,
                        "Device with ID register %#x is not rt274\n", val);
index 4d46f45..bec2eef 100644 (file)
@@ -280,6 +280,8 @@ static int rt5514_spi_pcm_probe(struct snd_soc_component *component)
 
        rt5514_dsp = devm_kzalloc(component->dev, sizeof(*rt5514_dsp),
                        GFP_KERNEL);
+       if (!rt5514_dsp)
+               return -ENOMEM;
 
        rt5514_dsp->dev = &rt5514_spi->dev;
        mutex_init(&rt5514_dsp->dma_lock);
index 34cfaf8..a9b91bc 100644 (file)
@@ -1778,7 +1778,9 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = {
        {"ADC Stereo1 Filter", NULL, "ADC STO1 ASRC", is_using_asrc},
        {"DAC Stereo1 Filter", NULL, "DAC STO1 ASRC", is_using_asrc},
        {"ADC STO1 ASRC", NULL, "AD ASRC"},
+       {"ADC STO1 ASRC", NULL, "DA ASRC"},
        {"ADC STO1 ASRC", NULL, "CLKDET"},
+       {"DAC STO1 ASRC", NULL, "AD ASRC"},
        {"DAC STO1 ASRC", NULL, "DA ASRC"},
        {"DAC STO1 ASRC", NULL, "CLKDET"},
 
@@ -2512,6 +2514,7 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682)
        regmap_write(rt5682->regmap, RT5682_PWR_DIG_1, 0x0000);
        regmap_write(rt5682->regmap, RT5682_CHOP_DAC, 0x2000);
        regmap_write(rt5682->regmap, RT5682_CALIB_ADC_CTRL, 0x2005);
+       regmap_write(rt5682->regmap, RT5682_STO1_ADC_MIXER, 0xc0c4);
 
        mutex_unlock(&rt5682->calibrate_mutex);
 
index d82a830..96944cf 100644 (file)
 #define RT5682_SCLK_SRC_PLL2                   (0x2 << 13)
 #define RT5682_SCLK_SRC_SDW                    (0x3 << 13)
 #define RT5682_SCLK_SRC_RCCLK                  (0x4 << 13)
-#define RT5682_PLL1_SRC_MASK                   (0x3 << 10)
-#define RT5682_PLL1_SRC_SFT                    10
-#define RT5682_PLL1_SRC_MCLK                   (0x0 << 10)
-#define RT5682_PLL1_SRC_BCLK1                  (0x1 << 10)
-#define RT5682_PLL1_SRC_SDW                    (0x2 << 10)
-#define RT5682_PLL1_SRC_RC                     (0x3 << 10)
-#define RT5682_PLL2_SRC_MASK                   (0x3 << 8)
-#define RT5682_PLL2_SRC_SFT                    8
-#define RT5682_PLL2_SRC_MCLK                   (0x0 << 8)
-#define RT5682_PLL2_SRC_BCLK1                  (0x1 << 8)
-#define RT5682_PLL2_SRC_SDW                    (0x2 << 8)
-#define RT5682_PLL2_SRC_RC                     (0x3 << 8)
+#define RT5682_PLL2_SRC_MASK                   (0x3 << 10)
+#define RT5682_PLL2_SRC_SFT                    10
+#define RT5682_PLL2_SRC_MCLK                   (0x0 << 10)
+#define RT5682_PLL2_SRC_BCLK1                  (0x1 << 10)
+#define RT5682_PLL2_SRC_SDW                    (0x2 << 10)
+#define RT5682_PLL2_SRC_RC                     (0x3 << 10)
+#define RT5682_PLL1_SRC_MASK                   (0x3 << 8)
+#define RT5682_PLL1_SRC_SFT                    8
+#define RT5682_PLL1_SRC_MCLK                   (0x0 << 8)
+#define RT5682_PLL1_SRC_BCLK1                  (0x1 << 8)
+#define RT5682_PLL1_SRC_SDW                    (0x2 << 8)
+#define RT5682_PLL1_SRC_RC                     (0x3 << 8)
 
 
 
index e2b5a11..f03195d 100644 (file)
@@ -822,6 +822,10 @@ static int aic32x4_set_bias_level(struct snd_soc_component *component,
        case SND_SOC_BIAS_PREPARE:
                break;
        case SND_SOC_BIAS_STANDBY:
+               /* Initial cold start */
+               if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
+                       break;
+
                /* Switch off BCLK_N Divider */
                snd_soc_component_update_bits(component, AIC32X4_BCLKN,
                                    AIC32X4_BCLKEN, 0);
index 392d5ee..99e07b0 100644 (file)
@@ -86,49 +86,49 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
        if (!buf)
                return -ENOMEM;
 
-       ret = snprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n",
+       ret = scnprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n",
                       pdcr, ptcr);
 
        if (ptcr & IMX_AUDMUX_V2_PTCR_TFSDIR)
-               ret += snprintf(buf + ret, PAGE_SIZE - ret,
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                "TxFS output from %s, ",
                                audmux_port_string((ptcr >> 27) & 0x7));
        else
-               ret += snprintf(buf + ret, PAGE_SIZE - ret,
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                "TxFS input, ");
 
        if (ptcr & IMX_AUDMUX_V2_PTCR_TCLKDIR)
-               ret += snprintf(buf + ret, PAGE_SIZE - ret,
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                "TxClk output from %s",
                                audmux_port_string((ptcr >> 22) & 0x7));
        else
-               ret += snprintf(buf + ret, PAGE_SIZE - ret,
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                "TxClk input");
 
-       ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+       ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
 
        if (ptcr & IMX_AUDMUX_V2_PTCR_SYN) {
-               ret += snprintf(buf + ret, PAGE_SIZE - ret,
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                "Port is symmetric");
        } else {
                if (ptcr & IMX_AUDMUX_V2_PTCR_RFSDIR)
-                       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+                       ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                        "RxFS output from %s, ",
                                        audmux_port_string((ptcr >> 17) & 0x7));
                else
-                       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+                       ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                        "RxFS input, ");
 
                if (ptcr & IMX_AUDMUX_V2_PTCR_RCLKDIR)
-                       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+                       ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                        "RxClk output from %s",
                                        audmux_port_string((ptcr >> 12) & 0x7));
                else
-                       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+                       ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                        "RxClk input");
        }
 
-       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+       ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                        "\nData received from %s\n",
                        audmux_port_string((pdcr >> 13) & 0x7));
 
index 99a62ba..bd9fd20 100644 (file)
@@ -91,7 +91,7 @@ config SND_SST_ATOM_HIFI2_PLATFORM_PCI
 config SND_SST_ATOM_HIFI2_PLATFORM_ACPI
        tristate "ACPI HiFi2 (Baytrail, Cherrytrail) Platforms"
        default ACPI
-       depends on X86 && ACPI
+       depends on X86 && ACPI && PCI
        select SND_SST_IPC_ACPI
        select SND_SST_ATOM_HIFI2_PLATFORM
        select SND_SOC_ACPI_INTEL_MATCH
index afc5598..91a2436 100644 (file)
@@ -399,7 +399,13 @@ static int sst_media_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *params,
                                struct snd_soc_dai *dai)
 {
-       snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+       int ret;
+
+       ret =
+               snd_pcm_lib_malloc_pages(substream,
+                               params_buffer_bytes(params));
+       if (ret)
+               return ret;
        memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
        return 0;
 }
index 68e6543..99f2a01 100644 (file)
@@ -192,7 +192,7 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = {
                .stream_name = "Loopback",
                .cpu_dai_name = "Loopback Pin",
                .platform_name = "haswell-pcm-audio",
-               .dynamic = 0,
+               .dynamic = 1,
                .codec_name = "snd-soc-dummy",
                .codec_dai_name = "snd-soc-dummy-dai",
                .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
index c74c4f1..8f83b18 100644 (file)
@@ -55,39 +55,6 @@ enum {
        GLK_DPCM_AUDIO_HDMI3_PB,
 };
 
-static int platform_clock_control(struct snd_soc_dapm_widget *w,
-                                       struct snd_kcontrol *k, int  event)
-{
-       struct snd_soc_dapm_context *dapm = w->dapm;
-       struct snd_soc_card *card = dapm->card;
-       struct snd_soc_dai *codec_dai;
-       int ret = 0;
-
-       codec_dai = snd_soc_card_get_codec_dai(card, GLK_REALTEK_CODEC_DAI);
-       if (!codec_dai) {
-               dev_err(card->dev, "Codec dai not found; Unable to set/unset codec pll\n");
-               return -EIO;
-       }
-
-       if (SND_SOC_DAPM_EVENT_OFF(event)) {
-               ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0);
-               if (ret)
-                       dev_err(card->dev, "failed to stop sysclk: %d\n", ret);
-       } else if (SND_SOC_DAPM_EVENT_ON(event)) {
-               ret = snd_soc_dai_set_pll(codec_dai, 0, RT5682_PLL1_S_MCLK,
-                                       GLK_PLAT_CLK_FREQ, RT5682_PLL_FREQ);
-               if (ret < 0) {
-                       dev_err(card->dev, "can't set codec pll: %d\n", ret);
-                       return ret;
-               }
-       }
-
-       if (ret)
-               dev_err(card->dev, "failed to start internal clk: %d\n", ret);
-
-       return ret;
-}
-
 static const struct snd_kcontrol_new geminilake_controls[] = {
        SOC_DAPM_PIN_SWITCH("Headphone Jack"),
        SOC_DAPM_PIN_SWITCH("Headset Mic"),
@@ -102,14 +69,10 @@ static const struct snd_soc_dapm_widget geminilake_widgets[] = {
        SND_SOC_DAPM_SPK("HDMI1", NULL),
        SND_SOC_DAPM_SPK("HDMI2", NULL),
        SND_SOC_DAPM_SPK("HDMI3", NULL),
-       SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
-                       platform_clock_control, SND_SOC_DAPM_PRE_PMU |
-                       SND_SOC_DAPM_POST_PMD),
 };
 
 static const struct snd_soc_dapm_route geminilake_map[] = {
        /* HP jack connectors - unknown if we have jack detection */
-       { "Headphone Jack", NULL, "Platform Clock" },
        { "Headphone Jack", NULL, "HPOL" },
        { "Headphone Jack", NULL, "HPOR" },
 
@@ -117,7 +80,6 @@ static const struct snd_soc_dapm_route geminilake_map[] = {
        { "Spk", NULL, "Speaker" },
 
        /* other jacks */
-       { "Headset Mic", NULL, "Platform Clock" },
        { "IN1P", NULL, "Headset Mic" },
 
        /* digital mics */
@@ -177,6 +139,13 @@ static int geminilake_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
        struct snd_soc_jack *jack;
        int ret;
 
+       ret = snd_soc_dai_set_pll(codec_dai, 0, RT5682_PLL1_S_MCLK,
+                                       GLK_PLAT_CLK_FREQ, RT5682_PLL_FREQ);
+       if (ret < 0) {
+               dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
+               return ret;
+       }
+
        /* Configure sysclk for codec */
        ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL1,
                                        RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
index eab1f43..a402298 100644 (file)
@@ -146,7 +146,7 @@ static struct snd_soc_dai_link haswell_rt5640_dais[] = {
                .stream_name = "Loopback",
                .cpu_dai_name = "Loopback Pin",
                .platform_name = "haswell-pcm-audio",
-               .dynamic = 0,
+               .dynamic = 1,
                .codec_name = "snd-soc-dummy",
                .codec_dai_name = "snd-soc-dummy-dai",
                .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
index 60c9483..4ed5b7e 100644 (file)
@@ -336,9 +336,6 @@ static int skl_suspend(struct device *dev)
                skl->skl_sst->fw_loaded = false;
        }
 
-       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
-               snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
-
        return 0;
 }
 
@@ -350,10 +347,6 @@ static int skl_resume(struct device *dev)
        struct hdac_ext_link *hlink = NULL;
        int ret;
 
-       /* Turned OFF in HDMI codec driver after codec reconfiguration */
-       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
-               snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true);
-
        /*
         * resume only when we are not in suspend active, otherwise need to
         * restore the device
@@ -446,8 +439,10 @@ static int skl_free(struct hdac_bus *bus)
        snd_hdac_ext_bus_exit(bus);
 
        cancel_work_sync(&skl->probe_work);
-       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
+       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
+               snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
                snd_hdac_i915_exit(bus);
+       }
 
        return 0;
 }
@@ -814,7 +809,7 @@ static void skl_probe_work(struct work_struct *work)
        err = skl_platform_register(bus->dev);
        if (err < 0) {
                dev_err(bus->dev, "platform register failed: %d\n", err);
-               return;
+               goto out_err;
        }
 
        err = skl_machine_device_register(skl);
index 5b986b7..548eb4f 100644 (file)
@@ -570,10 +570,10 @@ static int q6asm_dai_compr_open(struct snd_compr_stream *stream)
        prtd->audio_client = q6asm_audio_client_alloc(dev,
                                        (q6asm_cb)compress_event_handler,
                                        prtd, stream_id, LEGACY_PCM_MODE);
-       if (!prtd->audio_client) {
+       if (IS_ERR(prtd->audio_client)) {
                dev_err(dev, "Could not allocate memory\n");
-               kfree(prtd);
-               return -ENOMEM;
+               ret = PTR_ERR(prtd->audio_client);
+               goto free_prtd;
        }
 
        size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE *
@@ -582,7 +582,7 @@ static int q6asm_dai_compr_open(struct snd_compr_stream *stream)
                                  &prtd->dma_buffer);
        if (ret) {
                dev_err(dev, "Cannot allocate buffer(s)\n");
-               return ret;
+               goto free_client;
        }
 
        if (pdata->sid < 0)
@@ -595,6 +595,13 @@ static int q6asm_dai_compr_open(struct snd_compr_stream *stream)
        runtime->private_data = prtd;
 
        return 0;
+
+free_client:
+       q6asm_audio_client_free(prtd->audio_client);
+free_prtd:
+       kfree(prtd);
+
+       return ret;
 }
 
 static int q6asm_dai_compr_free(struct snd_compr_stream *stream)
@@ -874,7 +881,7 @@ static int of_q6asm_parse_dai_data(struct device *dev,
 
        for_each_child_of_node(dev->of_node, node) {
                ret = of_property_read_u32(node, "reg", &id);
-               if (ret || id > MAX_SESSIONS || id < 0) {
+               if (ret || id >= MAX_SESSIONS || id < 0) {
                        dev_err(dev, "valid dai id not found:%d\n", ret);
                        continue;
                }
index 1db8ef6..6f66a58 100644 (file)
@@ -158,17 +158,24 @@ static int sdm845_snd_hw_params(struct snd_pcm_substream *substream,
        return ret;
 }
 
+static void sdm845_jack_free(struct snd_jack *jack)
+{
+       struct snd_soc_component *component = jack->private_data;
+
+       snd_soc_component_set_jack(component, NULL, NULL);
+}
+
 static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_component *component;
-       struct snd_soc_dai_link *dai_link = rtd->dai_link;
        struct snd_soc_card *card = rtd->card;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(card);
-       int i, rval;
+       struct snd_jack *jack;
+       int rval;
 
        if (!pdata->jack_setup) {
-               struct snd_jack *jack;
-
                rval = snd_soc_card_jack_new(card, "Headset Jack",
                                SND_JACK_HEADSET |
                                SND_JACK_HEADPHONE |
@@ -190,16 +197,22 @@ static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd)
                pdata->jack_setup = true;
        }
 
-       for (i = 0 ; i < dai_link->num_codecs; i++) {
-               struct snd_soc_dai *dai = rtd->codec_dais[i];
+       switch (cpu_dai->id) {
+       case PRIMARY_MI2S_RX:
+               jack  = pdata->jack.jack;
+               component = codec_dai->component;
 
-               component = dai->component;
-               rval = snd_soc_component_set_jack(
-                               component, &pdata->jack, NULL);
+               jack->private_data = component;
+               jack->private_free = sdm845_jack_free;
+               rval = snd_soc_component_set_jack(component,
+                                                 &pdata->jack, NULL);
                if (rval != 0 && rval != -ENOTSUPP) {
                        dev_warn(card->dev, "Failed to set jack: %d\n", rval);
                        return rval;
                }
+               break;
+       default:
+               break;
        }
 
        return 0;
index d6c62aa..ce00fe2 100644 (file)
@@ -700,6 +700,7 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
 {
        struct i2s_dai *i2s = to_info(dai);
        u32 mod, mask = 0, val = 0;
+       struct clk *rclksrc;
        unsigned long flags;
 
        WARN_ON(!pm_runtime_active(dai->dev));
@@ -782,6 +783,10 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
 
        i2s->frmclk = params_rate(params);
 
+       rclksrc = i2s->clk_table[CLK_I2S_RCLK_SRC];
+       if (rclksrc && !IS_ERR(rclksrc))
+               i2s->rclk_srcrate = clk_get_rate(rclksrc);
+
        return 0;
 }
 
@@ -886,11 +891,6 @@ static int config_setup(struct i2s_dai *i2s)
                return 0;
 
        if (!(i2s->quirks & QUIRK_NO_MUXPSR)) {
-               struct clk *rclksrc = i2s->clk_table[CLK_I2S_RCLK_SRC];
-
-               if (rclksrc && !IS_ERR(rclksrc))
-                       i2s->rclk_srcrate = clk_get_rate(rclksrc);
-
                psr = i2s->rclk_srcrate / i2s->frmclk / rfs;
                writel(((psr - 1) << 8) | PSR_PSREN, i2s->addr + I2SPSR);
                dev_dbg(&i2s->pdev->dev,
index 922fb6a..5aee11c 100644 (file)
@@ -202,7 +202,7 @@ static int camelot_prepare(struct snd_pcm_substream *substream)
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
 
-       pr_debug("PCM data: addr 0x%08ulx len %d\n",
+       pr_debug("PCM data: addr 0x%08lx len %d\n",
                 (u32)runtime->dma_addr, runtime->dma_bytes);
  
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
index 59e250c..e819e96 100644 (file)
@@ -1526,14 +1526,14 @@ int rsnd_kctrl_new(struct rsnd_mod *mod,
        int ret;
 
        /*
-        * 1) Avoid duplicate register (ex. MIXer case)
-        * 2) re-register if card was rebinded
+        * 1) Avoid duplicate register for DVC with MIX case
+        * 2) Allow duplicate register for MIX
+        * 3) re-register if card was rebinded
         */
        list_for_each_entry(kctrl, &card->controls, list) {
                struct rsnd_kctrl_cfg *c = kctrl->private_data;
 
-               if (strcmp(kctrl->id.name, name) == 0 &&
-                   c->mod == mod)
+               if (c == cfg)
                        return 0;
        }
 
index 45ef295..f5afab6 100644 (file)
@@ -286,7 +286,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
        if (rsnd_ssi_is_multi_slave(mod, io))
                return 0;
 
-       if (ssi->usrcnt > 1) {
+       if (ssi->usrcnt > 0) {
                if (ssi->rate != rate) {
                        dev_err(dev, "SSI parent/child should use same rate\n");
                        return -EINVAL;
index c5934ad..c74991d 100644 (file)
@@ -79,7 +79,7 @@ static int rsnd_ssiu_init(struct rsnd_mod *mod,
                break;
        case 9:
                for (i = 0; i < 4; i++)
-                       rsnd_mod_write(mod, SSI_SYS_STATUS((i * 2) + 1), 0xf << (id * 4));
+                       rsnd_mod_write(mod, SSI_SYS_STATUS((i * 2) + 1), 0xf << 4);
                break;
        }
 
index 0462b3e..50617db 100644 (file)
@@ -735,14 +735,19 @@ static struct snd_soc_component *soc_find_component(
        const struct device_node *of_node, const char *name)
 {
        struct snd_soc_component *component;
+       struct device_node *component_of_node;
 
        lockdep_assert_held(&client_mutex);
 
        for_each_component(component) {
                if (of_node) {
-                       if (component->dev->of_node == of_node)
+                       component_of_node = component->dev->of_node;
+                       if (!component_of_node && component->dev->parent)
+                               component_of_node = component->dev->parent->of_node;
+
+                       if (component_of_node == of_node)
                                return component;
-               } else if (strcmp(component->name, name) == 0) {
+               } else if (name && strcmp(component->name, name) == 0) {
                        return component;
                }
        }
@@ -951,7 +956,7 @@ static void soc_remove_dai(struct snd_soc_dai *dai, int order)
 {
        int err;
 
-       if (!dai || !dai->probed ||
+       if (!dai || !dai->probed || !dai->driver ||
            dai->driver->remove_order != order)
                return;
 
@@ -1034,17 +1039,18 @@ static int snd_soc_init_platform(struct snd_soc_card *card,
         * this function should be removed in the future
         */
        /* convert Legacy platform link */
-       if (!platform) {
+       if (!platform || dai_link->legacy_platform) {
                platform = devm_kzalloc(card->dev,
                                sizeof(struct snd_soc_dai_link_component),
                                GFP_KERNEL);
                if (!platform)
                        return -ENOMEM;
 
-               dai_link->platform      = platform;
-               platform->name          = dai_link->platform_name;
-               platform->of_node       = dai_link->platform_of_node;
-               platform->dai_name      = NULL;
+               dai_link->platform        = platform;
+               dai_link->legacy_platform = 1;
+               platform->name            = dai_link->platform_name;
+               platform->of_node         = dai_link->platform_of_node;
+               platform->dai_name        = NULL;
        }
 
        /* if there's no platform we match on the empty platform */
@@ -1129,6 +1135,15 @@ static int soc_init_dai_link(struct snd_soc_card *card,
                        link->name);
                return -EINVAL;
        }
+
+       /*
+        * Defer card registartion if platform dai component is not added to
+        * component list.
+        */
+       if ((link->platform->of_node || link->platform->name) &&
+           !soc_find_component(link->platform->of_node, link->platform->name))
+               return -EPROBE_DEFER;
+
        /*
         * CPU device may be specified by either name or OF node, but
         * can be left unspecified, and will be matched based on DAI
@@ -1140,6 +1155,15 @@ static int soc_init_dai_link(struct snd_soc_card *card,
                        link->name);
                return -EINVAL;
        }
+
+       /*
+        * Defer card registartion if cpu dai component is not added to
+        * component list.
+        */
+       if ((link->cpu_of_node || link->cpu_name) &&
+           !soc_find_component(link->cpu_of_node, link->cpu_name))
+               return -EPROBE_DEFER;
+
        /*
         * At least one of CPU DAI name or CPU device name/node must be
         * specified
@@ -2739,15 +2763,18 @@ int snd_soc_register_card(struct snd_soc_card *card)
        if (!card->name || !card->dev)
                return -EINVAL;
 
+       mutex_lock(&client_mutex);
        for_each_card_prelinks(card, i, link) {
 
                ret = soc_init_dai_link(card, link);
                if (ret) {
                        dev_err(card->dev, "ASoC: failed to init link %s\n",
                                link->name);
+                       mutex_unlock(&client_mutex);
                        return ret;
                }
        }
+       mutex_unlock(&client_mutex);
 
        dev_set_drvdata(card->dev, card);
 
index a517884..20bad75 100644 (file)
@@ -70,12 +70,16 @@ static int dapm_up_seq[] = {
        [snd_soc_dapm_clock_supply] = 1,
        [snd_soc_dapm_supply] = 2,
        [snd_soc_dapm_micbias] = 3,
+       [snd_soc_dapm_vmid] = 3,
        [snd_soc_dapm_dai_link] = 2,
        [snd_soc_dapm_dai_in] = 4,
        [snd_soc_dapm_dai_out] = 4,
        [snd_soc_dapm_aif_in] = 4,
        [snd_soc_dapm_aif_out] = 4,
        [snd_soc_dapm_mic] = 5,
+       [snd_soc_dapm_siggen] = 5,
+       [snd_soc_dapm_input] = 5,
+       [snd_soc_dapm_output] = 5,
        [snd_soc_dapm_mux] = 6,
        [snd_soc_dapm_demux] = 6,
        [snd_soc_dapm_dac] = 7,
@@ -83,11 +87,19 @@ static int dapm_up_seq[] = {
        [snd_soc_dapm_mixer] = 8,
        [snd_soc_dapm_mixer_named_ctl] = 8,
        [snd_soc_dapm_pga] = 9,
+       [snd_soc_dapm_buffer] = 9,
+       [snd_soc_dapm_scheduler] = 9,
+       [snd_soc_dapm_effect] = 9,
+       [snd_soc_dapm_src] = 9,
+       [snd_soc_dapm_asrc] = 9,
+       [snd_soc_dapm_encoder] = 9,
+       [snd_soc_dapm_decoder] = 9,
        [snd_soc_dapm_adc] = 10,
        [snd_soc_dapm_out_drv] = 11,
        [snd_soc_dapm_hp] = 11,
        [snd_soc_dapm_spk] = 11,
        [snd_soc_dapm_line] = 11,
+       [snd_soc_dapm_sink] = 11,
        [snd_soc_dapm_kcontrol] = 12,
        [snd_soc_dapm_post] = 13,
 };
@@ -100,13 +112,25 @@ static int dapm_down_seq[] = {
        [snd_soc_dapm_spk] = 3,
        [snd_soc_dapm_line] = 3,
        [snd_soc_dapm_out_drv] = 3,
+       [snd_soc_dapm_sink] = 3,
        [snd_soc_dapm_pga] = 4,
+       [snd_soc_dapm_buffer] = 4,
+       [snd_soc_dapm_scheduler] = 4,
+       [snd_soc_dapm_effect] = 4,
+       [snd_soc_dapm_src] = 4,
+       [snd_soc_dapm_asrc] = 4,
+       [snd_soc_dapm_encoder] = 4,
+       [snd_soc_dapm_decoder] = 4,
        [snd_soc_dapm_switch] = 5,
        [snd_soc_dapm_mixer_named_ctl] = 5,
        [snd_soc_dapm_mixer] = 5,
        [snd_soc_dapm_dac] = 6,
        [snd_soc_dapm_mic] = 7,
+       [snd_soc_dapm_siggen] = 7,
+       [snd_soc_dapm_input] = 7,
+       [snd_soc_dapm_output] = 7,
        [snd_soc_dapm_micbias] = 8,
+       [snd_soc_dapm_vmid] = 8,
        [snd_soc_dapm_mux] = 9,
        [snd_soc_dapm_demux] = 9,
        [snd_soc_dapm_aif_in] = 10,
@@ -2019,19 +2043,19 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
                out = is_connected_output_ep(w, NULL, NULL);
        }
 
-       ret = snprintf(buf, PAGE_SIZE, "%s: %s%s  in %d out %d",
+       ret = scnprintf(buf, PAGE_SIZE, "%s: %s%s  in %d out %d",
                       w->name, w->power ? "On" : "Off",
                       w->force ? " (forced)" : "", in, out);
 
        if (w->reg >= 0)
-               ret += snprintf(buf + ret, PAGE_SIZE - ret,
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                " - R%d(0x%x) mask 0x%x",
                                w->reg, w->reg, w->mask << w->shift);
 
-       ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+       ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
 
        if (w->sname)
-               ret += snprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n",
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n",
                                w->sname,
                                w->active ? "active" : "inactive");
 
@@ -2044,7 +2068,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
                        if (!p->connect)
                                continue;
 
-                       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+                       ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                        " %s  \"%s\" \"%s\"\n",
                                        (rdir == SND_SOC_DAPM_DIR_IN) ? "in" : "out",
                                        p->name ? p->name : "static",
index 045ef13..fc79ec6 100644 (file)
@@ -502,6 +502,7 @@ static void remove_dai(struct snd_soc_component *comp,
 {
        struct snd_soc_dai_driver *dai_drv =
                container_of(dobj, struct snd_soc_dai_driver, dobj);
+       struct snd_soc_dai *dai;
 
        if (pass != SOC_TPLG_PASS_PCM_DAI)
                return;
@@ -509,6 +510,10 @@ static void remove_dai(struct snd_soc_component *comp,
        if (dobj->ops && dobj->ops->dai_unload)
                dobj->ops->dai_unload(comp, dobj);
 
+       list_for_each_entry(dai, &comp->dai_list, list)
+               if (dai->driver == dai_drv)
+                       dai->driver = NULL;
+
        kfree(dai_drv->name);
        list_del(&dobj->list);
        kfree(dai_drv);
index eeda6d5..a10fcb5 100644 (file)
@@ -108,7 +108,7 @@ struct davinci_mcasp {
        /* Used for comstraint setting on the second stream */
        u32     channels;
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
        struct davinci_mcasp_context context;
 #endif
 
@@ -1486,74 +1486,6 @@ static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int davinci_mcasp_suspend(struct snd_soc_dai *dai)
-{
-       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
-       struct davinci_mcasp_context *context = &mcasp->context;
-       u32 reg;
-       int i;
-
-       context->pm_state = pm_runtime_active(mcasp->dev);
-       if (!context->pm_state)
-               pm_runtime_get_sync(mcasp->dev);
-
-       for (i = 0; i < ARRAY_SIZE(context_regs); i++)
-               context->config_regs[i] = mcasp_get_reg(mcasp, context_regs[i]);
-
-       if (mcasp->txnumevt) {
-               reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
-               context->afifo_regs[0] = mcasp_get_reg(mcasp, reg);
-       }
-       if (mcasp->rxnumevt) {
-               reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
-               context->afifo_regs[1] = mcasp_get_reg(mcasp, reg);
-       }
-
-       for (i = 0; i < mcasp->num_serializer; i++)
-               context->xrsr_regs[i] = mcasp_get_reg(mcasp,
-                                               DAVINCI_MCASP_XRSRCTL_REG(i));
-
-       pm_runtime_put_sync(mcasp->dev);
-
-       return 0;
-}
-
-static int davinci_mcasp_resume(struct snd_soc_dai *dai)
-{
-       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
-       struct davinci_mcasp_context *context = &mcasp->context;
-       u32 reg;
-       int i;
-
-       pm_runtime_get_sync(mcasp->dev);
-
-       for (i = 0; i < ARRAY_SIZE(context_regs); i++)
-               mcasp_set_reg(mcasp, context_regs[i], context->config_regs[i]);
-
-       if (mcasp->txnumevt) {
-               reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
-               mcasp_set_reg(mcasp, reg, context->afifo_regs[0]);
-       }
-       if (mcasp->rxnumevt) {
-               reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
-               mcasp_set_reg(mcasp, reg, context->afifo_regs[1]);
-       }
-
-       for (i = 0; i < mcasp->num_serializer; i++)
-               mcasp_set_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
-                             context->xrsr_regs[i]);
-
-       if (!context->pm_state)
-               pm_runtime_put_sync(mcasp->dev);
-
-       return 0;
-}
-#else
-#define davinci_mcasp_suspend NULL
-#define davinci_mcasp_resume NULL
-#endif
-
 #define DAVINCI_MCASP_RATES    SNDRV_PCM_RATE_8000_192000
 
 #define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \
@@ -1571,8 +1503,6 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
        {
                .name           = "davinci-mcasp.0",
                .probe          = davinci_mcasp_dai_probe,
-               .suspend        = davinci_mcasp_suspend,
-               .resume         = davinci_mcasp_resume,
                .playback       = {
                        .channels_min   = 1,
                        .channels_max   = 32 * 16,
@@ -1976,7 +1906,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        }
 
        mcasp->num_serializer = pdata->num_serializer;
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
        mcasp->context.xrsr_regs = devm_kcalloc(&pdev->dev,
                                        mcasp->num_serializer, sizeof(u32),
                                        GFP_KERNEL);
@@ -2196,11 +2126,73 @@ static int davinci_mcasp_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int davinci_mcasp_runtime_suspend(struct device *dev)
+{
+       struct davinci_mcasp *mcasp = dev_get_drvdata(dev);
+       struct davinci_mcasp_context *context = &mcasp->context;
+       u32 reg;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(context_regs); i++)
+               context->config_regs[i] = mcasp_get_reg(mcasp, context_regs[i]);
+
+       if (mcasp->txnumevt) {
+               reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
+               context->afifo_regs[0] = mcasp_get_reg(mcasp, reg);
+       }
+       if (mcasp->rxnumevt) {
+               reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
+               context->afifo_regs[1] = mcasp_get_reg(mcasp, reg);
+       }
+
+       for (i = 0; i < mcasp->num_serializer; i++)
+               context->xrsr_regs[i] = mcasp_get_reg(mcasp,
+                                               DAVINCI_MCASP_XRSRCTL_REG(i));
+
+       return 0;
+}
+
+static int davinci_mcasp_runtime_resume(struct device *dev)
+{
+       struct davinci_mcasp *mcasp = dev_get_drvdata(dev);
+       struct davinci_mcasp_context *context = &mcasp->context;
+       u32 reg;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(context_regs); i++)
+               mcasp_set_reg(mcasp, context_regs[i], context->config_regs[i]);
+
+       if (mcasp->txnumevt) {
+               reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
+               mcasp_set_reg(mcasp, reg, context->afifo_regs[0]);
+       }
+       if (mcasp->rxnumevt) {
+               reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
+               mcasp_set_reg(mcasp, reg, context->afifo_regs[1]);
+       }
+
+       for (i = 0; i < mcasp->num_serializer; i++)
+               mcasp_set_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
+                             context->xrsr_regs[i]);
+
+       return 0;
+}
+
+#endif
+
+static const struct dev_pm_ops davinci_mcasp_pm_ops = {
+       SET_RUNTIME_PM_OPS(davinci_mcasp_runtime_suspend,
+                          davinci_mcasp_runtime_resume,
+                          NULL)
+};
+
 static struct platform_driver davinci_mcasp_driver = {
        .probe          = davinci_mcasp_probe,
        .remove         = davinci_mcasp_remove,
        .driver         = {
                .name   = "davinci-mcasp",
+               .pm     = &davinci_mcasp_pm_ops,
                .of_match_table = mcasp_dt_ids,
        },
 };
index 25e287f..723a583 100644 (file)
@@ -1,5 +1,5 @@
 config SND_SOC_XILINX_I2S
-       tristate "Audio support for the the Xilinx I2S"
+       tristate "Audio support for the Xilinx I2S"
        help
          Select this option to enable Xilinx I2S Audio. This enables
          I2S playback and capture using xilinx soft IP. In transmitter
index d4ae9ef..8b35316 100644 (file)
@@ -1,12 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0
-/*
- * Xilinx ASoC I2S audio support
- *
- * Copyright (C) 2018 Xilinx, Inc.
- *
- * Author: Praveen Vuppala <praveenv@xilinx.com>
- * Author: Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>
- */
+//
+// Xilinx ASoC I2S audio support
+//
+// Copyright (C) 2018 Xilinx, Inc.
+//
+// Author: Praveen Vuppala <praveenv@xilinx.com>
+// Author: Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>
 
 #include <linux/io.h>
 #include <linux/module.h>
index 7609ece..9e71d7c 100644 (file)
@@ -2541,8 +2541,8 @@ static int snd_dbri_create(struct snd_card *card,
        dbri->op = op;
        dbri->irq = irq;
 
-       dbri->dma = dma_zalloc_coherent(&op->dev, sizeof(struct dbri_dma),
-                                       &dbri->dma_dvma, GFP_KERNEL);
+       dbri->dma = dma_alloc_coherent(&op->dev, sizeof(struct dbri_dma),
+                                      &dbri->dma_dvma, GFP_KERNEL);
        if (!dbri->dma)
                return -ENOMEM;
 
index a105947..746a72e 100644 (file)
@@ -246,7 +246,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
                h1 = snd_usb_find_csint_desc(host_iface->extra,
                                                         host_iface->extralen,
                                                         NULL, UAC_HEADER);
-               if (!h1) {
+               if (!h1 || h1->bLength < sizeof(*h1)) {
                        dev_err(&dev->dev, "cannot find UAC_HEADER\n");
                        return -EINVAL;
                }
index c63c84b..e7d441d 100644 (file)
@@ -753,8 +753,9 @@ 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 < 11)
+       if (desc->bLength < sizeof(*desc))
                return -EINVAL;
        if (!desc->bNrInPins)
                return -EINVAL;
@@ -763,6 +764,8 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
        case UAC_VERSION_1:
        case UAC_VERSION_2:
        default:
+               if (desc->bLength < sizeof(*desc) + desc->bNrInPins + 1)
+                       return 0; /* no bmControls -> skip */
                mu_channels = uac_mixer_unit_bNrChannels(desc);
                break;
        case UAC_VERSION_3:
@@ -772,7 +775,11 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
        }
 
        if (!mu_channels)
-               return -EINVAL;
+               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;
 }
@@ -944,7 +951,7 @@ static int check_input_term(struct mixer_build *state, int id,
                                struct uac_mixer_unit_descriptor *d = p1;
 
                                err = uac_mixer_unit_get_channels(state, d);
-                               if (err < 0)
+                               if (err <= 0)
                                        return err;
 
                                term->channels = err;
@@ -2068,11 +2075,15 @@ static int parse_audio_input_terminal(struct mixer_build *state, int unitid,
 
        if (state->mixer->protocol == UAC_VERSION_2) {
                struct uac2_input_terminal_descriptor *d_v2 = raw_desc;
+               if (d_v2->bLength < sizeof(*d_v2))
+                       return -EINVAL;
                control = UAC2_TE_CONNECTOR;
                term_id = d_v2->bTerminalID;
                bmctls = le16_to_cpu(d_v2->bmControls);
        } else if (state->mixer->protocol == UAC_VERSION_3) {
                struct uac3_input_terminal_descriptor *d_v3 = raw_desc;
+               if (d_v3->bLength < sizeof(*d_v3))
+                       return -EINVAL;
                control = UAC3_TE_INSERTION;
                term_id = d_v3->bTerminalID;
                bmctls = le32_to_cpu(d_v3->bmControls);
@@ -2118,7 +2129,7 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
                if (err < 0)
                        continue;
                /* no bmControls field (e.g. Maya44) -> ignore */
-               if (desc->bLength <= 10 + input_pins)
+               if (!num_outs)
                        continue;
                err = check_input_term(state, desc->baSourceID[pin], &iterm);
                if (err < 0)
@@ -2314,7 +2325,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
                                char *name)
 {
        struct uac_processing_unit_descriptor *desc = raw_desc;
-       int num_ins = desc->bNrInPins;
+       int num_ins;
        struct usb_mixer_elem_info *cval;
        struct snd_kcontrol *kctl;
        int i, err, nameid, type, len;
@@ -2329,7 +2340,13 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
                0, NULL, default_value_info
        };
 
-       if (desc->bLength < 13 || desc->bLength < 13 + num_ins ||
+       if (desc->bLength < 13) {
+               usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid);
+               return -EINVAL;
+       }
+
+       num_ins = desc->bNrInPins;
+       if (desc->bLength < 13 + num_ins ||
            desc->bLength < num_ins + uac_processing_unit_bControlSize(desc, state->mixer->protocol)) {
                usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid);
                return -EINVAL;
index 3828471..db114f3 100644 (file)
@@ -314,6 +314,9 @@ static int search_roland_implicit_fb(struct usb_device *dev, int ifnum,
        return 0;
 }
 
+/* Setup an implicit feedback endpoint from a quirk. Returns 0 if no quirk
+ * applies. Returns 1 if a quirk was found.
+ */
 static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
                                         struct usb_device *dev,
                                         struct usb_interface_descriptor *altsd,
@@ -384,7 +387,7 @@ add_sync_ep:
 
        subs->data_endpoint->sync_master = subs->sync_endpoint;
 
-       return 0;
+       return 1;
 }
 
 static int set_sync_endpoint(struct snd_usb_substream *subs,
@@ -423,6 +426,10 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
        if (err < 0)
                return err;
 
+       /* endpoint set by quirk */
+       if (err > 0)
+               return 0;
+
        if (altsd->bNumEndpoints < 2)
                return 0;
 
index 37fc044..b345beb 100644 (file)
@@ -3326,6 +3326,9 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
                                        }
                                }
                        },
+                       {
+                               .ifnum = -1
+                       },
                }
        }
 },
@@ -3369,6 +3372,9 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
                                        }
                                }
                        },
+                       {
+                               .ifnum = -1
+                       },
                }
        }
 },
index 96340f2..7e65fe8 100644 (file)
@@ -768,7 +768,7 @@ static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
                 * REG1: PLL binary search enable, soft mute enable.
                 */
                CM6206_REG1_PLLBIN_EN |
-               CM6206_REG1_SOFT_MUTE_EN |
+               CM6206_REG1_SOFT_MUTE_EN,
                /*
                 * REG2: enable output drivers,
                 * select front channels to the headphone output,
@@ -1492,6 +1492,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
                        return SNDRV_PCM_FMTBIT_DSD_U32_BE;
                break;
 
+       case USB_ID(0x10cb, 0x0103): /* The Bit Opus #3; with fp->dsd_raw */
        case USB_ID(0x152a, 0x85de): /* SMSL D1 DAC */
        case USB_ID(0x16d0, 0x09dd): /* Encore mDSD */
        case USB_ID(0x0d8c, 0x0316): /* Hegel HD12 DSD */
@@ -1566,6 +1567,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
        case 0x20b1:  /* XMOS based devices */
        case 0x152a:  /* Thesycon devices */
        case 0x25ce:  /* Mytek devices */
+       case 0x2ab6:  /* T+A devices */
                if (fp->dsd_raw)
                        return SNDRV_PCM_FMTBIT_DSD_U32_BE;
                break;
index 67cf849..d9e3de4 100644 (file)
@@ -596,12 +596,8 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
                csep = snd_usb_find_desc(alts->extra, alts->extralen, NULL, USB_DT_CS_ENDPOINT);
 
        if (!csep || csep->bLength < 7 ||
-           csep->bDescriptorSubtype != UAC_EP_GENERAL) {
-               usb_audio_warn(chip,
-                              "%u:%d : no or invalid class specific endpoint descriptor\n",
-                              iface_no, altsd->bAlternateSetting);
-               return 0;
-       }
+           csep->bDescriptorSubtype != UAC_EP_GENERAL)
+               goto error;
 
        if (protocol == UAC_VERSION_1) {
                attributes = csep->bmAttributes;
@@ -609,6 +605,8 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
                struct uac2_iso_endpoint_descriptor *csep2 =
                        (struct uac2_iso_endpoint_descriptor *) csep;
 
+               if (csep2->bLength < sizeof(*csep2))
+                       goto error;
                attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX;
 
                /* emulate the endpoint attributes of a v1 device */
@@ -618,12 +616,20 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
                struct uac3_iso_endpoint_descriptor *csep3 =
                        (struct uac3_iso_endpoint_descriptor *) csep;
 
+               if (csep3->bLength < sizeof(*csep3))
+                       goto error;
                /* emulate the endpoint attributes of a v1 device */
                if (le32_to_cpu(csep3->bmControls) & UAC2_CONTROL_PITCH)
                        attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
        }
 
        return attributes;
+
+ error:
+       usb_audio_warn(chip,
+                      "%u:%d : no or invalid class specific endpoint descriptor\n",
+                      iface_no, altsd->bAlternateSetting);
+       return 0;
 }
 
 /* find an input terminal descriptor (either UAC1 or UAC2) with the given
@@ -631,13 +637,17 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
  */
 static void *
 snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
-                                              int terminal_id)
+                                      int terminal_id, bool uac23)
 {
        struct uac2_input_terminal_descriptor *term = NULL;
+       size_t minlen = uac23 ? sizeof(struct uac2_input_terminal_descriptor) :
+               sizeof(struct uac_input_terminal_descriptor);
 
        while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
                                               ctrl_iface->extralen,
                                               term, UAC_INPUT_TERMINAL))) {
+               if (term->bLength < minlen)
+                       continue;
                if (term->bTerminalID == terminal_id)
                        return term;
        }
@@ -655,7 +665,8 @@ snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface,
        while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
                                               ctrl_iface->extralen,
                                               term, UAC_OUTPUT_TERMINAL))) {
-               if (term->bTerminalID == terminal_id)
+               if (term->bLength >= sizeof(*term) &&
+                   term->bTerminalID == terminal_id)
                        return term;
        }
 
@@ -729,7 +740,8 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
                format = le16_to_cpu(as->wFormatTag); /* remember the format value */
 
                iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-                                                            as->bTerminalLink);
+                                                              as->bTerminalLink,
+                                                              false);
                if (iterm) {
                        num_channels = iterm->bNrChannels;
                        chconfig = le16_to_cpu(iterm->wChannelConfig);
@@ -764,7 +776,8 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
                 * to extract the clock
                 */
                input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-                                                                   as->bTerminalLink);
+                                                                   as->bTerminalLink,
+                                                                   true);
                if (input_term) {
                        clock = input_term->bCSourceID;
                        if (!chconfig && (num_channels == input_term->bNrChannels))
@@ -998,7 +1011,8 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
         * to extract the clock
         */
        input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-                                                           as->bTerminalLink);
+                                                           as->bTerminalLink,
+                                                           true);
        if (input_term) {
                clock = input_term->bCSourceID;
                goto found_clock;
index ff91192..f599064 100644 (file)
@@ -47,6 +47,7 @@ enum perf_event_powerpc_regs {
        PERF_REG_POWERPC_DAR,
        PERF_REG_POWERPC_DSISR,
        PERF_REG_POWERPC_SIER,
+       PERF_REG_POWERPC_MMCRA,
        PERF_REG_POWERPC_MAX,
 };
 #endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */
diff --git a/tools/arch/powerpc/include/uapi/asm/unistd.h b/tools/arch/powerpc/include/uapi/asm/unistd.h
deleted file mode 100644 (file)
index 985534d..0000000
+++ /dev/null
@@ -1,404 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
-/*
- * This file contains the system call numbers.
- *
- * 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.
- */
-#ifndef _UAPI_ASM_POWERPC_UNISTD_H_
-#define _UAPI_ASM_POWERPC_UNISTD_H_
-
-
-#define __NR_restart_syscall     0
-#define __NR_exit                1
-#define __NR_fork                2
-#define __NR_read                3
-#define __NR_write               4
-#define __NR_open                5
-#define __NR_close               6
-#define __NR_waitpid             7
-#define __NR_creat               8
-#define __NR_link                9
-#define __NR_unlink             10
-#define __NR_execve             11
-#define __NR_chdir              12
-#define __NR_time               13
-#define __NR_mknod              14
-#define __NR_chmod              15
-#define __NR_lchown             16
-#define __NR_break              17
-#define __NR_oldstat            18
-#define __NR_lseek              19
-#define __NR_getpid             20
-#define __NR_mount              21
-#define __NR_umount             22
-#define __NR_setuid             23
-#define __NR_getuid             24
-#define __NR_stime              25
-#define __NR_ptrace             26
-#define __NR_alarm              27
-#define __NR_oldfstat           28
-#define __NR_pause              29
-#define __NR_utime              30
-#define __NR_stty               31
-#define __NR_gtty               32
-#define __NR_access             33
-#define __NR_nice               34
-#define __NR_ftime              35
-#define __NR_sync               36
-#define __NR_kill               37
-#define __NR_rename             38
-#define __NR_mkdir              39
-#define __NR_rmdir              40
-#define __NR_dup                41
-#define __NR_pipe               42
-#define __NR_times              43
-#define __NR_prof               44
-#define __NR_brk                45
-#define __NR_setgid             46
-#define __NR_getgid             47
-#define __NR_signal             48
-#define __NR_geteuid            49
-#define __NR_getegid            50
-#define __NR_acct               51
-#define __NR_umount2            52
-#define __NR_lock               53
-#define __NR_ioctl              54
-#define __NR_fcntl              55
-#define __NR_mpx                56
-#define __NR_setpgid            57
-#define __NR_ulimit             58
-#define __NR_oldolduname        59
-#define __NR_umask              60
-#define __NR_chroot             61
-#define __NR_ustat              62
-#define __NR_dup2               63
-#define __NR_getppid            64
-#define __NR_getpgrp            65
-#define __NR_setsid             66
-#define __NR_sigaction          67
-#define __NR_sgetmask           68
-#define __NR_ssetmask           69
-#define __NR_setreuid           70
-#define __NR_setregid           71
-#define __NR_sigsuspend                 72
-#define __NR_sigpending                 73
-#define __NR_sethostname        74
-#define __NR_setrlimit          75
-#define __NR_getrlimit          76
-#define __NR_getrusage          77
-#define __NR_gettimeofday       78
-#define __NR_settimeofday       79
-#define __NR_getgroups          80
-#define __NR_setgroups          81
-#define __NR_select             82
-#define __NR_symlink            83
-#define __NR_oldlstat           84
-#define __NR_readlink           85
-#define __NR_uselib             86
-#define __NR_swapon             87
-#define __NR_reboot             88
-#define __NR_readdir            89
-#define __NR_mmap               90
-#define __NR_munmap             91
-#define __NR_truncate           92
-#define __NR_ftruncate          93
-#define __NR_fchmod             94
-#define __NR_fchown             95
-#define __NR_getpriority        96
-#define __NR_setpriority        97
-#define __NR_profil             98
-#define __NR_statfs             99
-#define __NR_fstatfs           100
-#define __NR_ioperm            101
-#define __NR_socketcall                102
-#define __NR_syslog            103
-#define __NR_setitimer         104
-#define __NR_getitimer         105
-#define __NR_stat              106
-#define __NR_lstat             107
-#define __NR_fstat             108
-#define __NR_olduname          109
-#define __NR_iopl              110
-#define __NR_vhangup           111
-#define __NR_idle              112
-#define __NR_vm86              113
-#define __NR_wait4             114
-#define __NR_swapoff           115
-#define __NR_sysinfo           116
-#define __NR_ipc               117
-#define __NR_fsync             118
-#define __NR_sigreturn         119
-#define __NR_clone             120
-#define __NR_setdomainname     121
-#define __NR_uname             122
-#define __NR_modify_ldt                123
-#define __NR_adjtimex          124
-#define __NR_mprotect          125
-#define __NR_sigprocmask       126
-#define __NR_create_module     127
-#define __NR_init_module       128
-#define __NR_delete_module     129
-#define __NR_get_kernel_syms   130
-#define __NR_quotactl          131
-#define __NR_getpgid           132
-#define __NR_fchdir            133
-#define __NR_bdflush           134
-#define __NR_sysfs             135
-#define __NR_personality       136
-#define __NR_afs_syscall       137 /* Syscall for Andrew File System */
-#define __NR_setfsuid          138
-#define __NR_setfsgid          139
-#define __NR__llseek           140
-#define __NR_getdents          141
-#define __NR__newselect                142
-#define __NR_flock             143
-#define __NR_msync             144
-#define __NR_readv             145
-#define __NR_writev            146
-#define __NR_getsid            147
-#define __NR_fdatasync         148
-#define __NR__sysctl           149
-#define __NR_mlock             150
-#define __NR_munlock           151
-#define __NR_mlockall          152
-#define __NR_munlockall                153
-#define __NR_sched_setparam            154
-#define __NR_sched_getparam            155
-#define __NR_sched_setscheduler                156
-#define __NR_sched_getscheduler                157
-#define __NR_sched_yield               158
-#define __NR_sched_get_priority_max    159
-#define __NR_sched_get_priority_min    160
-#define __NR_sched_rr_get_interval     161
-#define __NR_nanosleep         162
-#define __NR_mremap            163
-#define __NR_setresuid         164
-#define __NR_getresuid         165
-#define __NR_query_module      166
-#define __NR_poll              167
-#define __NR_nfsservctl                168
-#define __NR_setresgid         169
-#define __NR_getresgid         170
-#define __NR_prctl             171
-#define __NR_rt_sigreturn      172
-#define __NR_rt_sigaction      173
-#define __NR_rt_sigprocmask    174
-#define __NR_rt_sigpending     175
-#define __NR_rt_sigtimedwait   176
-#define __NR_rt_sigqueueinfo   177
-#define __NR_rt_sigsuspend     178
-#define __NR_pread64           179
-#define __NR_pwrite64          180
-#define __NR_chown             181
-#define __NR_getcwd            182
-#define __NR_capget            183
-#define __NR_capset            184
-#define __NR_sigaltstack       185
-#define __NR_sendfile          186
-#define __NR_getpmsg           187     /* some people actually want streams */
-#define __NR_putpmsg           188     /* some people actually want streams */
-#define __NR_vfork             189
-#define __NR_ugetrlimit                190     /* SuS compliant getrlimit */
-#define __NR_readahead         191
-#ifndef __powerpc64__                  /* these are 32-bit only */
-#define __NR_mmap2             192
-#define __NR_truncate64                193
-#define __NR_ftruncate64       194
-#define __NR_stat64            195
-#define __NR_lstat64           196
-#define __NR_fstat64           197
-#endif
-#define __NR_pciconfig_read    198
-#define __NR_pciconfig_write   199
-#define __NR_pciconfig_iobase  200
-#define __NR_multiplexer       201
-#define __NR_getdents64                202
-#define __NR_pivot_root                203
-#ifndef __powerpc64__
-#define __NR_fcntl64           204
-#endif
-#define __NR_madvise           205
-#define __NR_mincore           206
-#define __NR_gettid            207
-#define __NR_tkill             208
-#define __NR_setxattr          209
-#define __NR_lsetxattr         210
-#define __NR_fsetxattr         211
-#define __NR_getxattr          212
-#define __NR_lgetxattr         213
-#define __NR_fgetxattr         214
-#define __NR_listxattr         215
-#define __NR_llistxattr                216
-#define __NR_flistxattr                217
-#define __NR_removexattr       218
-#define __NR_lremovexattr      219
-#define __NR_fremovexattr      220
-#define __NR_futex             221
-#define __NR_sched_setaffinity 222
-#define __NR_sched_getaffinity 223
-/* 224 currently unused */
-#define __NR_tuxcall           225
-#ifndef __powerpc64__
-#define __NR_sendfile64                226
-#endif
-#define __NR_io_setup          227
-#define __NR_io_destroy                228
-#define __NR_io_getevents      229
-#define __NR_io_submit         230
-#define __NR_io_cancel         231
-#define __NR_set_tid_address   232
-#define __NR_fadvise64         233
-#define __NR_exit_group                234
-#define __NR_lookup_dcookie    235
-#define __NR_epoll_create      236
-#define __NR_epoll_ctl         237
-#define __NR_epoll_wait                238
-#define __NR_remap_file_pages  239
-#define __NR_timer_create      240
-#define __NR_timer_settime     241
-#define __NR_timer_gettime     242
-#define __NR_timer_getoverrun  243
-#define __NR_timer_delete      244
-#define __NR_clock_settime     245
-#define __NR_clock_gettime     246
-#define __NR_clock_getres      247
-#define __NR_clock_nanosleep   248
-#define __NR_swapcontext       249
-#define __NR_tgkill            250
-#define __NR_utimes            251
-#define __NR_statfs64          252
-#define __NR_fstatfs64         253
-#ifndef __powerpc64__
-#define __NR_fadvise64_64      254
-#endif
-#define __NR_rtas              255
-#define __NR_sys_debug_setcontext 256
-/* Number 257 is reserved for vserver */
-#define __NR_migrate_pages     258
-#define __NR_mbind             259
-#define __NR_get_mempolicy     260
-#define __NR_set_mempolicy     261
-#define __NR_mq_open           262
-#define __NR_mq_unlink         263
-#define __NR_mq_timedsend      264
-#define __NR_mq_timedreceive   265
-#define __NR_mq_notify         266
-#define __NR_mq_getsetattr     267
-#define __NR_kexec_load                268
-#define __NR_add_key           269
-#define __NR_request_key       270
-#define __NR_keyctl            271
-#define __NR_waitid            272
-#define __NR_ioprio_set                273
-#define __NR_ioprio_get                274
-#define __NR_inotify_init      275
-#define __NR_inotify_add_watch 276
-#define __NR_inotify_rm_watch  277
-#define __NR_spu_run           278
-#define __NR_spu_create                279
-#define __NR_pselect6          280
-#define __NR_ppoll             281
-#define __NR_unshare           282
-#define __NR_splice            283
-#define __NR_tee               284
-#define __NR_vmsplice          285
-#define __NR_openat            286
-#define __NR_mkdirat           287
-#define __NR_mknodat           288
-#define __NR_fchownat          289
-#define __NR_futimesat         290
-#ifdef __powerpc64__
-#define __NR_newfstatat                291
-#else
-#define __NR_fstatat64         291
-#endif
-#define __NR_unlinkat          292
-#define __NR_renameat          293
-#define __NR_linkat            294
-#define __NR_symlinkat         295
-#define __NR_readlinkat                296
-#define __NR_fchmodat          297
-#define __NR_faccessat         298
-#define __NR_get_robust_list   299
-#define __NR_set_robust_list   300
-#define __NR_move_pages                301
-#define __NR_getcpu            302
-#define __NR_epoll_pwait       303
-#define __NR_utimensat         304
-#define __NR_signalfd          305
-#define __NR_timerfd_create    306
-#define __NR_eventfd           307
-#define __NR_sync_file_range2  308
-#define __NR_fallocate         309
-#define __NR_subpage_prot      310
-#define __NR_timerfd_settime   311
-#define __NR_timerfd_gettime   312
-#define __NR_signalfd4         313
-#define __NR_eventfd2          314
-#define __NR_epoll_create1     315
-#define __NR_dup3              316
-#define __NR_pipe2             317
-#define __NR_inotify_init1     318
-#define __NR_perf_event_open   319
-#define __NR_preadv            320
-#define __NR_pwritev           321
-#define __NR_rt_tgsigqueueinfo 322
-#define __NR_fanotify_init     323
-#define __NR_fanotify_mark     324
-#define __NR_prlimit64         325
-#define __NR_socket            326
-#define __NR_bind              327
-#define __NR_connect           328
-#define __NR_listen            329
-#define __NR_accept            330
-#define __NR_getsockname       331
-#define __NR_getpeername       332
-#define __NR_socketpair                333
-#define __NR_send              334
-#define __NR_sendto            335
-#define __NR_recv              336
-#define __NR_recvfrom          337
-#define __NR_shutdown          338
-#define __NR_setsockopt                339
-#define __NR_getsockopt                340
-#define __NR_sendmsg           341
-#define __NR_recvmsg           342
-#define __NR_recvmmsg          343
-#define __NR_accept4           344
-#define __NR_name_to_handle_at 345
-#define __NR_open_by_handle_at 346
-#define __NR_clock_adjtime     347
-#define __NR_syncfs            348
-#define __NR_sendmmsg          349
-#define __NR_setns             350
-#define __NR_process_vm_readv  351
-#define __NR_process_vm_writev 352
-#define __NR_finit_module      353
-#define __NR_kcmp              354
-#define __NR_sched_setattr     355
-#define __NR_sched_getattr     356
-#define __NR_renameat2         357
-#define __NR_seccomp           358
-#define __NR_getrandom         359
-#define __NR_memfd_create      360
-#define __NR_bpf               361
-#define __NR_execveat          362
-#define __NR_switch_endian     363
-#define __NR_userfaultfd       364
-#define __NR_membarrier                365
-#define __NR_mlock2            378
-#define __NR_copy_file_range   379
-#define __NR_preadv2           380
-#define __NR_pwritev2          381
-#define __NR_kexec_file_load   382
-#define __NR_statx             383
-#define __NR_pkey_alloc                384
-#define __NR_pkey_free         385
-#define __NR_pkey_mprotect     386
-#define __NR_rseq              387
-#define __NR_io_pgetevents     388
-
-#endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
diff --git a/tools/arch/riscv/include/uapi/asm/bitsperlong.h b/tools/arch/riscv/include/uapi/asm/bitsperlong.h
new file mode 100644 (file)
index 0000000..0b3cb52
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 2015 Regents of the University of California
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.  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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _UAPI_ASM_RISCV_BITSPERLONG_H
+#define _UAPI_ASM_RISCV_BITSPERLONG_H
+
+#define __BITS_PER_LONG (__SIZEOF_POINTER__ * 8)
+
+#include <asm-generic/bitsperlong.h>
+
+#endif /* _UAPI_ASM_RISCV_BITSPERLONG_H */
index 28c4a50..6d61225 100644 (file)
 #define X86_FEATURE_CLZERO             (13*32+ 0) /* CLZERO instruction */
 #define X86_FEATURE_IRPERF             (13*32+ 1) /* Instructions Retired Count */
 #define X86_FEATURE_XSAVEERPTR         (13*32+ 2) /* Always save/restore FP error pointers */
+#define X86_FEATURE_WBNOINVD           (13*32+ 9) /* WBNOINVD instruction */
 #define X86_FEATURE_AMD_IBPB           (13*32+12) /* "" Indirect Branch Prediction Barrier */
 #define X86_FEATURE_AMD_IBRS           (13*32+14) /* "" Indirect Branch Restricted Speculation */
 #define X86_FEATURE_AMD_STIBP          (13*32+15) /* "" Single Thread Indirect Branch Predictors */
+#define X86_FEATURE_AMD_STIBP_ALWAYS_ON        (13*32+17) /* "" Single Thread Indirect Branch Predictors always-on preferred */
 #define X86_FEATURE_AMD_SSBD           (13*32+24) /* "" Speculative Store Bypass Disable */
 #define X86_FEATURE_VIRT_SSBD          (13*32+25) /* Virtualized Speculative Store Bypass Disable */
 #define X86_FEATURE_AMD_SSB_NO         (13*32+26) /* "" Speculative Store Bypass is fixed in hardware. */
index 33833d1..a5ea841 100644 (file)
 # define DISABLE_MPX   (1<<(X86_FEATURE_MPX & 31))
 #endif
 
+#ifdef CONFIG_X86_SMAP
+# define DISABLE_SMAP  0
+#else
+# define DISABLE_SMAP  (1<<(X86_FEATURE_SMAP & 31))
+#endif
+
 #ifdef CONFIG_X86_INTEL_UMIP
 # define DISABLE_UMIP  0
 #else
@@ -68,7 +74,7 @@
 #define DISABLED_MASK6 0
 #define DISABLED_MASK7 (DISABLE_PTI)
 #define DISABLED_MASK8 0
-#define DISABLED_MASK9 (DISABLE_MPX)
+#define DISABLED_MASK9 (DISABLE_MPX|DISABLE_SMAP)
 #define DISABLED_MASK10        0
 #define DISABLED_MASK11        0
 #define DISABLED_MASK12        0
index 492f0f2..4ad1f08 100644 (file)
@@ -93,9 +93,16 @@ BFD_SRCS = jit_disasm.c
 SRCS = $(filter-out $(BFD_SRCS),$(wildcard *.c))
 
 ifeq ($(feature-libbfd),1)
+  LIBS += -lbfd -ldl -lopcodes
+else ifeq ($(feature-libbfd-liberty),1)
+  LIBS += -lbfd -ldl -lopcodes -liberty
+else ifeq ($(feature-libbfd-liberty-z),1)
+  LIBS += -lbfd -ldl -lopcodes -liberty -lz
+endif
+
+ifneq ($(filter -lbfd,$(LIBS)),)
 CFLAGS += -DHAVE_LIBBFD_SUPPORT
 SRCS += $(BFD_SRCS)
-LIBS += -lbfd -lopcodes
 endif
 
 OBJS = $(patsubst %.c,$(OUTPUT)%.o,$(SRCS)) $(OUTPUT)disasm.o
index 3f0629e..6ba5f56 100644 (file)
@@ -82,8 +82,6 @@ static void btf_dumper_bitfield(__u32 nr_bits, __u8 bit_offset,
        int bits_to_copy;
        __u64 print_num;
 
-       data += BITS_ROUNDDOWN_BYTES(bit_offset);
-       bit_offset = BITS_PER_BYTE_MASKED(bit_offset);
        bits_to_copy = bit_offset + nr_bits;
        bytes_to_copy = BITS_ROUNDUP_BYTES(bits_to_copy);
 
@@ -118,7 +116,9 @@ static void btf_dumper_int_bits(__u32 int_type, __u8 bit_offset,
         * BTF_INT_OFFSET() cannot exceed 64 bits.
         */
        total_bits_offset = bit_offset + BTF_INT_OFFSET(int_type);
-       btf_dumper_bitfield(nr_bits, total_bits_offset, data, jw,
+       data += BITS_ROUNDDOWN_BYTES(total_bits_offset);
+       bit_offset = BITS_PER_BYTE_MASKED(total_bits_offset);
+       btf_dumper_bitfield(nr_bits, bit_offset, data, jw,
                            is_plain_text);
 }
 
@@ -216,11 +216,12 @@ static int btf_dumper_struct(const struct btf_dumper *d, __u32 type_id,
                }
 
                jsonw_name(d->jw, btf__name_by_offset(d->btf, m[i].name_off));
+               data_off = data + BITS_ROUNDDOWN_BYTES(bit_offset);
                if (bitfield_size) {
-                       btf_dumper_bitfield(bitfield_size, bit_offset,
-                                           data, d->jw, d->is_plain_text);
+                       btf_dumper_bitfield(bitfield_size,
+                                           BITS_PER_BYTE_MASKED(bit_offset),
+                                           data_off, d->jw, d->is_plain_text);
                } else {
-                       data_off = data + BITS_ROUNDDOWN_BYTES(bit_offset);
                        ret = btf_dumper_do_type(d, m[i].type,
                                                 BITS_PER_BYTE_MASKED(bit_offset),
                                                 data_off);
index 8974834..f7261fa 100644 (file)
@@ -297,10 +297,8 @@ char *get_fdinfo(int fd, const char *key)
        snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", fd);
 
        fdi = fopen(path, "r");
-       if (!fdi) {
-               p_err("can't open fdinfo: %s", strerror(errno));
+       if (!fdi)
                return NULL;
-       }
 
        while ((n = getline(&line, &line_n, fdi)) > 0) {
                char *value;
@@ -313,7 +311,6 @@ char *get_fdinfo(int fd, const char *key)
 
                value = strchr(line, '\t');
                if (!value || !value[1]) {
-                       p_err("malformed fdinfo!?");
                        free(line);
                        return NULL;
                }
@@ -326,7 +323,6 @@ char *get_fdinfo(int fd, const char *key)
                return line;
        }
 
-       p_err("key '%s' not found in fdinfo", key);
        free(line);
        fclose(fdi);
        return NULL;
index bff7ee0..6046dca 100644 (file)
@@ -1,15 +1,10 @@
-// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * Simple streaming JSON writer
  *
  * This takes care of the annoying bits of JSON syntax like the commas
  * after elements
  *
- * 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.
- *
  * Authors:    Stephen Hemminger <stephen@networkplumber.org>
  */
 
index c1ab51a..cb9a199 100644 (file)
@@ -5,11 +5,6 @@
  * This takes care of the annoying bits of JSON syntax like the commas
  * after elements
  *
- * 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.
- *
  * Authors:    Stephen Hemminger <stephen@networkplumber.org>
  */
 
index 2037e3d..1ef1ee2 100644 (file)
@@ -347,6 +347,20 @@ static char **parse_bytes(char **argv, const char *name, unsigned char *val,
        return argv + i;
 }
 
+/* on per cpu maps we must copy the provided value on all value instances */
+static void fill_per_cpu_value(struct bpf_map_info *info, void *value)
+{
+       unsigned int i, n, step;
+
+       if (!map_is_per_cpu(info->type))
+               return;
+
+       n = get_possible_cpus();
+       step = round_up(info->value_size, 8);
+       for (i = 1; i < n; i++)
+               memcpy(value + i * step, value, info->value_size);
+}
+
 static int parse_elem(char **argv, struct bpf_map_info *info,
                      void *key, void *value, __u32 key_size, __u32 value_size,
                      __u32 *flags, __u32 **value_fd)
@@ -426,6 +440,8 @@ static int parse_elem(char **argv, struct bpf_map_info *info,
                        argv = parse_bytes(argv, "value", value, value_size);
                        if (!argv)
                                return -1;
+
+                       fill_per_cpu_value(info, value);
                }
 
                return parse_elem(argv, info, key, NULL, key_size, value_size,
@@ -497,10 +513,9 @@ static int show_map_close_json(int fd, struct bpf_map_info *info)
                                jsonw_uint_field(json_wtr, "owner_prog_type",
                                                 prog_type);
                }
-               if (atoi(owner_jited))
-                       jsonw_bool_field(json_wtr, "owner_jited", true);
-               else
-                       jsonw_bool_field(json_wtr, "owner_jited", false);
+               if (owner_jited)
+                       jsonw_bool_field(json_wtr, "owner_jited",
+                                        !!atoi(owner_jited));
 
                free(owner_prog_type);
                free(owner_jited);
@@ -553,7 +568,8 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info)
                char *owner_prog_type = get_fdinfo(fd, "owner_prog_type");
                char *owner_jited = get_fdinfo(fd, "owner_jited");
 
-               printf("\n\t");
+               if (owner_prog_type || owner_jited)
+                       printf("\n\t");
                if (owner_prog_type) {
                        unsigned int prog_type = atoi(owner_prog_type);
 
@@ -563,10 +579,9 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info)
                        else
                                printf("owner_prog_type %d  ", prog_type);
                }
-               if (atoi(owner_jited))
-                       printf("owner jited");
-               else
-                       printf("owner not jited");
+               if (owner_jited)
+                       printf("owner%s jited",
+                              atoi(owner_jited) ? "" : " not");
 
                free(owner_prog_type);
                free(owner_jited);
index 2d1bb7d..b54ed82 100644 (file)
@@ -78,13 +78,14 @@ static void print_boot_time(__u64 nsecs, char *buf, unsigned int size)
 
 static int prog_fd_by_tag(unsigned char *tag)
 {
-       struct bpf_prog_info info = {};
-       __u32 len = sizeof(info);
        unsigned int id = 0;
        int err;
        int fd;
 
        while (true) {
+               struct bpf_prog_info info = {};
+               __u32 len = sizeof(info);
+
                err = bpf_prog_get_next_id(id, &id);
                if (err) {
                        p_err("%s", strerror(errno));
index 3040830..8454566 100644 (file)
@@ -330,7 +330,7 @@ static const struct option longopts[] = {
 
 int main(int argc, char **argv)
 {
-       unsigned long long num_loops = 2;
+       long long num_loops = 2;
        unsigned long timedelay = 1000000;
        unsigned long buf_len = 128;
 
index c7f3321..d901272 100644 (file)
@@ -738,9 +738,11 @@ __SYSCALL(__NR_statx,     sys_statx)
 __SC_COMP(__NR_io_pgetevents, sys_io_pgetevents, compat_sys_io_pgetevents)
 #define __NR_rseq 293
 __SYSCALL(__NR_rseq, sys_rseq)
+#define __NR_kexec_file_load 294
+__SYSCALL(__NR_kexec_file_load,     sys_kexec_file_load)
 
 #undef __NR_syscalls
-#define __NR_syscalls 294
+#define __NR_syscalls 295
 
 /*
  * 32 bit systems traditionally used different
index 8dd6aef..57aaeaf 100644 (file)
 #include "../../arch/mips/include/uapi/asm/bitsperlong.h"
 #elif defined(__ia64__)
 #include "../../arch/ia64/include/uapi/asm/bitsperlong.h"
+#elif defined(__riscv)
+#include "../../arch/riscv/include/uapi/asm/bitsperlong.h"
+#elif defined(__alpha__)
+#include "../../arch/alpha/include/uapi/asm/bitsperlong.h"
 #else
 #include <asm-generic/bitsperlong.h>
 #endif
index a4446f4..298b2e1 100644 (file)
@@ -412,6 +412,14 @@ typedef struct drm_i915_irq_wait {
        int irq_seq;
 } drm_i915_irq_wait_t;
 
+/*
+ * Different modes of per-process Graphics Translation Table,
+ * see I915_PARAM_HAS_ALIASING_PPGTT
+ */
+#define I915_GEM_PPGTT_NONE    0
+#define I915_GEM_PPGTT_ALIASING        1
+#define I915_GEM_PPGTT_FULL    2
+
 /* Ioctl to query kernel params:
  */
 #define I915_PARAM_IRQ_ACTIVE            1
index a441ea1..121e82c 100644 (file)
 #include <linux/ioctl.h>
 #include <linux/types.h>
 
+/* Use of MS_* flags within the kernel is restricted to core mount(2) code. */
+#if !defined(__KERNEL__)
+#include <linux/mount.h>
+#endif
+
 /*
  * It's silly to have NR_OPEN bigger than NR_FILE, but you can change
  * the file limit at runtime and only root can increase the per-process
@@ -101,57 +106,6 @@ struct inodes_stat_t {
 
 #define NR_FILE  8192  /* this can well be larger on a larger system */
 
-
-/*
- * These are the fs-independent mount-flags: up to 32 flags are supported
- */
-#define MS_RDONLY       1      /* Mount read-only */
-#define MS_NOSUID       2      /* Ignore suid and sgid bits */
-#define MS_NODEV        4      /* Disallow access to device special files */
-#define MS_NOEXEC       8      /* Disallow program execution */
-#define MS_SYNCHRONOUS 16      /* Writes are synced at once */
-#define MS_REMOUNT     32      /* Alter flags of a mounted FS */
-#define MS_MANDLOCK    64      /* Allow mandatory locks on an FS */
-#define MS_DIRSYNC     128     /* Directory modifications are synchronous */
-#define MS_NOATIME     1024    /* Do not update access times. */
-#define MS_NODIRATIME  2048    /* Do not update directory access times */
-#define MS_BIND                4096
-#define MS_MOVE                8192
-#define MS_REC         16384
-#define MS_VERBOSE     32768   /* War is peace. Verbosity is silence.
-                                  MS_VERBOSE is deprecated. */
-#define MS_SILENT      32768
-#define MS_POSIXACL    (1<<16) /* VFS does not apply the umask */
-#define MS_UNBINDABLE  (1<<17) /* change to unbindable */
-#define MS_PRIVATE     (1<<18) /* change to private */
-#define MS_SLAVE       (1<<19) /* change to slave */
-#define MS_SHARED      (1<<20) /* change to shared */
-#define MS_RELATIME    (1<<21) /* Update atime relative to mtime/ctime. */
-#define MS_KERNMOUNT   (1<<22) /* this is a kern_mount call */
-#define MS_I_VERSION   (1<<23) /* Update inode I_version field */
-#define MS_STRICTATIME (1<<24) /* Always perform atime updates */
-#define MS_LAZYTIME    (1<<25) /* Update the on-disk [acm]times lazily */
-
-/* These sb flags are internal to the kernel */
-#define MS_SUBMOUNT     (1<<26)
-#define MS_NOREMOTELOCK        (1<<27)
-#define MS_NOSEC       (1<<28)
-#define MS_BORN                (1<<29)
-#define MS_ACTIVE      (1<<30)
-#define MS_NOUSER      (1<<31)
-
-/*
- * Superblock flags that can be altered by MS_REMOUNT
- */
-#define MS_RMT_MASK    (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION|\
-                        MS_LAZYTIME)
-
-/*
- * Old magic mount flag and mask
- */
-#define MS_MGC_VAL 0xC0ED0000
-#define MS_MGC_MSK 0xffff0000
-
 /*
  * Structure for FS_IOC_FSGETXATTR[A] and FS_IOC_FSSETXATTR.
  */
@@ -269,7 +223,8 @@ struct fsxattr {
 #define FS_POLICY_FLAGS_PAD_16         0x02
 #define FS_POLICY_FLAGS_PAD_32         0x03
 #define FS_POLICY_FLAGS_PAD_MASK       0x03
-#define FS_POLICY_FLAGS_VALID          0x03
+#define FS_POLICY_FLAG_DIRECT_KEY      0x04    /* use master key directly */
+#define FS_POLICY_FLAGS_VALID          0x07
 
 /* Encryption algorithms */
 #define FS_ENCRYPTION_MODE_INVALID             0
@@ -281,6 +236,7 @@ struct fsxattr {
 #define FS_ENCRYPTION_MODE_AES_128_CTS         6
 #define FS_ENCRYPTION_MODE_SPECK128_256_XTS    7 /* Removed, do not use. */
 #define FS_ENCRYPTION_MODE_SPECK128_256_CTS    8 /* Removed, do not use. */
+#define FS_ENCRYPTION_MODE_ADIANTUM            9
 
 struct fscrypt_policy {
        __u8 version;
index 1debfa4..d653382 100644 (file)
@@ -288,6 +288,7 @@ enum {
        IFLA_BR_MCAST_IGMP_VERSION,
        IFLA_BR_MCAST_MLD_VERSION,
        IFLA_BR_VLAN_STATS_PER_PORT,
+       IFLA_BR_MULTI_BOOLOPT,
        __IFLA_BR_MAX,
 };
 
@@ -533,6 +534,7 @@ enum {
        IFLA_VXLAN_LABEL,
        IFLA_VXLAN_GPE,
        IFLA_VXLAN_TTL_INHERIT,
+       IFLA_VXLAN_DF,
        __IFLA_VXLAN_MAX
 };
 #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
@@ -542,6 +544,14 @@ struct ifla_vxlan_port_range {
        __be16  high;
 };
 
+enum ifla_vxlan_df {
+       VXLAN_DF_UNSET = 0,
+       VXLAN_DF_SET,
+       VXLAN_DF_INHERIT,
+       __VXLAN_DF_END,
+       VXLAN_DF_MAX = __VXLAN_DF_END - 1,
+};
+
 /* GENEVE section */
 enum {
        IFLA_GENEVE_UNSPEC,
@@ -557,10 +567,19 @@ enum {
        IFLA_GENEVE_UDP_ZERO_CSUM6_RX,
        IFLA_GENEVE_LABEL,
        IFLA_GENEVE_TTL_INHERIT,
+       IFLA_GENEVE_DF,
        __IFLA_GENEVE_MAX
 };
 #define IFLA_GENEVE_MAX        (__IFLA_GENEVE_MAX - 1)
 
+enum ifla_geneve_df {
+       GENEVE_DF_UNSET = 0,
+       GENEVE_DF_SET,
+       GENEVE_DF_INHERIT,
+       __GENEVE_DF_END,
+       GENEVE_DF_MAX = __GENEVE_DF_END - 1,
+};
+
 /* PPP section */
 enum {
        IFLA_PPP_UNSPEC,
index 48e8a22..a55cb8b 100644 (file)
@@ -266,10 +266,14 @@ struct sockaddr_in {
 
 #define        IN_CLASSD(a)            ((((long int) (a)) & 0xf0000000) == 0xe0000000)
 #define        IN_MULTICAST(a)         IN_CLASSD(a)
-#define IN_MULTICAST_NET       0xF0000000
+#define        IN_MULTICAST_NET        0xe0000000
 
-#define        IN_EXPERIMENTAL(a)      ((((long int) (a)) & 0xf0000000) == 0xf0000000)
-#define        IN_BADCLASS(a)          IN_EXPERIMENTAL((a))
+#define        IN_BADCLASS(a)          (((long int) (a) ) == (long int)0xffffffff)
+#define        IN_EXPERIMENTAL(a)      IN_BADCLASS((a))
+
+#define        IN_CLASSE(a)            ((((long int) (a)) & 0xf0000000) == 0xf0000000)
+#define        IN_CLASSE_NET           0xffffffff
+#define        IN_CLASSE_NSHIFT        0
 
 /* Address to accept any incoming messages. */
 #define        INADDR_ANY              ((unsigned long int) 0x00000000)
index 2b7a652..6d4ea4b 100644 (file)
@@ -492,6 +492,17 @@ struct kvm_dirty_log {
        };
 };
 
+/* 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 padding2;
+       };
+};
+
 /* for KVM_SET_SIGNAL_MASK */
 struct kvm_signal_mask {
        __u32 len;
@@ -975,6 +986,8 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_HYPERV_ENLIGHTENED_VMCS 163
 #define KVM_CAP_EXCEPTION_PAYLOAD 164
 #define KVM_CAP_ARM_VM_IPA_SIZE 165
+#define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT 166
+#define KVM_CAP_HYPERV_CPUID 167
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1421,6 +1434,12 @@ struct kvm_enc_region {
 #define KVM_GET_NESTED_STATE         _IOWR(KVMIO, 0xbe, struct kvm_nested_state)
 #define KVM_SET_NESTED_STATE         _IOW(KVMIO,  0xbf, struct kvm_nested_state)
 
+/* Available with KVM_CAP_MANUAL_DIRTY_LOG_PROTECT */
+#define KVM_CLEAR_DIRTY_LOG          _IOWR(KVMIO, 0xc0, struct kvm_clear_dirty_log)
+
+/* Available with KVM_CAP_HYPERV_CPUID */
+#define KVM_GET_SUPPORTED_HV_CPUID _IOWR(KVMIO, 0xc1, struct kvm_cpuid2)
+
 /* Secure Encrypted Virtualization command */
 enum sev_cmd_id {
        /* Guest initialization commands */
diff --git a/tools/include/uapi/linux/mount.h b/tools/include/uapi/linux/mount.h
new file mode 100644 (file)
index 0000000..3f9ec42
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef _UAPI_LINUX_MOUNT_H
+#define _UAPI_LINUX_MOUNT_H
+
+/*
+ * These are the fs-independent mount-flags: up to 32 flags are supported
+ *
+ * Usage of these is restricted within the kernel to core mount(2) code and
+ * callers of sys_mount() only.  Filesystems should be using the SB_*
+ * equivalent instead.
+ */
+#define MS_RDONLY       1      /* Mount read-only */
+#define MS_NOSUID       2      /* Ignore suid and sgid bits */
+#define MS_NODEV        4      /* Disallow access to device special files */
+#define MS_NOEXEC       8      /* Disallow program execution */
+#define MS_SYNCHRONOUS 16      /* Writes are synced at once */
+#define MS_REMOUNT     32      /* Alter flags of a mounted FS */
+#define MS_MANDLOCK    64      /* Allow mandatory locks on an FS */
+#define MS_DIRSYNC     128     /* Directory modifications are synchronous */
+#define MS_NOATIME     1024    /* Do not update access times. */
+#define MS_NODIRATIME  2048    /* Do not update directory access times */
+#define MS_BIND                4096
+#define MS_MOVE                8192
+#define MS_REC         16384
+#define MS_VERBOSE     32768   /* War is peace. Verbosity is silence.
+                                  MS_VERBOSE is deprecated. */
+#define MS_SILENT      32768
+#define MS_POSIXACL    (1<<16) /* VFS does not apply the umask */
+#define MS_UNBINDABLE  (1<<17) /* change to unbindable */
+#define MS_PRIVATE     (1<<18) /* change to private */
+#define MS_SLAVE       (1<<19) /* change to slave */
+#define MS_SHARED      (1<<20) /* change to shared */
+#define MS_RELATIME    (1<<21) /* Update atime relative to mtime/ctime. */
+#define MS_KERNMOUNT   (1<<22) /* this is a kern_mount call */
+#define MS_I_VERSION   (1<<23) /* Update inode I_version field */
+#define MS_STRICTATIME (1<<24) /* Always perform atime updates */
+#define MS_LAZYTIME    (1<<25) /* Update the on-disk [acm]times lazily */
+
+/* These sb flags are internal to the kernel */
+#define MS_SUBMOUNT     (1<<26)
+#define MS_NOREMOTELOCK        (1<<27)
+#define MS_NOSEC       (1<<28)
+#define MS_BORN                (1<<29)
+#define MS_ACTIVE      (1<<30)
+#define MS_NOUSER      (1<<31)
+
+/*
+ * Superblock flags that can be altered by MS_REMOUNT
+ */
+#define MS_RMT_MASK    (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION|\
+                        MS_LAZYTIME)
+
+/*
+ * Old magic mount flag and mask
+ */
+#define MS_MGC_VAL 0xC0ED0000
+#define MS_MGC_MSK 0xffff0000
+
+#endif /* _UAPI_LINUX_MOUNT_H */
diff --git a/tools/include/uapi/linux/pkt_sched.h b/tools/include/uapi/linux/pkt_sched.h
new file mode 100644 (file)
index 0000000..0d18b1d
--- /dev/null
@@ -0,0 +1,1163 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_PKT_SCHED_H
+#define __LINUX_PKT_SCHED_H
+
+#include <linux/types.h>
+
+/* Logical priority bands not depending on specific packet scheduler.
+   Every scheduler will map them to real traffic classes, if it has
+   no more precise mechanism to classify packets.
+
+   These numbers have no special meaning, though their coincidence
+   with obsolete IPv6 values is not occasional :-). New IPv6 drafts
+   preferred full anarchy inspired by diffserv group.
+
+   Note: TC_PRIO_BESTEFFORT does not mean that it is the most unhappy
+   class, actually, as rule it will be handled with more care than
+   filler or even bulk.
+ */
+
+#define TC_PRIO_BESTEFFORT             0
+#define TC_PRIO_FILLER                 1
+#define TC_PRIO_BULK                   2
+#define TC_PRIO_INTERACTIVE_BULK       4
+#define TC_PRIO_INTERACTIVE            6
+#define TC_PRIO_CONTROL                        7
+
+#define TC_PRIO_MAX                    15
+
+/* Generic queue statistics, available for all the elements.
+   Particular schedulers may have also their private records.
+ */
+
+struct tc_stats {
+       __u64   bytes;                  /* Number of enqueued bytes */
+       __u32   packets;                /* Number of enqueued packets   */
+       __u32   drops;                  /* Packets dropped because of lack of resources */
+       __u32   overlimits;             /* Number of throttle events when this
+                                        * flow goes out of allocated bandwidth */
+       __u32   bps;                    /* Current flow byte rate */
+       __u32   pps;                    /* Current flow packet rate */
+       __u32   qlen;
+       __u32   backlog;
+};
+
+struct tc_estimator {
+       signed char     interval;
+       unsigned char   ewma_log;
+};
+
+/* "Handles"
+   ---------
+
+    All the traffic control objects have 32bit identifiers, or "handles".
+
+    They can be considered as opaque numbers from user API viewpoint,
+    but actually they always consist of two fields: major and
+    minor numbers, which are interpreted by kernel specially,
+    that may be used by applications, though not recommended.
+
+    F.e. qdisc handles always have minor number equal to zero,
+    classes (or flows) have major equal to parent qdisc major, and
+    minor uniquely identifying class inside qdisc.
+
+    Macros to manipulate handles:
+ */
+
+#define TC_H_MAJ_MASK (0xFFFF0000U)
+#define TC_H_MIN_MASK (0x0000FFFFU)
+#define TC_H_MAJ(h) ((h)&TC_H_MAJ_MASK)
+#define TC_H_MIN(h) ((h)&TC_H_MIN_MASK)
+#define TC_H_MAKE(maj,min) (((maj)&TC_H_MAJ_MASK)|((min)&TC_H_MIN_MASK))
+
+#define TC_H_UNSPEC    (0U)
+#define TC_H_ROOT      (0xFFFFFFFFU)
+#define TC_H_INGRESS    (0xFFFFFFF1U)
+#define TC_H_CLSACT    TC_H_INGRESS
+
+#define TC_H_MIN_PRIORITY      0xFFE0U
+#define TC_H_MIN_INGRESS       0xFFF2U
+#define TC_H_MIN_EGRESS                0xFFF3U
+
+/* Need to corrospond to iproute2 tc/tc_core.h "enum link_layer" */
+enum tc_link_layer {
+       TC_LINKLAYER_UNAWARE, /* Indicate unaware old iproute2 util */
+       TC_LINKLAYER_ETHERNET,
+       TC_LINKLAYER_ATM,
+};
+#define TC_LINKLAYER_MASK 0x0F /* limit use to lower 4 bits */
+
+struct tc_ratespec {
+       unsigned char   cell_log;
+       __u8            linklayer; /* lower 4 bits */
+       unsigned short  overhead;
+       short           cell_align;
+       unsigned short  mpu;
+       __u32           rate;
+};
+
+#define TC_RTAB_SIZE   1024
+
+struct tc_sizespec {
+       unsigned char   cell_log;
+       unsigned char   size_log;
+       short           cell_align;
+       int             overhead;
+       unsigned int    linklayer;
+       unsigned int    mpu;
+       unsigned int    mtu;
+       unsigned int    tsize;
+};
+
+enum {
+       TCA_STAB_UNSPEC,
+       TCA_STAB_BASE,
+       TCA_STAB_DATA,
+       __TCA_STAB_MAX
+};
+
+#define TCA_STAB_MAX (__TCA_STAB_MAX - 1)
+
+/* FIFO section */
+
+struct tc_fifo_qopt {
+       __u32   limit;  /* Queue length: bytes for bfifo, packets for pfifo */
+};
+
+/* SKBPRIO section */
+
+/*
+ * Priorities go from zero to (SKBPRIO_MAX_PRIORITY - 1).
+ * SKBPRIO_MAX_PRIORITY should be at least 64 in order for skbprio to be able
+ * to map one to one the DS field of IPV4 and IPV6 headers.
+ * Memory allocation grows linearly with SKBPRIO_MAX_PRIORITY.
+ */
+
+#define SKBPRIO_MAX_PRIORITY 64
+
+struct tc_skbprio_qopt {
+       __u32   limit;          /* Queue length in packets. */
+};
+
+/* PRIO section */
+
+#define TCQ_PRIO_BANDS 16
+#define TCQ_MIN_PRIO_BANDS 2
+
+struct tc_prio_qopt {
+       int     bands;                  /* Number of bands */
+       __u8    priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */
+};
+
+/* MULTIQ section */
+
+struct tc_multiq_qopt {
+       __u16   bands;                  /* Number of bands */
+       __u16   max_bands;              /* Maximum number of queues */
+};
+
+/* PLUG section */
+
+#define TCQ_PLUG_BUFFER                0
+#define TCQ_PLUG_RELEASE_ONE           1
+#define TCQ_PLUG_RELEASE_INDEFINITE    2
+#define TCQ_PLUG_LIMIT                 3
+
+struct tc_plug_qopt {
+       /* TCQ_PLUG_BUFFER: Inset a plug into the queue and
+        *  buffer any incoming packets
+        * TCQ_PLUG_RELEASE_ONE: Dequeue packets from queue head
+        *   to beginning of the next plug.
+        * TCQ_PLUG_RELEASE_INDEFINITE: Dequeue all packets from queue.
+        *   Stop buffering packets until the next TCQ_PLUG_BUFFER
+        *   command is received (just act as a pass-thru queue).
+        * TCQ_PLUG_LIMIT: Increase/decrease queue size
+        */
+       int             action;
+       __u32           limit;
+};
+
+/* TBF section */
+
+struct tc_tbf_qopt {
+       struct tc_ratespec rate;
+       struct tc_ratespec peakrate;
+       __u32           limit;
+       __u32           buffer;
+       __u32           mtu;
+};
+
+enum {
+       TCA_TBF_UNSPEC,
+       TCA_TBF_PARMS,
+       TCA_TBF_RTAB,
+       TCA_TBF_PTAB,
+       TCA_TBF_RATE64,
+       TCA_TBF_PRATE64,
+       TCA_TBF_BURST,
+       TCA_TBF_PBURST,
+       TCA_TBF_PAD,
+       __TCA_TBF_MAX,
+};
+
+#define TCA_TBF_MAX (__TCA_TBF_MAX - 1)
+
+
+/* TEQL section */
+
+/* TEQL does not require any parameters */
+
+/* SFQ section */
+
+struct tc_sfq_qopt {
+       unsigned        quantum;        /* Bytes per round allocated to flow */
+       int             perturb_period; /* Period of hash perturbation */
+       __u32           limit;          /* Maximal packets in queue */
+       unsigned        divisor;        /* Hash divisor  */
+       unsigned        flows;          /* Maximal number of flows  */
+};
+
+struct tc_sfqred_stats {
+       __u32           prob_drop;      /* Early drops, below max threshold */
+       __u32           forced_drop;    /* Early drops, after max threshold */
+       __u32           prob_mark;      /* Marked packets, below max threshold */
+       __u32           forced_mark;    /* Marked packets, after max threshold */
+       __u32           prob_mark_head; /* Marked packets, below max threshold */
+       __u32           forced_mark_head;/* Marked packets, after max threshold */
+};
+
+struct tc_sfq_qopt_v1 {
+       struct tc_sfq_qopt v0;
+       unsigned int    depth;          /* max number of packets per flow */
+       unsigned int    headdrop;
+/* SFQRED parameters */
+       __u32           limit;          /* HARD maximal flow queue length (bytes) */
+       __u32           qth_min;        /* Min average length threshold (bytes) */
+       __u32           qth_max;        /* Max average length threshold (bytes) */
+       unsigned char   Wlog;           /* log(W)               */
+       unsigned char   Plog;           /* log(P_max/(qth_max-qth_min)) */
+       unsigned char   Scell_log;      /* cell size for idle damping */
+       unsigned char   flags;
+       __u32           max_P;          /* probability, high resolution */
+/* SFQRED stats */
+       struct tc_sfqred_stats stats;
+};
+
+
+struct tc_sfq_xstats {
+       __s32           allot;
+};
+
+/* RED section */
+
+enum {
+       TCA_RED_UNSPEC,
+       TCA_RED_PARMS,
+       TCA_RED_STAB,
+       TCA_RED_MAX_P,
+       __TCA_RED_MAX,
+};
+
+#define TCA_RED_MAX (__TCA_RED_MAX - 1)
+
+struct tc_red_qopt {
+       __u32           limit;          /* HARD maximal queue length (bytes)    */
+       __u32           qth_min;        /* Min average length threshold (bytes) */
+       __u32           qth_max;        /* Max average length threshold (bytes) */
+       unsigned char   Wlog;           /* log(W)               */
+       unsigned char   Plog;           /* log(P_max/(qth_max-qth_min)) */
+       unsigned char   Scell_log;      /* cell size for idle damping */
+       unsigned char   flags;
+#define TC_RED_ECN             1
+#define TC_RED_HARDDROP                2
+#define TC_RED_ADAPTATIVE      4
+};
+
+struct tc_red_xstats {
+       __u32           early;          /* Early drops */
+       __u32           pdrop;          /* Drops due to queue limits */
+       __u32           other;          /* Drops due to drop() calls */
+       __u32           marked;         /* Marked packets */
+};
+
+/* GRED section */
+
+#define MAX_DPs 16
+
+enum {
+       TCA_GRED_UNSPEC,
+       TCA_GRED_PARMS,
+       TCA_GRED_STAB,
+       TCA_GRED_DPS,
+       TCA_GRED_MAX_P,
+       TCA_GRED_LIMIT,
+       TCA_GRED_VQ_LIST,       /* nested TCA_GRED_VQ_ENTRY */
+       __TCA_GRED_MAX,
+};
+
+#define TCA_GRED_MAX (__TCA_GRED_MAX - 1)
+
+enum {
+       TCA_GRED_VQ_ENTRY_UNSPEC,
+       TCA_GRED_VQ_ENTRY,      /* nested TCA_GRED_VQ_* */
+       __TCA_GRED_VQ_ENTRY_MAX,
+};
+#define TCA_GRED_VQ_ENTRY_MAX (__TCA_GRED_VQ_ENTRY_MAX - 1)
+
+enum {
+       TCA_GRED_VQ_UNSPEC,
+       TCA_GRED_VQ_PAD,
+       TCA_GRED_VQ_DP,                 /* u32 */
+       TCA_GRED_VQ_STAT_BYTES,         /* u64 */
+       TCA_GRED_VQ_STAT_PACKETS,       /* u32 */
+       TCA_GRED_VQ_STAT_BACKLOG,       /* u32 */
+       TCA_GRED_VQ_STAT_PROB_DROP,     /* u32 */
+       TCA_GRED_VQ_STAT_PROB_MARK,     /* u32 */
+       TCA_GRED_VQ_STAT_FORCED_DROP,   /* u32 */
+       TCA_GRED_VQ_STAT_FORCED_MARK,   /* u32 */
+       TCA_GRED_VQ_STAT_PDROP,         /* u32 */
+       TCA_GRED_VQ_STAT_OTHER,         /* u32 */
+       TCA_GRED_VQ_FLAGS,              /* u32 */
+       __TCA_GRED_VQ_MAX
+};
+
+#define TCA_GRED_VQ_MAX (__TCA_GRED_VQ_MAX - 1)
+
+struct tc_gred_qopt {
+       __u32           limit;        /* HARD maximal queue length (bytes)    */
+       __u32           qth_min;      /* Min average length threshold (bytes) */
+       __u32           qth_max;      /* Max average length threshold (bytes) */
+       __u32           DP;           /* up to 2^32 DPs */
+       __u32           backlog;
+       __u32           qave;
+       __u32           forced;
+       __u32           early;
+       __u32           other;
+       __u32           pdrop;
+       __u8            Wlog;         /* log(W)               */
+       __u8            Plog;         /* log(P_max/(qth_max-qth_min)) */
+       __u8            Scell_log;    /* cell size for idle damping */
+       __u8            prio;         /* prio of this VQ */
+       __u32           packets;
+       __u32           bytesin;
+};
+
+/* gred setup */
+struct tc_gred_sopt {
+       __u32           DPs;
+       __u32           def_DP;
+       __u8            grio;
+       __u8            flags;
+       __u16           pad1;
+};
+
+/* CHOKe section */
+
+enum {
+       TCA_CHOKE_UNSPEC,
+       TCA_CHOKE_PARMS,
+       TCA_CHOKE_STAB,
+       TCA_CHOKE_MAX_P,
+       __TCA_CHOKE_MAX,
+};
+
+#define TCA_CHOKE_MAX (__TCA_CHOKE_MAX - 1)
+
+struct tc_choke_qopt {
+       __u32           limit;          /* Hard queue length (packets)  */
+       __u32           qth_min;        /* Min average threshold (packets) */
+       __u32           qth_max;        /* Max average threshold (packets) */
+       unsigned char   Wlog;           /* log(W)               */
+       unsigned char   Plog;           /* log(P_max/(qth_max-qth_min)) */
+       unsigned char   Scell_log;      /* cell size for idle damping */
+       unsigned char   flags;          /* see RED flags */
+};
+
+struct tc_choke_xstats {
+       __u32           early;          /* Early drops */
+       __u32           pdrop;          /* Drops due to queue limits */
+       __u32           other;          /* Drops due to drop() calls */
+       __u32           marked;         /* Marked packets */
+       __u32           matched;        /* Drops due to flow match */
+};
+
+/* HTB section */
+#define TC_HTB_NUMPRIO         8
+#define TC_HTB_MAXDEPTH                8
+#define TC_HTB_PROTOVER                3 /* the same as HTB and TC's major */
+
+struct tc_htb_opt {
+       struct tc_ratespec      rate;
+       struct tc_ratespec      ceil;
+       __u32   buffer;
+       __u32   cbuffer;
+       __u32   quantum;
+       __u32   level;          /* out only */
+       __u32   prio;
+};
+struct tc_htb_glob {
+       __u32 version;          /* to match HTB/TC */
+       __u32 rate2quantum;     /* bps->quantum divisor */
+       __u32 defcls;           /* default class number */
+       __u32 debug;            /* debug flags */
+
+       /* stats */
+       __u32 direct_pkts; /* count of non shaped packets */
+};
+enum {
+       TCA_HTB_UNSPEC,
+       TCA_HTB_PARMS,
+       TCA_HTB_INIT,
+       TCA_HTB_CTAB,
+       TCA_HTB_RTAB,
+       TCA_HTB_DIRECT_QLEN,
+       TCA_HTB_RATE64,
+       TCA_HTB_CEIL64,
+       TCA_HTB_PAD,
+       __TCA_HTB_MAX,
+};
+
+#define TCA_HTB_MAX (__TCA_HTB_MAX - 1)
+
+struct tc_htb_xstats {
+       __u32 lends;
+       __u32 borrows;
+       __u32 giants;   /* unused since 'Make HTB scheduler work with TSO.' */
+       __s32 tokens;
+       __s32 ctokens;
+};
+
+/* HFSC section */
+
+struct tc_hfsc_qopt {
+       __u16   defcls;         /* default class */
+};
+
+struct tc_service_curve {
+       __u32   m1;             /* slope of the first segment in bps */
+       __u32   d;              /* x-projection of the first segment in us */
+       __u32   m2;             /* slope of the second segment in bps */
+};
+
+struct tc_hfsc_stats {
+       __u64   work;           /* total work done */
+       __u64   rtwork;         /* work done by real-time criteria */
+       __u32   period;         /* current period */
+       __u32   level;          /* class level in hierarchy */
+};
+
+enum {
+       TCA_HFSC_UNSPEC,
+       TCA_HFSC_RSC,
+       TCA_HFSC_FSC,
+       TCA_HFSC_USC,
+       __TCA_HFSC_MAX,
+};
+
+#define TCA_HFSC_MAX (__TCA_HFSC_MAX - 1)
+
+
+/* CBQ section */
+
+#define TC_CBQ_MAXPRIO         8
+#define TC_CBQ_MAXLEVEL                8
+#define TC_CBQ_DEF_EWMA                5
+
+struct tc_cbq_lssopt {
+       unsigned char   change;
+       unsigned char   flags;
+#define TCF_CBQ_LSS_BOUNDED    1
+#define TCF_CBQ_LSS_ISOLATED   2
+       unsigned char   ewma_log;
+       unsigned char   level;
+#define TCF_CBQ_LSS_FLAGS      1
+#define TCF_CBQ_LSS_EWMA       2
+#define TCF_CBQ_LSS_MAXIDLE    4
+#define TCF_CBQ_LSS_MINIDLE    8
+#define TCF_CBQ_LSS_OFFTIME    0x10
+#define TCF_CBQ_LSS_AVPKT      0x20
+       __u32           maxidle;
+       __u32           minidle;
+       __u32           offtime;
+       __u32           avpkt;
+};
+
+struct tc_cbq_wrropt {
+       unsigned char   flags;
+       unsigned char   priority;
+       unsigned char   cpriority;
+       unsigned char   __reserved;
+       __u32           allot;
+       __u32           weight;
+};
+
+struct tc_cbq_ovl {
+       unsigned char   strategy;
+#define        TC_CBQ_OVL_CLASSIC      0
+#define        TC_CBQ_OVL_DELAY        1
+#define        TC_CBQ_OVL_LOWPRIO      2
+#define        TC_CBQ_OVL_DROP         3
+#define        TC_CBQ_OVL_RCLASSIC     4
+       unsigned char   priority2;
+       __u16           pad;
+       __u32           penalty;
+};
+
+struct tc_cbq_police {
+       unsigned char   police;
+       unsigned char   __res1;
+       unsigned short  __res2;
+};
+
+struct tc_cbq_fopt {
+       __u32           split;
+       __u32           defmap;
+       __u32           defchange;
+};
+
+struct tc_cbq_xstats {
+       __u32           borrows;
+       __u32           overactions;
+       __s32           avgidle;
+       __s32           undertime;
+};
+
+enum {
+       TCA_CBQ_UNSPEC,
+       TCA_CBQ_LSSOPT,
+       TCA_CBQ_WRROPT,
+       TCA_CBQ_FOPT,
+       TCA_CBQ_OVL_STRATEGY,
+       TCA_CBQ_RATE,
+       TCA_CBQ_RTAB,
+       TCA_CBQ_POLICE,
+       __TCA_CBQ_MAX,
+};
+
+#define TCA_CBQ_MAX    (__TCA_CBQ_MAX - 1)
+
+/* dsmark section */
+
+enum {
+       TCA_DSMARK_UNSPEC,
+       TCA_DSMARK_INDICES,
+       TCA_DSMARK_DEFAULT_INDEX,
+       TCA_DSMARK_SET_TC_INDEX,
+       TCA_DSMARK_MASK,
+       TCA_DSMARK_VALUE,
+       __TCA_DSMARK_MAX,
+};
+
+#define TCA_DSMARK_MAX (__TCA_DSMARK_MAX - 1)
+
+/* ATM  section */
+
+enum {
+       TCA_ATM_UNSPEC,
+       TCA_ATM_FD,             /* file/socket descriptor */
+       TCA_ATM_PTR,            /* pointer to descriptor - later */
+       TCA_ATM_HDR,            /* LL header */
+       TCA_ATM_EXCESS,         /* excess traffic class (0 for CLP)  */
+       TCA_ATM_ADDR,           /* PVC address (for output only) */
+       TCA_ATM_STATE,          /* VC state (ATM_VS_*; for output only) */
+       __TCA_ATM_MAX,
+};
+
+#define TCA_ATM_MAX    (__TCA_ATM_MAX - 1)
+
+/* Network emulator */
+
+enum {
+       TCA_NETEM_UNSPEC,
+       TCA_NETEM_CORR,
+       TCA_NETEM_DELAY_DIST,
+       TCA_NETEM_REORDER,
+       TCA_NETEM_CORRUPT,
+       TCA_NETEM_LOSS,
+       TCA_NETEM_RATE,
+       TCA_NETEM_ECN,
+       TCA_NETEM_RATE64,
+       TCA_NETEM_PAD,
+       TCA_NETEM_LATENCY64,
+       TCA_NETEM_JITTER64,
+       TCA_NETEM_SLOT,
+       TCA_NETEM_SLOT_DIST,
+       __TCA_NETEM_MAX,
+};
+
+#define TCA_NETEM_MAX (__TCA_NETEM_MAX - 1)
+
+struct tc_netem_qopt {
+       __u32   latency;        /* added delay (us) */
+       __u32   limit;          /* fifo limit (packets) */
+       __u32   loss;           /* random packet loss (0=none ~0=100%) */
+       __u32   gap;            /* re-ordering gap (0 for none) */
+       __u32   duplicate;      /* random packet dup  (0=none ~0=100%) */
+       __u32   jitter;         /* random jitter in latency (us) */
+};
+
+struct tc_netem_corr {
+       __u32   delay_corr;     /* delay correlation */
+       __u32   loss_corr;      /* packet loss correlation */
+       __u32   dup_corr;       /* duplicate correlation  */
+};
+
+struct tc_netem_reorder {
+       __u32   probability;
+       __u32   correlation;
+};
+
+struct tc_netem_corrupt {
+       __u32   probability;
+       __u32   correlation;
+};
+
+struct tc_netem_rate {
+       __u32   rate;   /* byte/s */
+       __s32   packet_overhead;
+       __u32   cell_size;
+       __s32   cell_overhead;
+};
+
+struct tc_netem_slot {
+       __s64   min_delay; /* nsec */
+       __s64   max_delay;
+       __s32   max_packets;
+       __s32   max_bytes;
+       __s64   dist_delay; /* nsec */
+       __s64   dist_jitter; /* nsec */
+};
+
+enum {
+       NETEM_LOSS_UNSPEC,
+       NETEM_LOSS_GI,          /* General Intuitive - 4 state model */
+       NETEM_LOSS_GE,          /* Gilbert Elliot models */
+       __NETEM_LOSS_MAX
+};
+#define NETEM_LOSS_MAX (__NETEM_LOSS_MAX - 1)
+
+/* State transition probabilities for 4 state model */
+struct tc_netem_gimodel {
+       __u32   p13;
+       __u32   p31;
+       __u32   p32;
+       __u32   p14;
+       __u32   p23;
+};
+
+/* Gilbert-Elliot models */
+struct tc_netem_gemodel {
+       __u32 p;
+       __u32 r;
+       __u32 h;
+       __u32 k1;
+};
+
+#define NETEM_DIST_SCALE       8192
+#define NETEM_DIST_MAX         16384
+
+/* DRR */
+
+enum {
+       TCA_DRR_UNSPEC,
+       TCA_DRR_QUANTUM,
+       __TCA_DRR_MAX
+};
+
+#define TCA_DRR_MAX    (__TCA_DRR_MAX - 1)
+
+struct tc_drr_stats {
+       __u32   deficit;
+};
+
+/* MQPRIO */
+#define TC_QOPT_BITMASK 15
+#define TC_QOPT_MAX_QUEUE 16
+
+enum {
+       TC_MQPRIO_HW_OFFLOAD_NONE,      /* no offload requested */
+       TC_MQPRIO_HW_OFFLOAD_TCS,       /* offload TCs, no queue counts */
+       __TC_MQPRIO_HW_OFFLOAD_MAX
+};
+
+#define TC_MQPRIO_HW_OFFLOAD_MAX (__TC_MQPRIO_HW_OFFLOAD_MAX - 1)
+
+enum {
+       TC_MQPRIO_MODE_DCB,
+       TC_MQPRIO_MODE_CHANNEL,
+       __TC_MQPRIO_MODE_MAX
+};
+
+#define __TC_MQPRIO_MODE_MAX (__TC_MQPRIO_MODE_MAX - 1)
+
+enum {
+       TC_MQPRIO_SHAPER_DCB,
+       TC_MQPRIO_SHAPER_BW_RATE,       /* Add new shapers below */
+       __TC_MQPRIO_SHAPER_MAX
+};
+
+#define __TC_MQPRIO_SHAPER_MAX (__TC_MQPRIO_SHAPER_MAX - 1)
+
+struct tc_mqprio_qopt {
+       __u8    num_tc;
+       __u8    prio_tc_map[TC_QOPT_BITMASK + 1];
+       __u8    hw;
+       __u16   count[TC_QOPT_MAX_QUEUE];
+       __u16   offset[TC_QOPT_MAX_QUEUE];
+};
+
+#define TC_MQPRIO_F_MODE               0x1
+#define TC_MQPRIO_F_SHAPER             0x2
+#define TC_MQPRIO_F_MIN_RATE           0x4
+#define TC_MQPRIO_F_MAX_RATE           0x8
+
+enum {
+       TCA_MQPRIO_UNSPEC,
+       TCA_MQPRIO_MODE,
+       TCA_MQPRIO_SHAPER,
+       TCA_MQPRIO_MIN_RATE64,
+       TCA_MQPRIO_MAX_RATE64,
+       __TCA_MQPRIO_MAX,
+};
+
+#define TCA_MQPRIO_MAX (__TCA_MQPRIO_MAX - 1)
+
+/* SFB */
+
+enum {
+       TCA_SFB_UNSPEC,
+       TCA_SFB_PARMS,
+       __TCA_SFB_MAX,
+};
+
+#define TCA_SFB_MAX (__TCA_SFB_MAX - 1)
+
+/*
+ * Note: increment, decrement are Q0.16 fixed-point values.
+ */
+struct tc_sfb_qopt {
+       __u32 rehash_interval;  /* delay between hash move, in ms */
+       __u32 warmup_time;      /* double buffering warmup time in ms (warmup_time < rehash_interval) */
+       __u32 max;              /* max len of qlen_min */
+       __u32 bin_size;         /* maximum queue length per bin */
+       __u32 increment;        /* probability increment, (d1 in Blue) */
+       __u32 decrement;        /* probability decrement, (d2 in Blue) */
+       __u32 limit;            /* max SFB queue length */
+       __u32 penalty_rate;     /* inelastic flows are rate limited to 'rate' pps */
+       __u32 penalty_burst;
+};
+
+struct tc_sfb_xstats {
+       __u32 earlydrop;
+       __u32 penaltydrop;
+       __u32 bucketdrop;
+       __u32 queuedrop;
+       __u32 childdrop; /* drops in child qdisc */
+       __u32 marked;
+       __u32 maxqlen;
+       __u32 maxprob;
+       __u32 avgprob;
+};
+
+#define SFB_MAX_PROB 0xFFFF
+
+/* QFQ */
+enum {
+       TCA_QFQ_UNSPEC,
+       TCA_QFQ_WEIGHT,
+       TCA_QFQ_LMAX,
+       __TCA_QFQ_MAX
+};
+
+#define TCA_QFQ_MAX    (__TCA_QFQ_MAX - 1)
+
+struct tc_qfq_stats {
+       __u32 weight;
+       __u32 lmax;
+};
+
+/* CODEL */
+
+enum {
+       TCA_CODEL_UNSPEC,
+       TCA_CODEL_TARGET,
+       TCA_CODEL_LIMIT,
+       TCA_CODEL_INTERVAL,
+       TCA_CODEL_ECN,
+       TCA_CODEL_CE_THRESHOLD,
+       __TCA_CODEL_MAX
+};
+
+#define TCA_CODEL_MAX  (__TCA_CODEL_MAX - 1)
+
+struct tc_codel_xstats {
+       __u32   maxpacket; /* largest packet we've seen so far */
+       __u32   count;     /* how many drops we've done since the last time we
+                           * entered dropping state
+                           */
+       __u32   lastcount; /* count at entry to dropping state */
+       __u32   ldelay;    /* in-queue delay seen by most recently dequeued packet */
+       __s32   drop_next; /* time to drop next packet */
+       __u32   drop_overlimit; /* number of time max qdisc packet limit was hit */
+       __u32   ecn_mark;  /* number of packets we ECN marked instead of dropped */
+       __u32   dropping;  /* are we in dropping state ? */
+       __u32   ce_mark;   /* number of CE marked packets because of ce_threshold */
+};
+
+/* FQ_CODEL */
+
+enum {
+       TCA_FQ_CODEL_UNSPEC,
+       TCA_FQ_CODEL_TARGET,
+       TCA_FQ_CODEL_LIMIT,
+       TCA_FQ_CODEL_INTERVAL,
+       TCA_FQ_CODEL_ECN,
+       TCA_FQ_CODEL_FLOWS,
+       TCA_FQ_CODEL_QUANTUM,
+       TCA_FQ_CODEL_CE_THRESHOLD,
+       TCA_FQ_CODEL_DROP_BATCH_SIZE,
+       TCA_FQ_CODEL_MEMORY_LIMIT,
+       __TCA_FQ_CODEL_MAX
+};
+
+#define TCA_FQ_CODEL_MAX       (__TCA_FQ_CODEL_MAX - 1)
+
+enum {
+       TCA_FQ_CODEL_XSTATS_QDISC,
+       TCA_FQ_CODEL_XSTATS_CLASS,
+};
+
+struct tc_fq_codel_qd_stats {
+       __u32   maxpacket;      /* largest packet we've seen so far */
+       __u32   drop_overlimit; /* number of time max qdisc
+                                * packet limit was hit
+                                */
+       __u32   ecn_mark;       /* number of packets we ECN marked
+                                * instead of being dropped
+                                */
+       __u32   new_flow_count; /* number of time packets
+                                * created a 'new flow'
+                                */
+       __u32   new_flows_len;  /* count of flows in new list */
+       __u32   old_flows_len;  /* count of flows in old list */
+       __u32   ce_mark;        /* packets above ce_threshold */
+       __u32   memory_usage;   /* in bytes */
+       __u32   drop_overmemory;
+};
+
+struct tc_fq_codel_cl_stats {
+       __s32   deficit;
+       __u32   ldelay;         /* in-queue delay seen by most recently
+                                * dequeued packet
+                                */
+       __u32   count;
+       __u32   lastcount;
+       __u32   dropping;
+       __s32   drop_next;
+};
+
+struct tc_fq_codel_xstats {
+       __u32   type;
+       union {
+               struct tc_fq_codel_qd_stats qdisc_stats;
+               struct tc_fq_codel_cl_stats class_stats;
+       };
+};
+
+/* FQ */
+
+enum {
+       TCA_FQ_UNSPEC,
+
+       TCA_FQ_PLIMIT,          /* limit of total number of packets in queue */
+
+       TCA_FQ_FLOW_PLIMIT,     /* limit of packets per flow */
+
+       TCA_FQ_QUANTUM,         /* RR quantum */
+
+       TCA_FQ_INITIAL_QUANTUM,         /* RR quantum for new flow */
+
+       TCA_FQ_RATE_ENABLE,     /* enable/disable rate limiting */
+
+       TCA_FQ_FLOW_DEFAULT_RATE,/* obsolete, do not use */
+
+       TCA_FQ_FLOW_MAX_RATE,   /* per flow max rate */
+
+       TCA_FQ_BUCKETS_LOG,     /* log2(number of buckets) */
+
+       TCA_FQ_FLOW_REFILL_DELAY,       /* flow credit refill delay in usec */
+
+       TCA_FQ_ORPHAN_MASK,     /* mask applied to orphaned skb hashes */
+
+       TCA_FQ_LOW_RATE_THRESHOLD, /* per packet delay under this rate */
+
+       TCA_FQ_CE_THRESHOLD,    /* DCTCP-like CE-marking threshold */
+
+       __TCA_FQ_MAX
+};
+
+#define TCA_FQ_MAX     (__TCA_FQ_MAX - 1)
+
+struct tc_fq_qd_stats {
+       __u64   gc_flows;
+       __u64   highprio_packets;
+       __u64   tcp_retrans;
+       __u64   throttled;
+       __u64   flows_plimit;
+       __u64   pkts_too_long;
+       __u64   allocation_errors;
+       __s64   time_next_delayed_flow;
+       __u32   flows;
+       __u32   inactive_flows;
+       __u32   throttled_flows;
+       __u32   unthrottle_latency_ns;
+       __u64   ce_mark;                /* packets above ce_threshold */
+};
+
+/* Heavy-Hitter Filter */
+
+enum {
+       TCA_HHF_UNSPEC,
+       TCA_HHF_BACKLOG_LIMIT,
+       TCA_HHF_QUANTUM,
+       TCA_HHF_HH_FLOWS_LIMIT,
+       TCA_HHF_RESET_TIMEOUT,
+       TCA_HHF_ADMIT_BYTES,
+       TCA_HHF_EVICT_TIMEOUT,
+       TCA_HHF_NON_HH_WEIGHT,
+       __TCA_HHF_MAX
+};
+
+#define TCA_HHF_MAX    (__TCA_HHF_MAX - 1)
+
+struct tc_hhf_xstats {
+       __u32   drop_overlimit; /* number of times max qdisc packet limit
+                                * was hit
+                                */
+       __u32   hh_overlimit;   /* number of times max heavy-hitters was hit */
+       __u32   hh_tot_count;   /* number of captured heavy-hitters so far */
+       __u32   hh_cur_count;   /* number of current heavy-hitters */
+};
+
+/* PIE */
+enum {
+       TCA_PIE_UNSPEC,
+       TCA_PIE_TARGET,
+       TCA_PIE_LIMIT,
+       TCA_PIE_TUPDATE,
+       TCA_PIE_ALPHA,
+       TCA_PIE_BETA,
+       TCA_PIE_ECN,
+       TCA_PIE_BYTEMODE,
+       __TCA_PIE_MAX
+};
+#define TCA_PIE_MAX   (__TCA_PIE_MAX - 1)
+
+struct tc_pie_xstats {
+       __u32 prob;             /* current probability */
+       __u32 delay;            /* current delay in ms */
+       __u32 avg_dq_rate;      /* current average dq_rate in bits/pie_time */
+       __u32 packets_in;       /* total number of packets enqueued */
+       __u32 dropped;          /* packets dropped due to pie_action */
+       __u32 overlimit;        /* dropped due to lack of space in queue */
+       __u32 maxq;             /* maximum queue size */
+       __u32 ecn_mark;         /* packets marked with ecn*/
+};
+
+/* CBS */
+struct tc_cbs_qopt {
+       __u8 offload;
+       __u8 _pad[3];
+       __s32 hicredit;
+       __s32 locredit;
+       __s32 idleslope;
+       __s32 sendslope;
+};
+
+enum {
+       TCA_CBS_UNSPEC,
+       TCA_CBS_PARMS,
+       __TCA_CBS_MAX,
+};
+
+#define TCA_CBS_MAX (__TCA_CBS_MAX - 1)
+
+
+/* ETF */
+struct tc_etf_qopt {
+       __s32 delta;
+       __s32 clockid;
+       __u32 flags;
+#define TC_ETF_DEADLINE_MODE_ON        BIT(0)
+#define TC_ETF_OFFLOAD_ON      BIT(1)
+};
+
+enum {
+       TCA_ETF_UNSPEC,
+       TCA_ETF_PARMS,
+       __TCA_ETF_MAX,
+};
+
+#define TCA_ETF_MAX (__TCA_ETF_MAX - 1)
+
+
+/* CAKE */
+enum {
+       TCA_CAKE_UNSPEC,
+       TCA_CAKE_PAD,
+       TCA_CAKE_BASE_RATE64,
+       TCA_CAKE_DIFFSERV_MODE,
+       TCA_CAKE_ATM,
+       TCA_CAKE_FLOW_MODE,
+       TCA_CAKE_OVERHEAD,
+       TCA_CAKE_RTT,
+       TCA_CAKE_TARGET,
+       TCA_CAKE_AUTORATE,
+       TCA_CAKE_MEMORY,
+       TCA_CAKE_NAT,
+       TCA_CAKE_RAW,
+       TCA_CAKE_WASH,
+       TCA_CAKE_MPU,
+       TCA_CAKE_INGRESS,
+       TCA_CAKE_ACK_FILTER,
+       TCA_CAKE_SPLIT_GSO,
+       __TCA_CAKE_MAX
+};
+#define TCA_CAKE_MAX   (__TCA_CAKE_MAX - 1)
+
+enum {
+       __TCA_CAKE_STATS_INVALID,
+       TCA_CAKE_STATS_PAD,
+       TCA_CAKE_STATS_CAPACITY_ESTIMATE64,
+       TCA_CAKE_STATS_MEMORY_LIMIT,
+       TCA_CAKE_STATS_MEMORY_USED,
+       TCA_CAKE_STATS_AVG_NETOFF,
+       TCA_CAKE_STATS_MIN_NETLEN,
+       TCA_CAKE_STATS_MAX_NETLEN,
+       TCA_CAKE_STATS_MIN_ADJLEN,
+       TCA_CAKE_STATS_MAX_ADJLEN,
+       TCA_CAKE_STATS_TIN_STATS,
+       TCA_CAKE_STATS_DEFICIT,
+       TCA_CAKE_STATS_COBALT_COUNT,
+       TCA_CAKE_STATS_DROPPING,
+       TCA_CAKE_STATS_DROP_NEXT_US,
+       TCA_CAKE_STATS_P_DROP,
+       TCA_CAKE_STATS_BLUE_TIMER_US,
+       __TCA_CAKE_STATS_MAX
+};
+#define TCA_CAKE_STATS_MAX (__TCA_CAKE_STATS_MAX - 1)
+
+enum {
+       __TCA_CAKE_TIN_STATS_INVALID,
+       TCA_CAKE_TIN_STATS_PAD,
+       TCA_CAKE_TIN_STATS_SENT_PACKETS,
+       TCA_CAKE_TIN_STATS_SENT_BYTES64,
+       TCA_CAKE_TIN_STATS_DROPPED_PACKETS,
+       TCA_CAKE_TIN_STATS_DROPPED_BYTES64,
+       TCA_CAKE_TIN_STATS_ACKS_DROPPED_PACKETS,
+       TCA_CAKE_TIN_STATS_ACKS_DROPPED_BYTES64,
+       TCA_CAKE_TIN_STATS_ECN_MARKED_PACKETS,
+       TCA_CAKE_TIN_STATS_ECN_MARKED_BYTES64,
+       TCA_CAKE_TIN_STATS_BACKLOG_PACKETS,
+       TCA_CAKE_TIN_STATS_BACKLOG_BYTES,
+       TCA_CAKE_TIN_STATS_THRESHOLD_RATE64,
+       TCA_CAKE_TIN_STATS_TARGET_US,
+       TCA_CAKE_TIN_STATS_INTERVAL_US,
+       TCA_CAKE_TIN_STATS_WAY_INDIRECT_HITS,
+       TCA_CAKE_TIN_STATS_WAY_MISSES,
+       TCA_CAKE_TIN_STATS_WAY_COLLISIONS,
+       TCA_CAKE_TIN_STATS_PEAK_DELAY_US,
+       TCA_CAKE_TIN_STATS_AVG_DELAY_US,
+       TCA_CAKE_TIN_STATS_BASE_DELAY_US,
+       TCA_CAKE_TIN_STATS_SPARSE_FLOWS,
+       TCA_CAKE_TIN_STATS_BULK_FLOWS,
+       TCA_CAKE_TIN_STATS_UNRESPONSIVE_FLOWS,
+       TCA_CAKE_TIN_STATS_MAX_SKBLEN,
+       TCA_CAKE_TIN_STATS_FLOW_QUANTUM,
+       __TCA_CAKE_TIN_STATS_MAX
+};
+#define TCA_CAKE_TIN_STATS_MAX (__TCA_CAKE_TIN_STATS_MAX - 1)
+#define TC_CAKE_MAX_TINS (8)
+
+enum {
+       CAKE_FLOW_NONE = 0,
+       CAKE_FLOW_SRC_IP,
+       CAKE_FLOW_DST_IP,
+       CAKE_FLOW_HOSTS,    /* = CAKE_FLOW_SRC_IP | CAKE_FLOW_DST_IP */
+       CAKE_FLOW_FLOWS,
+       CAKE_FLOW_DUAL_SRC, /* = CAKE_FLOW_SRC_IP | CAKE_FLOW_FLOWS */
+       CAKE_FLOW_DUAL_DST, /* = CAKE_FLOW_DST_IP | CAKE_FLOW_FLOWS */
+       CAKE_FLOW_TRIPLE,   /* = CAKE_FLOW_HOSTS  | CAKE_FLOW_FLOWS */
+       CAKE_FLOW_MAX,
+};
+
+enum {
+       CAKE_DIFFSERV_DIFFSERV3 = 0,
+       CAKE_DIFFSERV_DIFFSERV4,
+       CAKE_DIFFSERV_DIFFSERV8,
+       CAKE_DIFFSERV_BESTEFFORT,
+       CAKE_DIFFSERV_PRECEDENCE,
+       CAKE_DIFFSERV_MAX
+};
+
+enum {
+       CAKE_ACK_NONE = 0,
+       CAKE_ACK_FILTER,
+       CAKE_ACK_AGGRESSIVE,
+       CAKE_ACK_MAX
+};
+
+enum {
+       CAKE_ATM_NONE = 0,
+       CAKE_ATM_ATM,
+       CAKE_ATM_PTM,
+       CAKE_ATM_MAX
+};
+
+
+/* TAPRIO */
+enum {
+       TC_TAPRIO_CMD_SET_GATES = 0x00,
+       TC_TAPRIO_CMD_SET_AND_HOLD = 0x01,
+       TC_TAPRIO_CMD_SET_AND_RELEASE = 0x02,
+};
+
+enum {
+       TCA_TAPRIO_SCHED_ENTRY_UNSPEC,
+       TCA_TAPRIO_SCHED_ENTRY_INDEX, /* u32 */
+       TCA_TAPRIO_SCHED_ENTRY_CMD, /* u8 */
+       TCA_TAPRIO_SCHED_ENTRY_GATE_MASK, /* u32 */
+       TCA_TAPRIO_SCHED_ENTRY_INTERVAL, /* u32 */
+       __TCA_TAPRIO_SCHED_ENTRY_MAX,
+};
+#define TCA_TAPRIO_SCHED_ENTRY_MAX (__TCA_TAPRIO_SCHED_ENTRY_MAX - 1)
+
+/* The format for schedule entry list is:
+ * [TCA_TAPRIO_SCHED_ENTRY_LIST]
+ *   [TCA_TAPRIO_SCHED_ENTRY]
+ *     [TCA_TAPRIO_SCHED_ENTRY_CMD]
+ *     [TCA_TAPRIO_SCHED_ENTRY_GATES]
+ *     [TCA_TAPRIO_SCHED_ENTRY_INTERVAL]
+ */
+enum {
+       TCA_TAPRIO_SCHED_UNSPEC,
+       TCA_TAPRIO_SCHED_ENTRY,
+       __TCA_TAPRIO_SCHED_MAX,
+};
+
+#define TCA_TAPRIO_SCHED_MAX (__TCA_TAPRIO_SCHED_MAX - 1)
+
+enum {
+       TCA_TAPRIO_ATTR_UNSPEC,
+       TCA_TAPRIO_ATTR_PRIOMAP, /* struct tc_mqprio_qopt */
+       TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST, /* nested of entry */
+       TCA_TAPRIO_ATTR_SCHED_BASE_TIME, /* s64 */
+       TCA_TAPRIO_ATTR_SCHED_SINGLE_ENTRY, /* single entry */
+       TCA_TAPRIO_ATTR_SCHED_CLOCKID, /* s32 */
+       TCA_TAPRIO_PAD,
+       __TCA_TAPRIO_ATTR_MAX,
+};
+
+#define TCA_TAPRIO_ATTR_MAX (__TCA_TAPRIO_ATTR_MAX - 1)
+
+#endif
index b17201e..b4875a9 100644 (file)
@@ -220,4 +220,12 @@ struct prctl_mm_map {
 # define PR_SPEC_DISABLE               (1UL << 2)
 # define PR_SPEC_FORCE_DISABLE         (1UL << 3)
 
+/* Reset arm64 pointer authentication keys */
+#define PR_PAC_RESET_KEYS              54
+# define PR_PAC_APIAKEY                        (1UL << 0)
+# define PR_PAC_APIBKEY                        (1UL << 1)
+# define PR_PAC_APDAKEY                        (1UL << 2)
+# define PR_PAC_APDBKEY                        (1UL << 3)
+# define PR_PAC_APGAKEY                        (1UL << 4)
+
 #endif /* _LINUX_PRCTL_H */
index 84c3de8..40d028e 100644 (file)
  * device configuration.
  */
 
+#include <linux/vhost_types.h>
 #include <linux/types.h>
-#include <linux/compiler.h>
 #include <linux/ioctl.h>
-#include <linux/virtio_config.h>
-#include <linux/virtio_ring.h>
-
-struct vhost_vring_state {
-       unsigned int index;
-       unsigned int num;
-};
-
-struct vhost_vring_file {
-       unsigned int index;
-       int fd; /* Pass -1 to unbind from file. */
-
-};
-
-struct vhost_vring_addr {
-       unsigned int index;
-       /* Option flags. */
-       unsigned int flags;
-       /* Flag values: */
-       /* Whether log address is valid. If set enables logging. */
-#define VHOST_VRING_F_LOG 0
-
-       /* Start of array of descriptors (virtually contiguous) */
-       __u64 desc_user_addr;
-       /* Used structure address. Must be 32 bit aligned */
-       __u64 used_user_addr;
-       /* Available structure address. Must be 16 bit aligned */
-       __u64 avail_user_addr;
-       /* Logging support. */
-       /* Log writes to used structure, at offset calculated from specified
-        * address. Address must be 32 bit aligned. */
-       __u64 log_guest_addr;
-};
-
-/* no alignment requirement */
-struct vhost_iotlb_msg {
-       __u64 iova;
-       __u64 size;
-       __u64 uaddr;
-#define VHOST_ACCESS_RO      0x1
-#define VHOST_ACCESS_WO      0x2
-#define VHOST_ACCESS_RW      0x3
-       __u8 perm;
-#define VHOST_IOTLB_MISS           1
-#define VHOST_IOTLB_UPDATE         2
-#define VHOST_IOTLB_INVALIDATE     3
-#define VHOST_IOTLB_ACCESS_FAIL    4
-       __u8 type;
-};
-
-#define VHOST_IOTLB_MSG 0x1
-#define VHOST_IOTLB_MSG_V2 0x2
-
-struct vhost_msg {
-       int type;
-       union {
-               struct vhost_iotlb_msg iotlb;
-               __u8 padding[64];
-       };
-};
-
-struct vhost_msg_v2 {
-       __u32 type;
-       __u32 reserved;
-       union {
-               struct vhost_iotlb_msg iotlb;
-               __u8 padding[64];
-       };
-};
-
-struct vhost_memory_region {
-       __u64 guest_phys_addr;
-       __u64 memory_size; /* bytes */
-       __u64 userspace_addr;
-       __u64 flags_padding; /* No flags are currently specified. */
-};
-
-/* All region addresses and sizes must be 4K aligned. */
-#define VHOST_PAGE_SIZE 0x1000
-
-struct vhost_memory {
-       __u32 nregions;
-       __u32 padding;
-       struct vhost_memory_region regions[0];
-};
 
 /* ioctls */
 
@@ -186,31 +101,7 @@ struct vhost_memory {
  * device.  This can be used to stop the ring (e.g. for migration). */
 #define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
 
-/* Feature bits */
-/* Log all write descriptors. Can be changed while device is active. */
-#define VHOST_F_LOG_ALL 26
-/* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */
-#define VHOST_NET_F_VIRTIO_NET_HDR 27
-
-/* VHOST_SCSI specific definitions */
-
-/*
- * Used by QEMU userspace to ensure a consistent vhost-scsi ABI.
- *
- * ABI Rev 0: July 2012 version starting point for v3.6-rc merge candidate +
- *            RFC-v2 vhost-scsi userspace.  Add GET_ABI_VERSION ioctl usage
- * ABI Rev 1: January 2013. Ignore vhost_tpgt filed in struct vhost_scsi_target.
- *            All the targets under vhost_wwpn can be seen and used by guset.
- */
-
-#define VHOST_SCSI_ABI_VERSION 1
-
-struct vhost_scsi_target {
-       int abi_version;
-       char vhost_wwpn[224]; /* TRANSPORT_IQN_LEN */
-       unsigned short vhost_tpgt;
-       unsigned short reserved;
-};
+/* VHOST_SCSI specific defines */
 
 #define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target)
 #define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target)
index f81e549..4db7475 100644 (file)
@@ -1,2 +1,3 @@
 libbpf_version.h
 FEATURE-DUMP.libbpf
+test_libbpf
index 056f383..607aae4 100644 (file)
@@ -132,6 +132,20 @@ For example, if current state of ``libbpf.map`` is:
 Format of version script and ways to handle ABI changes, including
 incompatible ones, described in details in [1].
 
+Stand-alone build
+=================
+
+Under https://github.com/libbpf/libbpf there is a (semi-)automated
+mirror of the mainline's version of libbpf for a stand-alone build.
+
+However, all changes to libbpf's code base must be upstreamed through
+the mainline kernel tree.
+
+License
+=======
+
+libbpf is dual-licensed under LGPL 2.1 and BSD 2-Clause.
+
 Links
 =====
 
index 3caaa34..88cbd11 100644 (file)
@@ -65,6 +65,17 @@ static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
        return syscall(__NR_bpf, cmd, attr, size);
 }
 
+static inline int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size)
+{
+       int fd;
+
+       do {
+               fd = sys_bpf(BPF_PROG_LOAD, attr, size);
+       } while (fd < 0 && errno == EAGAIN);
+
+       return fd;
+}
+
 int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr)
 {
        __u32 name_len = create_attr->name ? strlen(create_attr->name) : 0;
@@ -232,7 +243,7 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
        memcpy(attr.prog_name, load_attr->name,
               min(name_len, BPF_OBJ_NAME_LEN - 1));
 
-       fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+       fd = sys_bpf_prog_load(&attr, sizeof(attr));
        if (fd >= 0)
                return fd;
 
@@ -269,7 +280,7 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
                        break;
                }
 
-               fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+               fd = sys_bpf_prog_load(&attr, sizeof(attr));
 
                if (fd >= 0)
                        goto done;
@@ -283,7 +294,7 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
        attr.log_size = log_buf_sz;
        attr.log_level = 1;
        log_buf[0] = 0;
-       fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+       fd = sys_bpf_prog_load(&attr, sizeof(attr));
 done:
        free(finfo);
        free(linfo);
@@ -328,7 +339,7 @@ int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
        attr.kern_version = kern_version;
        attr.prog_flags = prog_flags;
 
-       return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+       return sys_bpf_prog_load(&attr, sizeof(attr));
 }
 
 int bpf_map_update_elem(int fd, const void *key, const void *value,
index 8b31c0e..d463761 100644 (file)
@@ -194,13 +194,13 @@ void tep_set_page_size(struct tep_handle *pevent, int _page_size)
 }
 
 /**
- * tep_is_file_bigendian - get if the file is in big endian order
+ * tep_file_bigendian - get if the file is in big endian order
  * @pevent: a handle to the tep_handle
  *
  * This returns if the file is in big endian order
  * If @pevent is NULL, 0 is returned.
  */
-int tep_is_file_bigendian(struct tep_handle *pevent)
+int tep_file_bigendian(struct tep_handle *pevent)
 {
        if(pevent)
                return pevent->file_bigendian;
index 9a092dd..35833ee 100644 (file)
@@ -7,7 +7,7 @@
 #ifndef _PARSE_EVENTS_INT_H
 #define _PARSE_EVENTS_INT_H
 
-struct cmdline;
+struct tep_cmdline;
 struct cmdline_list;
 struct func_map;
 struct func_list;
@@ -36,7 +36,7 @@ struct tep_handle {
        int long_size;
        int page_size;
 
-       struct cmdline *cmdlines;
+       struct tep_cmdline *cmdlines;
        struct cmdline_list *cmdlist;
        int cmdline_count;
 
index 69a96e3..abd4fa5 100644 (file)
@@ -124,15 +124,15 @@ struct tep_print_arg *alloc_arg(void)
        return calloc(1, sizeof(struct tep_print_arg));
 }
 
-struct cmdline {
+struct tep_cmdline {
        char *comm;
        int pid;
 };
 
 static int cmdline_cmp(const void *a, const void *b)
 {
-       const struct cmdline *ca = a;
-       const struct cmdline *cb = b;
+       const struct tep_cmdline *ca = a;
+       const struct tep_cmdline *cb = b;
 
        if (ca->pid < cb->pid)
                return -1;
@@ -152,7 +152,7 @@ static int cmdline_init(struct tep_handle *pevent)
 {
        struct cmdline_list *cmdlist = pevent->cmdlist;
        struct cmdline_list *item;
-       struct cmdline *cmdlines;
+       struct tep_cmdline *cmdlines;
        int i;
 
        cmdlines = malloc(sizeof(*cmdlines) * pevent->cmdline_count);
@@ -179,8 +179,8 @@ static int cmdline_init(struct tep_handle *pevent)
 
 static const char *find_cmdline(struct tep_handle *pevent, int pid)
 {
-       const struct cmdline *comm;
-       struct cmdline key;
+       const struct tep_cmdline *comm;
+       struct tep_cmdline key;
 
        if (!pid)
                return "<idle>";
@@ -208,8 +208,8 @@ static const char *find_cmdline(struct tep_handle *pevent, int pid)
  */
 int tep_pid_is_registered(struct tep_handle *pevent, int pid)
 {
-       const struct cmdline *comm;
-       struct cmdline key;
+       const struct tep_cmdline *comm;
+       struct tep_cmdline key;
 
        if (!pid)
                return 1;
@@ -232,11 +232,13 @@ int tep_pid_is_registered(struct tep_handle *pevent, int pid)
  * we must add this pid. This is much slower than when cmdlines
  * are added before the array is initialized.
  */
-static int add_new_comm(struct tep_handle *pevent, const char *comm, int pid)
+static int add_new_comm(struct tep_handle *pevent,
+                       const char *comm, int pid, bool override)
 {
-       struct cmdline *cmdlines = pevent->cmdlines;
-       const struct cmdline *cmdline;
-       struct cmdline key;
+       struct tep_cmdline *cmdlines = pevent->cmdlines;
+       struct tep_cmdline *cmdline;
+       struct tep_cmdline key;
+       char *new_comm;
 
        if (!pid)
                return 0;
@@ -247,8 +249,19 @@ static int add_new_comm(struct tep_handle *pevent, const char *comm, int pid)
        cmdline = bsearch(&key, pevent->cmdlines, pevent->cmdline_count,
                       sizeof(*pevent->cmdlines), cmdline_cmp);
        if (cmdline) {
-               errno = EEXIST;
-               return -1;
+               if (!override) {
+                       errno = EEXIST;
+                       return -1;
+               }
+               new_comm = strdup(comm);
+               if (!new_comm) {
+                       errno = ENOMEM;
+                       return -1;
+               }
+               free(cmdline->comm);
+               cmdline->comm = new_comm;
+
+               return 0;
        }
 
        cmdlines = realloc(cmdlines, sizeof(*cmdlines) * (pevent->cmdline_count + 1));
@@ -275,21 +288,13 @@ static int add_new_comm(struct tep_handle *pevent, const char *comm, int pid)
        return 0;
 }
 
-/**
- * tep_register_comm - register a pid / comm mapping
- * @pevent: handle for the pevent
- * @comm: the command line to register
- * @pid: the pid to map the command line to
- *
- * This adds a mapping to search for command line names with
- * a given pid. The comm is duplicated.
- */
-int tep_register_comm(struct tep_handle *pevent, const char *comm, int pid)
+static int _tep_register_comm(struct tep_handle *pevent,
+                             const char *comm, int pid, bool override)
 {
        struct cmdline_list *item;
 
        if (pevent->cmdlines)
-               return add_new_comm(pevent, comm, pid);
+               return add_new_comm(pevent, comm, pid, override);
 
        item = malloc(sizeof(*item));
        if (!item)
@@ -312,6 +317,40 @@ int tep_register_comm(struct tep_handle *pevent, const char *comm, int pid)
        return 0;
 }
 
+/**
+ * tep_register_comm - register a pid / comm mapping
+ * @pevent: handle for the pevent
+ * @comm: the command line to register
+ * @pid: the pid to map the command line to
+ *
+ * This adds a mapping to search for command line names with
+ * a given pid. The comm is duplicated. If a command with the same pid
+ * already exist, -1 is returned and errno is set to EEXIST
+ */
+int tep_register_comm(struct tep_handle *pevent, const char *comm, int pid)
+{
+       return _tep_register_comm(pevent, comm, pid, false);
+}
+
+/**
+ * tep_override_comm - register a pid / comm mapping
+ * @pevent: handle for the pevent
+ * @comm: the command line to register
+ * @pid: the pid to map the command line to
+ *
+ * This adds a mapping to search for command line names with
+ * a given pid. The comm is duplicated. If a command with the same pid
+ * already exist, the command string is udapted with the new one
+ */
+int tep_override_comm(struct tep_handle *pevent, const char *comm, int pid)
+{
+       if (!pevent->cmdlines && cmdline_init(pevent)) {
+               errno = ENOMEM;
+               return -1;
+       }
+       return _tep_register_comm(pevent, comm, pid, true);
+}
+
 int tep_register_trace_clock(struct tep_handle *pevent, const char *trace_clock)
 {
        pevent->trace_clock = strdup(trace_clock);
@@ -5227,18 +5266,6 @@ int tep_data_type(struct tep_handle *pevent, struct tep_record *rec)
 }
 
 /**
- * tep_data_event_from_type - find the event by a given type
- * @pevent: a handle to the pevent
- * @type: the type of the event.
- *
- * This returns the event form a given @type;
- */
-struct tep_event *tep_data_event_from_type(struct tep_handle *pevent, int type)
-{
-       return tep_find_event(pevent, type);
-}
-
-/**
  * tep_data_pid - parse the PID from record
  * @pevent: a handle to the pevent
  * @rec: the record to parse
@@ -5292,8 +5319,8 @@ const char *tep_data_comm_from_pid(struct tep_handle *pevent, int pid)
        return comm;
 }
 
-static struct cmdline *
-pid_from_cmdlist(struct tep_handle *pevent, const char *comm, struct cmdline *next)
+static struct tep_cmdline *
+pid_from_cmdlist(struct tep_handle *pevent, const char *comm, struct tep_cmdline *next)
 {
        struct cmdline_list *cmdlist = (struct cmdline_list *)next;
 
@@ -5305,7 +5332,7 @@ pid_from_cmdlist(struct tep_handle *pevent, const char *comm, struct cmdline *ne
        while (cmdlist && strcmp(cmdlist->comm, comm) != 0)
                cmdlist = cmdlist->next;
 
-       return (struct cmdline *)cmdlist;
+       return (struct tep_cmdline *)cmdlist;
 }
 
 /**
@@ -5321,10 +5348,10 @@ pid_from_cmdlist(struct tep_handle *pevent, const char *comm, struct cmdline *ne
  * next pid.
  * Also, it does a linear search, so it may be slow.
  */
-struct cmdline *tep_data_pid_from_comm(struct tep_handle *pevent, const char *comm,
-                                      struct cmdline *next)
+struct tep_cmdline *tep_data_pid_from_comm(struct tep_handle *pevent, const char *comm,
+                                          struct tep_cmdline *next)
 {
-       struct cmdline *cmdline;
+       struct tep_cmdline *cmdline;
 
        /*
         * If the cmdlines have not been converted yet, then use
@@ -5363,7 +5390,7 @@ struct cmdline *tep_data_pid_from_comm(struct tep_handle *pevent, const char *co
  * Returns the pid for a give cmdline. If @cmdline is NULL, then
  * -1 is returned.
  */
-int tep_cmdline_pid(struct tep_handle *pevent, struct cmdline *cmdline)
+int tep_cmdline_pid(struct tep_handle *pevent, struct tep_cmdline *cmdline)
 {
        struct cmdline_list *cmdlist = (struct cmdline_list *)cmdline;
 
@@ -6593,6 +6620,12 @@ static struct tep_event *search_event(struct tep_handle *pevent, int id,
  *
  * If @id is >= 0, then it is used to find the event.
  * else @sys_name and @event_name are used.
+ *
+ * Returns:
+ *  TEP_REGISTER_SUCCESS_OVERWRITE if an existing handler is overwritten
+ *  TEP_REGISTER_SUCCESS if a new handler is registered successfully
+ *  negative TEP_ERRNO_... in case of an error
+ *
  */
 int tep_register_event_handler(struct tep_handle *pevent, int id,
                               const char *sys_name, const char *event_name,
@@ -6610,7 +6643,7 @@ int tep_register_event_handler(struct tep_handle *pevent, int id,
 
        event->handler = func;
        event->context = context;
-       return 0;
+       return TEP_REGISTER_SUCCESS_OVERWRITE;
 
  not_found:
        /* Save for later use. */
@@ -6640,7 +6673,7 @@ int tep_register_event_handler(struct tep_handle *pevent, int id,
        pevent->handlers = handle;
        handle->context = context;
 
-       return -1;
+       return TEP_REGISTER_SUCCESS;
 }
 
 static int handle_matches(struct event_handler *handler, int id,
@@ -6723,8 +6756,10 @@ struct tep_handle *tep_alloc(void)
 {
        struct tep_handle *pevent = calloc(1, sizeof(*pevent));
 
-       if (pevent)
+       if (pevent) {
                pevent->ref_count = 1;
+               pevent->host_bigendian = tep_host_bigendian();
+       }
 
        return pevent;
 }
index 35d3708..aec48f2 100644 (file)
@@ -432,6 +432,7 @@ int tep_set_function_resolver(struct tep_handle *pevent,
                              tep_func_resolver_t *func, void *priv);
 void tep_reset_function_resolver(struct tep_handle *pevent);
 int tep_register_comm(struct tep_handle *pevent, const char *comm, int pid);
+int tep_override_comm(struct tep_handle *pevent, const char *comm, int pid);
 int tep_register_trace_clock(struct tep_handle *pevent, const char *trace_clock);
 int tep_register_function(struct tep_handle *pevent, char *name,
                          unsigned long long addr, char *mod);
@@ -484,6 +485,11 @@ int tep_print_func_field(struct trace_seq *s, const char *fmt,
                         struct tep_event *event, const char *name,
                         struct tep_record *record, int err);
 
+enum tep_reg_handler {
+       TEP_REGISTER_SUCCESS = 0,
+       TEP_REGISTER_SUCCESS_OVERWRITE,
+};
+
 int tep_register_event_handler(struct tep_handle *pevent, int id,
                               const char *sys_name, const char *event_name,
                               tep_event_handler_func func, void *context);
@@ -520,15 +526,14 @@ tep_find_event_by_record(struct tep_handle *pevent, struct tep_record *record);
 void tep_data_lat_fmt(struct tep_handle *pevent,
                      struct trace_seq *s, struct tep_record *record);
 int tep_data_type(struct tep_handle *pevent, struct tep_record *rec);
-struct tep_event *tep_data_event_from_type(struct tep_handle *pevent, int type);
 int tep_data_pid(struct tep_handle *pevent, struct tep_record *rec);
 int tep_data_preempt_count(struct tep_handle *pevent, struct tep_record *rec);
 int tep_data_flags(struct tep_handle *pevent, struct tep_record *rec);
 const char *tep_data_comm_from_pid(struct tep_handle *pevent, int pid);
-struct cmdline;
-struct cmdline *tep_data_pid_from_comm(struct tep_handle *pevent, const char *comm,
-                                      struct cmdline *next);
-int tep_cmdline_pid(struct tep_handle *pevent, struct cmdline *cmdline);
+struct tep_cmdline;
+struct tep_cmdline *tep_data_pid_from_comm(struct tep_handle *pevent, const char *comm,
+                                          struct tep_cmdline *next);
+int tep_cmdline_pid(struct tep_handle *pevent, struct tep_cmdline *cmdline);
 
 void tep_print_field(struct trace_seq *s, void *data,
                     struct tep_format_field *field);
@@ -553,7 +558,7 @@ int tep_get_long_size(struct tep_handle *pevent);
 void tep_set_long_size(struct tep_handle *pevent, int long_size);
 int tep_get_page_size(struct tep_handle *pevent);
 void tep_set_page_size(struct tep_handle *pevent, int _page_size);
-int tep_is_file_bigendian(struct tep_handle *pevent);
+int tep_file_bigendian(struct tep_handle *pevent);
 void tep_set_file_bigendian(struct tep_handle *pevent, enum tep_endian endian);
 int tep_is_host_bigendian(struct tep_handle *pevent);
 void tep_set_host_bigendian(struct tep_handle *pevent, enum tep_endian endian);
index 754050e..64b9c25 100644 (file)
@@ -389,7 +389,7 @@ static int kvm_mmu_print_role(struct trace_seq *s, struct tep_record *record,
         * We can only use the structure if file is of the same
         * endianness.
         */
-       if (tep_is_file_bigendian(event->pevent) ==
+       if (tep_file_bigendian(event->pevent) ==
            tep_is_host_bigendian(event->pevent)) {
 
                trace_seq_printf(s, "%u q%u%s %s%s %spae %snxe %swp%s%s%s",
index 8ff1d55..8d5ecd2 100644 (file)
@@ -100,7 +100,8 @@ static void expand_buffer(struct trace_seq *s)
  * @fmt: printf format string
  *
  * It returns 0 if the trace oversizes the buffer's free
- * space, 1 otherwise.
+ * space, the number of characters printed, or a negative
+ * value in case of an error.
  *
  * The tracer may use either sequence operations or its own
  * copy to user routines. To simplify formating of a trace
@@ -129,9 +130,10 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
                goto try_again;
        }
 
-       s->len += ret;
+       if (ret > 0)
+               s->len += ret;
 
-       return 1;
+       return ret;
 }
 
 /**
@@ -139,6 +141,10 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
  * @s: trace sequence descriptor
  * @fmt: printf format string
  *
+ * It returns 0 if the trace oversizes the buffer's free
+ * space, the number of characters printed, or a negative
+ * value in case of an error.
+ * *
  * The tracer may use either sequence operations or its own
  * copy to user routines. To simplify formating of a trace
  * trace_seq_printf is used to store strings into a special
@@ -163,9 +169,10 @@ trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
                goto try_again;
        }
 
-       s->len += ret;
+       if (ret > 0)
+               s->len += ret;
 
-       return len;
+       return ret;
 }
 
 /**
index 095aebd..e6150f2 100644 (file)
@@ -19,8 +19,11 @@ C2C stands for Cache To Cache.
 The perf c2c tool provides means for Shared Data C2C/HITM analysis. It allows
 you to track down the cacheline contentions.
 
-The tool is based on x86's load latency and precise store facility events
-provided by Intel CPUs. These events provide:
+On x86, the tool is based on load latency and precise store facility events
+provided by Intel CPUs. On PowerPC, the tool uses random instruction sampling
+with thresholding feature.
+
+These events provide:
   - memory address of the access
   - type of the access (load and store details)
   - latency (in cycles) of the load access
@@ -46,7 +49,7 @@ RECORD OPTIONS
 
 -l::
 --ldlat::
-       Configure mem-loads latency.
+       Configure mem-loads latency. (x86 only)
 
 -k::
 --all-kernel::
@@ -119,11 +122,16 @@ Following perf record options are configured by default:
   -W,-d,--phys-data,--sample-cpu
 
 Unless specified otherwise with '-e' option, following events are monitored by
-default:
+default on x86:
 
   cpu/mem-loads,ldlat=30/P
   cpu/mem-stores/P
 
+and following on PowerPC:
+
+  cpu/mem-loads/
+  cpu/mem-stores/
+
 User can pass any 'perf record' option behind '--' mark, like (to enable
 callchains and system wide monitoring):
 
index f8d2167..199ea0f 100644 (file)
@@ -82,7 +82,7 @@ RECORD OPTIONS
        Be more verbose (show counter open errors, etc)
 
 --ldlat <n>::
-       Specify desired latency for loads event.
+       Specify desired latency for loads event. (x86 only)
 
 In addition, for report all perf report options are valid, and for record
 all perf record options.
index ff29c33..0ee6795 100644 (file)
@@ -524,12 +524,14 @@ $(arch_errno_name_array): $(arch_errno_tbl)
 
 all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
 
+# Create python binding output directory if not already present
+_dummy := $(shell [ -d '$(OUTPUT)python' ] || mkdir -p '$(OUTPUT)python')
+
 $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST)
        $(QUIET_GEN)LDSHARED="$(CC) -pthread -shared" \
         CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \
          $(PYTHON_WORD) util/setup.py \
          --quiet build_ext; \
-       mkdir -p $(OUTPUT)python && \
        cp $(PYTHON_EXTBUILD_LIB)perf*.so $(OUTPUT)python/
 
 please_set_SHELL_PATH_to_a_more_modern_shell:
@@ -660,12 +662,12 @@ $(OUTPUT)perf-%: %.o $(PERFLIBS)
        $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS)
 
 ifndef NO_PERF_READ_VDSO32
-$(OUTPUT)perf-read-vdso32: perf-read-vdso.c util/find-vdso-map.c
+$(OUTPUT)perf-read-vdso32: perf-read-vdso.c util/find-map.c
        $(QUIET_CC)$(CC) -m32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c
 endif
 
 ifndef NO_PERF_READ_VDSOX32
-$(OUTPUT)perf-read-vdsox32: perf-read-vdso.c util/find-vdso-map.c
+$(OUTPUT)perf-read-vdsox32: perf-read-vdso.c util/find-map.c
        $(QUIET_CC)$(CC) -mx32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c
 endif
 
index 883c57f..d9ae273 100644 (file)
@@ -1,4 +1,5 @@
 libperf-y += regs_load.o
 libperf-y += dwarf-unwind.o
+libperf-y += vectors-page.o
 
 libperf-y += arch-tests.o
index 5b1543c..6848101 100644 (file)
@@ -11,6 +11,10 @@ struct test arch_tests[] = {
        },
 #endif
        {
+               .desc = "Vectors page",
+               .func = test__vectors_page,
+       },
+       {
                .func = NULL,
        },
 };
diff --git a/tools/perf/arch/arm/tests/vectors-page.c b/tools/perf/arch/arm/tests/vectors-page.c
new file mode 100644 (file)
index 0000000..7ffdd79
--- /dev/null
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <stdio.h>
+#include <string.h>
+#include <linux/compiler.h>
+
+#include "debug.h"
+#include "tests/tests.h"
+#include "util/find-map.c"
+
+#define VECTORS__MAP_NAME "[vectors]"
+
+int test__vectors_page(struct test *test __maybe_unused,
+                      int subtest __maybe_unused)
+{
+       void *start, *end;
+
+       if (find_map(&start, &end, VECTORS__MAP_NAME)) {
+               pr_err("%s not found, is CONFIG_KUSER_HELPERS enabled?\n",
+                      VECTORS__MAP_NAME);
+               return TEST_FAIL;
+       }
+
+       return TEST_OK;
+}
index a111239..e58d00d 100644 (file)
@@ -14,18 +14,25 @@ PERF_HAVE_JITDUMP := 1
 out    := $(OUTPUT)arch/powerpc/include/generated/asm
 header32 := $(out)/syscalls_32.c
 header64 := $(out)/syscalls_64.c
-sysdef := $(srctree)/tools/arch/powerpc/include/uapi/asm/unistd.h
-sysprf := $(srctree)/tools/perf/arch/powerpc/entry/syscalls/
+syskrn := $(srctree)/arch/powerpc/kernel/syscalls/syscall.tbl
+sysprf := $(srctree)/tools/perf/arch/powerpc/entry/syscalls
+sysdef := $(sysprf)/syscall.tbl
 systbl := $(sysprf)/mksyscalltbl
 
 # Create output directory if not already present
 _dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
 
 $(header64): $(sysdef) $(systbl)
-       $(Q)$(SHELL) '$(systbl)' '64' '$(CC)' $(sysdef) > $@
+       @(test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \
+       (diff -B $(sysdef) $(syskrn) >/dev/null) \
+       || echo "Warning: Kernel ABI header at '$(sysdef)' differs from latest version at '$(syskrn)'" >&2 )) || true
+       $(Q)$(SHELL) '$(systbl)' '64' $(sysdef) > $@
 
 $(header32): $(sysdef) $(systbl)
-       $(Q)$(SHELL) '$(systbl)' '32' '$(CC)' $(sysdef) > $@
+       @(test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \
+       (diff -B $(sysdef) $(syskrn) >/dev/null) \
+       || echo "Warning: Kernel ABI header at '$(sysdef)' differs from latest version at '$(syskrn)'" >&2 )) || true
+       $(Q)$(SHELL) '$(systbl)' '32' $(sysdef) > $@
 
 clean::
        $(call QUIET_CLEAN, powerpc) $(RM) $(header32) $(header64)
index ef52e1d..6c58060 100755 (executable)
@@ -9,10 +9,9 @@
 # Changed by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
 
 wordsize=$1
-gcc=$2
-input=$3
+SYSCALL_TBL=$2
 
-if ! test -r $input; then
+if ! test -r $SYSCALL_TBL; then
        echo "Could not read input file" >&2
        exit 1
 fi
@@ -20,18 +19,21 @@ fi
 create_table()
 {
        local wordsize=$1
-       local max_nr
+       local max_nr nr abi sc discard
+       max_nr=-1
+       nr=0
 
        echo "static const char *syscalltbl_powerpc_${wordsize}[] = {"
-       while read sc nr; do
-               printf '\t[%d] = "%s",\n' $nr $sc
-               max_nr=$nr
+       while read nr abi sc discard; do
+               if [ "$max_nr" -lt "$nr" ]; then
+                       printf '\t[%d] = "%s",\n' $nr $sc
+                       max_nr=$nr
+               fi
        done
        echo '};'
        echo "#define SYSCALLTBL_POWERPC_${wordsize}_MAX_ID $max_nr"
 }
 
-$gcc -m${wordsize} -E -dM -x c  $input        \
-       |sed -ne 's/^#define __NR_//p' \
-       |sort -t' ' -k2 -nu            \
+grep -E "^[[:digit:]]+[[:space:]]+(common|spu|nospu|${wordsize})" $SYSCALL_TBL \
+       |sort -k1 -n                                                           \
        |create_table ${wordsize}
diff --git a/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl b/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
new file mode 100644 (file)
index 0000000..db3bbb8
--- /dev/null
@@ -0,0 +1,427 @@
+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+#
+# system call numbers and entry vectors for powerpc
+#
+# The format is:
+# <number> <abi> <name> <entry point> <compat entry point>
+#
+# The <abi> can be common, spu, nospu, 64, or 32 for this file.
+#
+0      nospu   restart_syscall                 sys_restart_syscall
+1      nospu   exit                            sys_exit
+2      nospu   fork                            ppc_fork
+3      common  read                            sys_read
+4      common  write                           sys_write
+5      common  open                            sys_open                        compat_sys_open
+6      common  close                           sys_close
+7      common  waitpid                         sys_waitpid
+8      common  creat                           sys_creat
+9      common  link                            sys_link
+10     common  unlink                          sys_unlink
+11     nospu   execve                          sys_execve                      compat_sys_execve
+12     common  chdir                           sys_chdir
+13     common  time                            sys_time                        compat_sys_time
+14     common  mknod                           sys_mknod
+15     common  chmod                           sys_chmod
+16     common  lchown                          sys_lchown
+17     common  break                           sys_ni_syscall
+18     32      oldstat                         sys_stat                        sys_ni_syscall
+18     64      oldstat                         sys_ni_syscall
+18     spu     oldstat                         sys_ni_syscall
+19     common  lseek                           sys_lseek                       compat_sys_lseek
+20     common  getpid                          sys_getpid
+21     nospu   mount                           sys_mount                       compat_sys_mount
+22     32      umount                          sys_oldumount
+22     64      umount                          sys_ni_syscall
+22     spu     umount                          sys_ni_syscall
+23     common  setuid                          sys_setuid
+24     common  getuid                          sys_getuid
+25     common  stime                           sys_stime                       compat_sys_stime
+26     nospu   ptrace                          sys_ptrace                      compat_sys_ptrace
+27     common  alarm                           sys_alarm
+28     32      oldfstat                        sys_fstat                       sys_ni_syscall
+28     64      oldfstat                        sys_ni_syscall
+28     spu     oldfstat                        sys_ni_syscall
+29     nospu   pause                           sys_pause
+30     nospu   utime                           sys_utime                       compat_sys_utime
+31     common  stty                            sys_ni_syscall
+32     common  gtty                            sys_ni_syscall
+33     common  access                          sys_access
+34     common  nice                            sys_nice
+35     common  ftime                           sys_ni_syscall
+36     common  sync                            sys_sync
+37     common  kill                            sys_kill
+38     common  rename                          sys_rename
+39     common  mkdir                           sys_mkdir
+40     common  rmdir                           sys_rmdir
+41     common  dup                             sys_dup
+42     common  pipe                            sys_pipe
+43     common  times                           sys_times                       compat_sys_times
+44     common  prof                            sys_ni_syscall
+45     common  brk                             sys_brk
+46     common  setgid                          sys_setgid
+47     common  getgid                          sys_getgid
+48     nospu   signal                          sys_signal
+49     common  geteuid                         sys_geteuid
+50     common  getegid                         sys_getegid
+51     nospu   acct                            sys_acct
+52     nospu   umount2                         sys_umount
+53     common  lock                            sys_ni_syscall
+54     common  ioctl                           sys_ioctl                       compat_sys_ioctl
+55     common  fcntl                           sys_fcntl                       compat_sys_fcntl
+56     common  mpx                             sys_ni_syscall
+57     common  setpgid                         sys_setpgid
+58     common  ulimit                          sys_ni_syscall
+59     32      oldolduname                     sys_olduname
+59     64      oldolduname                     sys_ni_syscall
+59     spu     oldolduname                     sys_ni_syscall
+60     common  umask                           sys_umask
+61     common  chroot                          sys_chroot
+62     nospu   ustat                           sys_ustat                       compat_sys_ustat
+63     common  dup2                            sys_dup2
+64     common  getppid                         sys_getppid
+65     common  getpgrp                         sys_getpgrp
+66     common  setsid                          sys_setsid
+67     32      sigaction                       sys_sigaction                   compat_sys_sigaction
+67     64      sigaction                       sys_ni_syscall
+67     spu     sigaction                       sys_ni_syscall
+68     common  sgetmask                        sys_sgetmask
+69     common  ssetmask                        sys_ssetmask
+70     common  setreuid                        sys_setreuid
+71     common  setregid                        sys_setregid
+72     32      sigsuspend                      sys_sigsuspend
+72     64      sigsuspend                      sys_ni_syscall
+72     spu     sigsuspend                      sys_ni_syscall
+73     32      sigpending                      sys_sigpending                  compat_sys_sigpending
+73     64      sigpending                      sys_ni_syscall
+73     spu     sigpending                      sys_ni_syscall
+74     common  sethostname                     sys_sethostname
+75     common  setrlimit                       sys_setrlimit                   compat_sys_setrlimit
+76     32      getrlimit                       sys_old_getrlimit               compat_sys_old_getrlimit
+76     64      getrlimit                       sys_ni_syscall
+76     spu     getrlimit                       sys_ni_syscall
+77     common  getrusage                       sys_getrusage                   compat_sys_getrusage
+78     common  gettimeofday                    sys_gettimeofday                compat_sys_gettimeofday
+79     common  settimeofday                    sys_settimeofday                compat_sys_settimeofday
+80     common  getgroups                       sys_getgroups
+81     common  setgroups                       sys_setgroups
+82     32      select                          ppc_select                      sys_ni_syscall
+82     64      select                          sys_ni_syscall
+82     spu     select                          sys_ni_syscall
+83     common  symlink                         sys_symlink
+84     32      oldlstat                        sys_lstat                       sys_ni_syscall
+84     64      oldlstat                        sys_ni_syscall
+84     spu     oldlstat                        sys_ni_syscall
+85     common  readlink                        sys_readlink
+86     nospu   uselib                          sys_uselib
+87     nospu   swapon                          sys_swapon
+88     nospu   reboot                          sys_reboot
+89     32      readdir                         sys_old_readdir                 compat_sys_old_readdir
+89     64      readdir                         sys_ni_syscall
+89     spu     readdir                         sys_ni_syscall
+90     common  mmap                            sys_mmap
+91     common  munmap                          sys_munmap
+92     common  truncate                        sys_truncate                    compat_sys_truncate
+93     common  ftruncate                       sys_ftruncate                   compat_sys_ftruncate
+94     common  fchmod                          sys_fchmod
+95     common  fchown                          sys_fchown
+96     common  getpriority                     sys_getpriority
+97     common  setpriority                     sys_setpriority
+98     common  profil                          sys_ni_syscall
+99     nospu   statfs                          sys_statfs                      compat_sys_statfs
+100    nospu   fstatfs                         sys_fstatfs                     compat_sys_fstatfs
+101    common  ioperm                          sys_ni_syscall
+102    common  socketcall                      sys_socketcall                  compat_sys_socketcall
+103    common  syslog                          sys_syslog
+104    common  setitimer                       sys_setitimer                   compat_sys_setitimer
+105    common  getitimer                       sys_getitimer                   compat_sys_getitimer
+106    common  stat                            sys_newstat                     compat_sys_newstat
+107    common  lstat                           sys_newlstat                    compat_sys_newlstat
+108    common  fstat                           sys_newfstat                    compat_sys_newfstat
+109    32      olduname                        sys_uname
+109    64      olduname                        sys_ni_syscall
+109    spu     olduname                        sys_ni_syscall
+110    common  iopl                            sys_ni_syscall
+111    common  vhangup                         sys_vhangup
+112    common  idle                            sys_ni_syscall
+113    common  vm86                            sys_ni_syscall
+114    common  wait4                           sys_wait4                       compat_sys_wait4
+115    nospu   swapoff                         sys_swapoff
+116    common  sysinfo                         sys_sysinfo                     compat_sys_sysinfo
+117    nospu   ipc                             sys_ipc                         compat_sys_ipc
+118    common  fsync                           sys_fsync
+119    32      sigreturn                       sys_sigreturn                   compat_sys_sigreturn
+119    64      sigreturn                       sys_ni_syscall
+119    spu     sigreturn                       sys_ni_syscall
+120    nospu   clone                           ppc_clone
+121    common  setdomainname                   sys_setdomainname
+122    common  uname                           sys_newuname
+123    common  modify_ldt                      sys_ni_syscall
+124    common  adjtimex                        sys_adjtimex                    compat_sys_adjtimex
+125    common  mprotect                        sys_mprotect
+126    32      sigprocmask                     sys_sigprocmask                 compat_sys_sigprocmask
+126    64      sigprocmask                     sys_ni_syscall
+126    spu     sigprocmask                     sys_ni_syscall
+127    common  create_module                   sys_ni_syscall
+128    nospu   init_module                     sys_init_module
+129    nospu   delete_module                   sys_delete_module
+130    common  get_kernel_syms                 sys_ni_syscall
+131    nospu   quotactl                        sys_quotactl
+132    common  getpgid                         sys_getpgid
+133    common  fchdir                          sys_fchdir
+134    common  bdflush                         sys_bdflush
+135    common  sysfs                           sys_sysfs
+136    32      personality                     sys_personality                 ppc64_personality
+136    64      personality                     ppc64_personality
+136    spu     personality                     ppc64_personality
+137    common  afs_syscall                     sys_ni_syscall
+138    common  setfsuid                        sys_setfsuid
+139    common  setfsgid                        sys_setfsgid
+140    common  _llseek                         sys_llseek
+141    common  getdents                        sys_getdents                    compat_sys_getdents
+142    common  _newselect                      sys_select                      compat_sys_select
+143    common  flock                           sys_flock
+144    common  msync                           sys_msync
+145    common  readv                           sys_readv                       compat_sys_readv
+146    common  writev                          sys_writev                      compat_sys_writev
+147    common  getsid                          sys_getsid
+148    common  fdatasync                       sys_fdatasync
+149    nospu   _sysctl                         sys_sysctl                      compat_sys_sysctl
+150    common  mlock                           sys_mlock
+151    common  munlock                         sys_munlock
+152    common  mlockall                        sys_mlockall
+153    common  munlockall                      sys_munlockall
+154    common  sched_setparam                  sys_sched_setparam
+155    common  sched_getparam                  sys_sched_getparam
+156    common  sched_setscheduler              sys_sched_setscheduler
+157    common  sched_getscheduler              sys_sched_getscheduler
+158    common  sched_yield                     sys_sched_yield
+159    common  sched_get_priority_max          sys_sched_get_priority_max
+160    common  sched_get_priority_min          sys_sched_get_priority_min
+161    common  sched_rr_get_interval           sys_sched_rr_get_interval       compat_sys_sched_rr_get_interval
+162    common  nanosleep                       sys_nanosleep                   compat_sys_nanosleep
+163    common  mremap                          sys_mremap
+164    common  setresuid                       sys_setresuid
+165    common  getresuid                       sys_getresuid
+166    common  query_module                    sys_ni_syscall
+167    common  poll                            sys_poll
+168    common  nfsservctl                      sys_ni_syscall
+169    common  setresgid                       sys_setresgid
+170    common  getresgid                       sys_getresgid
+171    common  prctl                           sys_prctl
+172    nospu   rt_sigreturn                    sys_rt_sigreturn                compat_sys_rt_sigreturn
+173    nospu   rt_sigaction                    sys_rt_sigaction                compat_sys_rt_sigaction
+174    nospu   rt_sigprocmask                  sys_rt_sigprocmask              compat_sys_rt_sigprocmask
+175    nospu   rt_sigpending                   sys_rt_sigpending               compat_sys_rt_sigpending
+176    nospu   rt_sigtimedwait                 sys_rt_sigtimedwait             compat_sys_rt_sigtimedwait
+177    nospu   rt_sigqueueinfo                 sys_rt_sigqueueinfo             compat_sys_rt_sigqueueinfo
+178    nospu   rt_sigsuspend                   sys_rt_sigsuspend               compat_sys_rt_sigsuspend
+179    common  pread64                         sys_pread64                     compat_sys_pread64
+180    common  pwrite64                        sys_pwrite64                    compat_sys_pwrite64
+181    common  chown                           sys_chown
+182    common  getcwd                          sys_getcwd
+183    common  capget                          sys_capget
+184    common  capset                          sys_capset
+185    nospu   sigaltstack                     sys_sigaltstack                 compat_sys_sigaltstack
+186    32      sendfile                        sys_sendfile                    compat_sys_sendfile
+186    64      sendfile                        sys_sendfile64
+186    spu     sendfile                        sys_sendfile64
+187    common  getpmsg                         sys_ni_syscall
+188    common  putpmsg                         sys_ni_syscall
+189    nospu   vfork                           ppc_vfork
+190    common  ugetrlimit                      sys_getrlimit                   compat_sys_getrlimit
+191    common  readahead                       sys_readahead                   compat_sys_readahead
+192    32      mmap2                           sys_mmap2                       compat_sys_mmap2
+193    32      truncate64                      sys_truncate64                  compat_sys_truncate64
+194    32      ftruncate64                     sys_ftruncate64                 compat_sys_ftruncate64
+195    32      stat64                          sys_stat64
+196    32      lstat64                         sys_lstat64
+197    32      fstat64                         sys_fstat64
+198    nospu   pciconfig_read                  sys_pciconfig_read
+199    nospu   pciconfig_write                 sys_pciconfig_write
+200    nospu   pciconfig_iobase                sys_pciconfig_iobase
+201    common  multiplexer                     sys_ni_syscall
+202    common  getdents64                      sys_getdents64
+203    common  pivot_root                      sys_pivot_root
+204    32      fcntl64                         sys_fcntl64                     compat_sys_fcntl64
+205    common  madvise                         sys_madvise
+206    common  mincore                         sys_mincore
+207    common  gettid                          sys_gettid
+208    common  tkill                           sys_tkill
+209    common  setxattr                        sys_setxattr
+210    common  lsetxattr                       sys_lsetxattr
+211    common  fsetxattr                       sys_fsetxattr
+212    common  getxattr                        sys_getxattr
+213    common  lgetxattr                       sys_lgetxattr
+214    common  fgetxattr                       sys_fgetxattr
+215    common  listxattr                       sys_listxattr
+216    common  llistxattr                      sys_llistxattr
+217    common  flistxattr                      sys_flistxattr
+218    common  removexattr                     sys_removexattr
+219    common  lremovexattr                    sys_lremovexattr
+220    common  fremovexattr                    sys_fremovexattr
+221    common  futex                           sys_futex                       compat_sys_futex
+222    common  sched_setaffinity               sys_sched_setaffinity           compat_sys_sched_setaffinity
+223    common  sched_getaffinity               sys_sched_getaffinity           compat_sys_sched_getaffinity
+# 224 unused
+225    common  tuxcall                         sys_ni_syscall
+226    32      sendfile64                      sys_sendfile64                  compat_sys_sendfile64
+227    common  io_setup                        sys_io_setup                    compat_sys_io_setup
+228    common  io_destroy                      sys_io_destroy
+229    common  io_getevents                    sys_io_getevents                compat_sys_io_getevents
+230    common  io_submit                       sys_io_submit                   compat_sys_io_submit
+231    common  io_cancel                       sys_io_cancel
+232    nospu   set_tid_address                 sys_set_tid_address
+233    common  fadvise64                       sys_fadvise64                   ppc32_fadvise64
+234    nospu   exit_group                      sys_exit_group
+235    nospu   lookup_dcookie                  sys_lookup_dcookie              compat_sys_lookup_dcookie
+236    common  epoll_create                    sys_epoll_create
+237    common  epoll_ctl                       sys_epoll_ctl
+238    common  epoll_wait                      sys_epoll_wait
+239    common  remap_file_pages                sys_remap_file_pages
+240    common  timer_create                    sys_timer_create                compat_sys_timer_create
+241    common  timer_settime                   sys_timer_settime               compat_sys_timer_settime
+242    common  timer_gettime                   sys_timer_gettime               compat_sys_timer_gettime
+243    common  timer_getoverrun                sys_timer_getoverrun
+244    common  timer_delete                    sys_timer_delete
+245    common  clock_settime                   sys_clock_settime               compat_sys_clock_settime
+246    common  clock_gettime                   sys_clock_gettime               compat_sys_clock_gettime
+247    common  clock_getres                    sys_clock_getres                compat_sys_clock_getres
+248    common  clock_nanosleep                 sys_clock_nanosleep             compat_sys_clock_nanosleep
+249    32      swapcontext                     ppc_swapcontext                 ppc32_swapcontext
+249    64      swapcontext                     ppc64_swapcontext
+249    spu     swapcontext                     sys_ni_syscall
+250    common  tgkill                          sys_tgkill
+251    common  utimes                          sys_utimes                      compat_sys_utimes
+252    common  statfs64                        sys_statfs64                    compat_sys_statfs64
+253    common  fstatfs64                       sys_fstatfs64                   compat_sys_fstatfs64
+254    32      fadvise64_64                    ppc_fadvise64_64
+254    spu     fadvise64_64                    sys_ni_syscall
+255    common  rtas                            sys_rtas
+256    32      sys_debug_setcontext            sys_debug_setcontext            sys_ni_syscall
+256    64      sys_debug_setcontext            sys_ni_syscall
+256    spu     sys_debug_setcontext            sys_ni_syscall
+# 257 reserved for vserver
+258    nospu   migrate_pages                   sys_migrate_pages               compat_sys_migrate_pages
+259    nospu   mbind                           sys_mbind                       compat_sys_mbind
+260    nospu   get_mempolicy                   sys_get_mempolicy               compat_sys_get_mempolicy
+261    nospu   set_mempolicy                   sys_set_mempolicy               compat_sys_set_mempolicy
+262    nospu   mq_open                         sys_mq_open                     compat_sys_mq_open
+263    nospu   mq_unlink                       sys_mq_unlink
+264    nospu   mq_timedsend                    sys_mq_timedsend                compat_sys_mq_timedsend
+265    nospu   mq_timedreceive                 sys_mq_timedreceive             compat_sys_mq_timedreceive
+266    nospu   mq_notify                       sys_mq_notify                   compat_sys_mq_notify
+267    nospu   mq_getsetattr                   sys_mq_getsetattr               compat_sys_mq_getsetattr
+268    nospu   kexec_load                      sys_kexec_load                  compat_sys_kexec_load
+269    nospu   add_key                         sys_add_key
+270    nospu   request_key                     sys_request_key
+271    nospu   keyctl                          sys_keyctl                      compat_sys_keyctl
+272    nospu   waitid                          sys_waitid                      compat_sys_waitid
+273    nospu   ioprio_set                      sys_ioprio_set
+274    nospu   ioprio_get                      sys_ioprio_get
+275    nospu   inotify_init                    sys_inotify_init
+276    nospu   inotify_add_watch               sys_inotify_add_watch
+277    nospu   inotify_rm_watch                sys_inotify_rm_watch
+278    nospu   spu_run                         sys_spu_run
+279    nospu   spu_create                      sys_spu_create
+280    nospu   pselect6                        sys_pselect6                    compat_sys_pselect6
+281    nospu   ppoll                           sys_ppoll                       compat_sys_ppoll
+282    common  unshare                         sys_unshare
+283    common  splice                          sys_splice
+284    common  tee                             sys_tee
+285    common  vmsplice                        sys_vmsplice                    compat_sys_vmsplice
+286    common  openat                          sys_openat                      compat_sys_openat
+287    common  mkdirat                         sys_mkdirat
+288    common  mknodat                         sys_mknodat
+289    common  fchownat                        sys_fchownat
+290    common  futimesat                       sys_futimesat                   compat_sys_futimesat
+291    32      fstatat64                       sys_fstatat64
+291    64      newfstatat                      sys_newfstatat
+291    spu     newfstatat                      sys_newfstatat
+292    common  unlinkat                        sys_unlinkat
+293    common  renameat                        sys_renameat
+294    common  linkat                          sys_linkat
+295    common  symlinkat                       sys_symlinkat
+296    common  readlinkat                      sys_readlinkat
+297    common  fchmodat                        sys_fchmodat
+298    common  faccessat                       sys_faccessat
+299    common  get_robust_list                 sys_get_robust_list             compat_sys_get_robust_list
+300    common  set_robust_list                 sys_set_robust_list             compat_sys_set_robust_list
+301    common  move_pages                      sys_move_pages                  compat_sys_move_pages
+302    common  getcpu                          sys_getcpu
+303    nospu   epoll_pwait                     sys_epoll_pwait                 compat_sys_epoll_pwait
+304    common  utimensat                       sys_utimensat                   compat_sys_utimensat
+305    common  signalfd                        sys_signalfd                    compat_sys_signalfd
+306    common  timerfd_create                  sys_timerfd_create
+307    common  eventfd                         sys_eventfd
+308    common  sync_file_range2                sys_sync_file_range2            compat_sys_sync_file_range2
+309    nospu   fallocate                       sys_fallocate                   compat_sys_fallocate
+310    nospu   subpage_prot                    sys_subpage_prot
+311    common  timerfd_settime                 sys_timerfd_settime             compat_sys_timerfd_settime
+312    common  timerfd_gettime                 sys_timerfd_gettime             compat_sys_timerfd_gettime
+313    common  signalfd4                       sys_signalfd4                   compat_sys_signalfd4
+314    common  eventfd2                        sys_eventfd2
+315    common  epoll_create1                   sys_epoll_create1
+316    common  dup3                            sys_dup3
+317    common  pipe2                           sys_pipe2
+318    nospu   inotify_init1                   sys_inotify_init1
+319    common  perf_event_open                 sys_perf_event_open
+320    common  preadv                          sys_preadv                      compat_sys_preadv
+321    common  pwritev                         sys_pwritev                     compat_sys_pwritev
+322    nospu   rt_tgsigqueueinfo               sys_rt_tgsigqueueinfo           compat_sys_rt_tgsigqueueinfo
+323    nospu   fanotify_init                   sys_fanotify_init
+324    nospu   fanotify_mark                   sys_fanotify_mark               compat_sys_fanotify_mark
+325    common  prlimit64                       sys_prlimit64
+326    common  socket                          sys_socket
+327    common  bind                            sys_bind
+328    common  connect                         sys_connect
+329    common  listen                          sys_listen
+330    common  accept                          sys_accept
+331    common  getsockname                     sys_getsockname
+332    common  getpeername                     sys_getpeername
+333    common  socketpair                      sys_socketpair
+334    common  send                            sys_send
+335    common  sendto                          sys_sendto
+336    common  recv                            sys_recv                        compat_sys_recv
+337    common  recvfrom                        sys_recvfrom                    compat_sys_recvfrom
+338    common  shutdown                        sys_shutdown
+339    common  setsockopt                      sys_setsockopt                  compat_sys_setsockopt
+340    common  getsockopt                      sys_getsockopt                  compat_sys_getsockopt
+341    common  sendmsg                         sys_sendmsg                     compat_sys_sendmsg
+342    common  recvmsg                         sys_recvmsg                     compat_sys_recvmsg
+343    common  recvmmsg                        sys_recvmmsg                    compat_sys_recvmmsg
+344    common  accept4                         sys_accept4
+345    common  name_to_handle_at               sys_name_to_handle_at
+346    common  open_by_handle_at               sys_open_by_handle_at           compat_sys_open_by_handle_at
+347    common  clock_adjtime                   sys_clock_adjtime               compat_sys_clock_adjtime
+348    common  syncfs                          sys_syncfs
+349    common  sendmmsg                        sys_sendmmsg                    compat_sys_sendmmsg
+350    common  setns                           sys_setns
+351    nospu   process_vm_readv                sys_process_vm_readv            compat_sys_process_vm_readv
+352    nospu   process_vm_writev               sys_process_vm_writev           compat_sys_process_vm_writev
+353    nospu   finit_module                    sys_finit_module
+354    nospu   kcmp                            sys_kcmp
+355    common  sched_setattr                   sys_sched_setattr
+356    common  sched_getattr                   sys_sched_getattr
+357    common  renameat2                       sys_renameat2
+358    common  seccomp                         sys_seccomp
+359    common  getrandom                       sys_getrandom
+360    common  memfd_create                    sys_memfd_create
+361    common  bpf                             sys_bpf
+362    nospu   execveat                        sys_execveat                    compat_sys_execveat
+363    32      switch_endian                   sys_ni_syscall
+363    64      switch_endian                   ppc_switch_endian
+363    spu     switch_endian                   sys_ni_syscall
+364    common  userfaultfd                     sys_userfaultfd
+365    common  membarrier                      sys_membarrier
+378    nospu   mlock2                          sys_mlock2
+379    nospu   copy_file_range                 sys_copy_file_range
+380    common  preadv2                         sys_preadv2                     compat_sys_preadv2
+381    common  pwritev2                        sys_pwritev2                    compat_sys_pwritev2
+382    nospu   kexec_file_load                 sys_kexec_file_load
+383    nospu   statx                           sys_statx
+384    nospu   pkey_alloc                      sys_pkey_alloc
+385    nospu   pkey_free                       sys_pkey_free
+386    nospu   pkey_mprotect                   sys_pkey_mprotect
+387    nospu   rseq                            sys_rseq
+388    nospu   io_pgetevents                   sys_io_pgetevents               compat_sys_io_pgetevents
index 1076393..e18a355 100644 (file)
@@ -63,7 +63,8 @@ static const char *reg_names[] = {
        [PERF_REG_POWERPC_TRAP] = "trap",
        [PERF_REG_POWERPC_DAR] = "dar",
        [PERF_REG_POWERPC_DSISR] = "dsisr",
-       [PERF_REG_POWERPC_SIER] = "sier"
+       [PERF_REG_POWERPC_SIER] = "sier",
+       [PERF_REG_POWERPC_MMCRA] = "mmcra"
 };
 
 static inline const char *perf_reg_name(int id)
index 2e65953..ba98bd0 100644 (file)
@@ -2,6 +2,7 @@ libperf-y += header.o
 libperf-y += sym-handling.o
 libperf-y += kvm-stat.o
 libperf-y += perf_regs.o
+libperf-y += mem-events.o
 
 libperf-$(CONFIG_DWARF) += dwarf-regs.o
 libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
diff --git a/tools/perf/arch/powerpc/util/mem-events.c b/tools/perf/arch/powerpc/util/mem-events.c
new file mode 100644 (file)
index 0000000..d08311f
--- /dev/null
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "mem-events.h"
+
+/* PowerPC does not support 'ldlat' parameter. */
+char *perf_mem_events__name(int i)
+{
+       if (i == PERF_MEM_EVENTS__LOAD)
+               return (char *) "cpu/mem-loads/";
+
+       return (char *) "cpu/mem-stores/";
+}
index 07fcd97..34d5134 100644 (file)
@@ -53,6 +53,7 @@ const struct sample_reg sample_reg_masks[] = {
        SMPL_REG(dar, PERF_REG_POWERPC_DAR),
        SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR),
        SMPL_REG(sier, PERF_REG_POWERPC_SIER),
+       SMPL_REG(mmcra, PERF_REG_POWERPC_MMCRA),
        SMPL_REG_END
 };
 
index d079f36..ac221f1 100644 (file)
@@ -1681,13 +1681,8 @@ static void perf_sample__fprint_metric(struct perf_script *script,
                .force_header = false,
        };
        struct perf_evsel *ev2;
-       static bool init;
        u64 val;
 
-       if (!init) {
-               perf_stat__init_shadow_stats();
-               init = true;
-       }
        if (!evsel->stats)
                perf_evlist__alloc_stats(script->session->evlist, false);
        if (evsel_script(evsel->leader)->gnum++ == 0)
@@ -1794,7 +1789,7 @@ static void process_event(struct perf_script *script,
                return;
        }
 
-       if (PRINT_FIELD(TRACE)) {
+       if (PRINT_FIELD(TRACE) && sample->raw_data) {
                event_format__fprintf(evsel->tp_format, sample->cpu,
                                      sample->raw_data, sample->raw_size, fp);
        }
@@ -2359,6 +2354,8 @@ static int __cmd_script(struct perf_script *script)
 
        signal(SIGINT, sig_handler);
 
+       perf_stat__init_shadow_stats();
+
        /* override event processing functions */
        if (script->show_task_events) {
                script->tool.comm = process_comm_event;
index 1410d66..63a3afc 100644 (file)
@@ -561,7 +561,8 @@ try_again:
                                        break;
                        }
                }
-               wait4(child_pid, &status, 0, &stat_config.ru_data);
+               if (child_pid != -1)
+                       wait4(child_pid, &status, 0, &stat_config.ru_data);
 
                if (workload_exec_errno) {
                        const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
index fe3ecfb..f64e312 100644 (file)
@@ -1028,12 +1028,7 @@ out_err:
 
 static int callchain_param__setup_sample_type(struct callchain_param *callchain)
 {
-       if (!perf_hpp_list.sym) {
-               if (callchain->enabled) {
-                       ui__error("Selected -g but \"sym\" not present in --sort/-s.");
-                       return -EINVAL;
-               }
-       } else if (callchain->mode != CHAIN_NONE) {
+       if (callchain->mode != CHAIN_NONE) {
                if (callchain_register_param(callchain) < 0) {
                        ui__error("Can't register callchain params.\n");
                        return -EINVAL;
index adbf281..b36061c 100644 (file)
@@ -1758,6 +1758,7 @@ static int trace__printf_interrupted_entry(struct trace *trace)
 {
        struct thread_trace *ttrace;
        size_t printed;
+       int len;
 
        if (trace->failure_only || trace->current == NULL)
                return 0;
@@ -1768,9 +1769,14 @@ static int trace__printf_interrupted_entry(struct trace *trace)
                return 0;
 
        printed  = trace__fprintf_entry_head(trace, trace->current, 0, false, ttrace->entry_time, trace->output);
-       printed += fprintf(trace->output, ")%-*s ...\n", trace->args_alignment, ttrace->entry_str);
-       ttrace->entry_pending = false;
+       printed += len = fprintf(trace->output, "%s)", ttrace->entry_str);
+
+       if (len < trace->args_alignment - 4)
+               printed += fprintf(trace->output, "%-*s", trace->args_alignment - 4 - len, " ");
+
+       printed += fprintf(trace->output, " ...\n");
 
+       ttrace->entry_pending = false;
        ++trace->nr_events_printed;
 
        return printed;
@@ -2026,9 +2032,10 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
        if (ttrace->entry_pending) {
                printed = fprintf(trace->output, "%s", ttrace->entry_str);
        } else {
-               fprintf(trace->output, " ... [");
+               printed += fprintf(trace->output, " ... [");
                color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
-               fprintf(trace->output, "]: %s()", sc->name);
+               printed += 9;
+               printed += fprintf(trace->output, "]: %s()", sc->name);
        }
 
        printed++; /* the closing ')' */
@@ -2507,19 +2514,30 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
 
 static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
 {
-       struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
+       bool found = false;
+       struct perf_evsel *evsel, *tmp;
+       struct parse_events_error err = { .idx = 0, };
+       int ret = parse_events(evlist, "probe:vfs_getname*", &err);
 
-       if (IS_ERR(evsel))
+       if (ret)
                return false;
 
-       if (perf_evsel__field(evsel, "pathname") == NULL) {
+       evlist__for_each_entry_safe(evlist, evsel, tmp) {
+               if (!strstarts(perf_evsel__name(evsel), "probe:vfs_getname"))
+                       continue;
+
+               if (perf_evsel__field(evsel, "pathname")) {
+                       evsel->handler = trace__vfs_getname;
+                       found = true;
+                       continue;
+               }
+
+               list_del_init(&evsel->node);
+               evsel->evlist = NULL;
                perf_evsel__delete(evsel);
-               return false;
        }
 
-       evsel->handler = trace__vfs_getname;
-       perf_evlist__add(evlist, evsel);
-       return true;
+       return found;
 }
 
 static struct perf_evsel *perf_evsel__new_pgfault(u64 config)
index 6cb98f8..7b55613 100755 (executable)
@@ -10,6 +10,7 @@ include/uapi/linux/fs.h
 include/uapi/linux/kcmp.h
 include/uapi/linux/kvm.h
 include/uapi/linux/in.h
+include/uapi/linux/mount.h
 include/uapi/linux/perf_event.h
 include/uapi/linux/prctl.h
 include/uapi/linux/sched.h
@@ -49,7 +50,6 @@ arch/parisc/include/uapi/asm/errno.h
 arch/powerpc/include/uapi/asm/errno.h
 arch/sparc/include/uapi/asm/errno.h
 arch/x86/include/uapi/asm/errno.h
-arch/powerpc/include/uapi/asm/unistd.h
 include/asm-generic/bitops/arch_hweight.h
 include/asm-generic/bitops/const_hweight.h
 include/asm-generic/bitops/__fls.h
index 8c0ca0c..aaa5210 100644 (file)
@@ -5,17 +5,17 @@
 #define VDSO__MAP_NAME "[vdso]"
 
 /*
- * Include definition of find_vdso_map() also used in util/vdso.c for
+ * Include definition of find_map() also used in util/vdso.c for
  * building perf.
  */
-#include "util/find-vdso-map.c"
+#include "util/find-map.c"
 
 int main(void)
 {
        void *start, *end;
        size_t size, written;
 
-       if (find_vdso_map(&start, &end))
+       if (find_map(&start, &end, VDSO__MAP_NAME))
                return 1;
 
        size = end - start;
index 44090a9..e952127 100644 (file)
@@ -1,6 +1,8 @@
 #! /usr/bin/python
 # SPDX-License-Identifier: GPL-2.0
 
+from __future__ import print_function
+
 import os
 import sys
 import glob
@@ -8,7 +10,11 @@ import optparse
 import tempfile
 import logging
 import shutil
-import ConfigParser
+
+try:
+    import configparser
+except ImportError:
+    import ConfigParser as configparser
 
 def data_equal(a, b):
     # Allow multiple values in assignment separated by '|'
@@ -100,20 +106,20 @@ class Event(dict):
     def equal(self, other):
         for t in Event.terms:
             log.debug("      [%s] %s %s" % (t, self[t], other[t]));
-            if not self.has_key(t) or not other.has_key(t):
+            if t not in self or t not in other:
                 return False
             if not data_equal(self[t], other[t]):
                 return False
         return True
 
     def optional(self):
-        if self.has_key('optional') and self['optional'] == '1':
+        if 'optional' in self and self['optional'] == '1':
             return True
         return False
 
     def diff(self, other):
         for t in Event.terms:
-            if not self.has_key(t) or not other.has_key(t):
+            if t not in self or t not in other:
                 continue
             if not data_equal(self[t], other[t]):
                 log.warning("expected %s=%s, got %s" % (t, self[t], other[t]))
@@ -134,7 +140,7 @@ class Event(dict):
 #   - expected values assignments
 class Test(object):
     def __init__(self, path, options):
-        parser = ConfigParser.SafeConfigParser()
+        parser = configparser.SafeConfigParser()
         parser.read(path)
 
         log.warning("running '%s'" % path)
@@ -193,7 +199,7 @@ class Test(object):
         return True
 
     def load_events(self, path, events):
-        parser_event = ConfigParser.SafeConfigParser()
+        parser_event = configparser.SafeConfigParser()
         parser_event.read(path)
 
         # The event record section header contains 'event' word,
@@ -207,7 +213,7 @@ class Test(object):
             # Read parent event if there's any
             if (':' in section):
                 base = section[section.index(':') + 1:]
-                parser_base = ConfigParser.SafeConfigParser()
+                parser_base = configparser.SafeConfigParser()
                 parser_base.read(self.test_dir + '/' + base)
                 base_items = parser_base.items('event')
 
@@ -322,9 +328,9 @@ def run_tests(options):
     for f in glob.glob(options.test_dir + '/' + options.test):
         try:
             Test(f, options).run()
-        except Unsup, obj:
+        except Unsup as obj:
             log.warning("unsupp  %s" % obj.getMsg())
-        except Notest, obj:
+        except Notest as obj:
             log.warning("skipped %s" % obj.getMsg())
 
 def setup_log(verbose):
@@ -363,7 +369,7 @@ def main():
     parser.add_option("-p", "--perf",
                       action="store", type="string", dest="perf")
     parser.add_option("-v", "--verbose",
-                      action="count", dest="verbose")
+                      default=0, action="count", dest="verbose")
 
     options, args = parser.parse_args()
     if args:
@@ -373,7 +379,7 @@ def main():
     setup_log(options.verbose)
 
     if not options.test_dir:
-        print 'FAILED no -d option specified'
+        print('FAILED no -d option specified')
         sys.exit(-1)
 
     if not options.test:
@@ -382,8 +388,8 @@ def main():
     try:
         run_tests(options)
 
-    except Fail, obj:
-        print "FAILED %s" % obj.getMsg();
+    except Fail as obj:
+        print("FAILED %s" % obj.getMsg())
         sys.exit(-1)
 
     sys.exit(0)
index 5f8501c..5cbba70 100644 (file)
@@ -17,7 +17,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
                return -1;
        }
 
-       is_signed = !!(field->flags | TEP_FIELD_IS_SIGNED);
+       is_signed = !!(field->flags & TEP_FIELD_IS_SIGNED);
        if (should_be_signed && !is_signed) {
                pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n",
                         evsel->name, name, is_signed, should_be_signed);
index 1c16e56..7cb99b4 100644 (file)
@@ -13,7 +13,8 @@ add_probe_vfs_getname() {
        local verbose=$1
        if [ $had_vfs_getname -eq 1 ] ; then
                line=$(perf probe -L getname_flags 2>&1 | egrep 'result.*=.*filename;' | sed -r 's/[[:space:]]+([[:digit:]]+)[[:space:]]+result->uptr.*/\1/')
-               perf probe $verbose "vfs_getname=getname_flags:${line} pathname=result->name:string"
+               perf probe -q       "vfs_getname=getname_flags:${line} pathname=result->name:string" || \
+               perf probe $verbose "vfs_getname=getname_flags:${line} pathname=filename:string"
        fi
 }
 
index b82f55f..399f18c 100644 (file)
@@ -119,4 +119,9 @@ int test__arch_unwind_sample(struct perf_sample *sample,
                             struct thread *thread);
 #endif
 #endif
+
+#if defined(__arm__)
+int test__vectors_page(struct test *test, int subtest);
+#endif
+
 #endif /* TESTS_H */
index 4554757..847850b 100755 (executable)
@@ -5,11 +5,11 @@
 
 printf "static const char *mount_flags[] = {\n"
 regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MS_([[:alnum:]_]+)[[:space:]]+([[:digit:]]+)[[:space:]]*.*'
-egrep $regex ${header_dir}/fs.h | egrep -v '(MSK|VERBOSE|MGC_VAL)\>' | \
+egrep $regex ${header_dir}/mount.h | egrep -v '(MSK|VERBOSE|MGC_VAL)\>' | \
        sed -r "s/$regex/\2 \2 \1/g" | sort -n | \
        xargs printf "\t[%s ? (ilog2(%s) + 1) : 0] = \"%s\",\n"
 regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MS_([[:alnum:]_]+)[[:space:]]+\(1<<([[:digit:]]+)\)[[:space:]]*.*'
-egrep $regex ${header_dir}/fs.h | \
+egrep $regex ${header_dir}/mount.h | \
        sed -r "s/$regex/\2 \1/g" | \
        xargs printf "\t[%s + 1] = \"%s\",\n"
 printf "};\n"
index d32f8f1..3109d7b 100755 (executable)
@@ -4,7 +4,7 @@
 [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
 
 printf "static const char *prctl_options[] = {\n"
-regex='^#define[[:space:]]+PR_([GS]ET\w+)[[:space:]]*([[:xdigit:]]+).*'
+regex='^#define[[:space:]]+PR_(\w+)[[:space:]]*([[:xdigit:]]+).*'
 egrep $regex ${header_dir}/prctl.h | grep -v PR_SET_PTRACER | \
        sed -r "s/$regex/\2 \1/g"       | \
        sort -n | xargs printf "\t[%s] = \"%s\",\n"
index 1d00e5e..82e16bf 100644 (file)
@@ -224,20 +224,24 @@ static unsigned int annotate_browser__refresh(struct ui_browser *browser)
        return ret;
 }
 
-static int disasm__cmp(struct annotation_line *a, struct annotation_line *b)
+static double disasm__cmp(struct annotation_line *a, struct annotation_line *b,
+                                                 int percent_type)
 {
        int i;
 
        for (i = 0; i < a->data_nr; i++) {
-               if (a->data[i].percent == b->data[i].percent)
+               if (a->data[i].percent[percent_type] == b->data[i].percent[percent_type])
                        continue;
-               return a->data[i].percent < b->data[i].percent;
+               return a->data[i].percent[percent_type] -
+                          b->data[i].percent[percent_type];
        }
        return 0;
 }
 
-static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line *al)
+static void disasm_rb_tree__insert(struct annotate_browser *browser,
+                               struct annotation_line *al)
 {
+       struct rb_root *root = &browser->entries;
        struct rb_node **p = &root->rb_node;
        struct rb_node *parent = NULL;
        struct annotation_line *l;
@@ -246,7 +250,7 @@ static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line
                parent = *p;
                l = rb_entry(parent, struct annotation_line, rb_node);
 
-               if (disasm__cmp(al, l))
+               if (disasm__cmp(al, l, browser->opts->percent_type) < 0)
                        p = &(*p)->rb_left;
                else
                        p = &(*p)->rb_right;
@@ -329,7 +333,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
                        RB_CLEAR_NODE(&pos->al.rb_node);
                        continue;
                }
-               disasm_rb_tree__insert(&browser->entries, &pos->al);
+               disasm_rb_tree__insert(browser, &pos->al);
        }
        pthread_mutex_unlock(&notes->lock);
 
index ac9805e..70de8f6 100644 (file)
@@ -1723,15 +1723,14 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
        err = asprintf(&command,
                 "%s %s%s --start-address=0x%016" PRIx64
                 " --stop-address=0x%016" PRIx64
-                " -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand",
+                " -l -d %s %s -C \"$1\" 2>/dev/null|grep -v \"$1:\"|expand",
                 opts->objdump_path ?: "objdump",
                 opts->disassembler_style ? "-M " : "",
                 opts->disassembler_style ?: "",
                 map__rip_2objdump(map, sym->start),
                 map__rip_2objdump(map, sym->end),
                 opts->show_asm_raw ? "" : "--no-show-raw",
-                opts->annotate_src ? "-S" : "",
-                symfs_filename, symfs_filename);
+                opts->annotate_src ? "-S" : "");
 
        if (err < 0) {
                pr_err("Failure allocating memory for the command to run\n");
@@ -1756,7 +1755,8 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
                close(stdout_fd[0]);
                dup2(stdout_fd[1], 1);
                close(stdout_fd[1]);
-               execl("/bin/sh", "sh", "-c", command, NULL);
+               execl("/bin/sh", "sh", "-c", command, "--", symfs_filename,
+                     NULL);
                perror(command);
                exit(-1);
        }
index 8951250..39c0004 100644 (file)
@@ -160,7 +160,7 @@ getBPFObjectFromModule(llvm::Module *Module)
        }
        PM.run(*Module);
 
-       return std::move(Buffer);
+       return Buffer;
 }
 
 }
index 32ef7bd..dc2212e 100644 (file)
@@ -766,6 +766,7 @@ static enum match_result match_chain(struct callchain_cursor_node *node,
                        cnode->cycles_count += node->branch_flags.cycles;
                        cnode->iter_count += node->nr_loop_iter;
                        cnode->iter_cycles += node->iter_cycles;
+                       cnode->from_count++;
                }
        }
 
@@ -1345,10 +1346,10 @@ static int branch_to_str(char *bf, int bfsize,
 static int branch_from_str(char *bf, int bfsize,
                           u64 branch_count,
                           u64 cycles_count, u64 iter_count,
-                          u64 iter_cycles)
+                          u64 iter_cycles, u64 from_count)
 {
        int printed = 0, i = 0;
-       u64 cycles;
+       u64 cycles, v = 0;
 
        cycles = cycles_count / branch_count;
        if (cycles) {
@@ -1357,14 +1358,16 @@ static int branch_from_str(char *bf, int bfsize,
                                bf + printed, bfsize - printed);
        }
 
-       if (iter_count) {
-               printed += count_pri64_printf(i++, "iter",
-                               iter_count,
-                               bf + printed, bfsize - printed);
+       if (iter_count && from_count) {
+               v = iter_count / from_count;
+               if (v) {
+                       printed += count_pri64_printf(i++, "iter",
+                                       v, bf + printed, bfsize - printed);
 
-               printed += count_pri64_printf(i++, "avg_cycles",
-                               iter_cycles / iter_count,
-                               bf + printed, bfsize - printed);
+                       printed += count_pri64_printf(i++, "avg_cycles",
+                                       iter_cycles / iter_count,
+                                       bf + printed, bfsize - printed);
+               }
        }
 
        if (i)
@@ -1377,6 +1380,7 @@ static int counts_str_build(char *bf, int bfsize,
                             u64 branch_count, u64 predicted_count,
                             u64 abort_count, u64 cycles_count,
                             u64 iter_count, u64 iter_cycles,
+                            u64 from_count,
                             struct branch_type_stat *brtype_stat)
 {
        int printed;
@@ -1389,7 +1393,8 @@ static int counts_str_build(char *bf, int bfsize,
                                predicted_count, abort_count, brtype_stat);
        } else {
                printed = branch_from_str(bf, bfsize, branch_count,
-                               cycles_count, iter_count, iter_cycles);
+                               cycles_count, iter_count, iter_cycles,
+                               from_count);
        }
 
        if (!printed)
@@ -1402,13 +1407,14 @@ static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
                                   u64 branch_count, u64 predicted_count,
                                   u64 abort_count, u64 cycles_count,
                                   u64 iter_count, u64 iter_cycles,
+                                  u64 from_count,
                                   struct branch_type_stat *brtype_stat)
 {
        char str[256];
 
        counts_str_build(str, sizeof(str), branch_count,
                         predicted_count, abort_count, cycles_count,
-                        iter_count, iter_cycles, brtype_stat);
+                        iter_count, iter_cycles, from_count, brtype_stat);
 
        if (fp)
                return fprintf(fp, "%s", str);
@@ -1422,6 +1428,7 @@ int callchain_list_counts__printf_value(struct callchain_list *clist,
        u64 branch_count, predicted_count;
        u64 abort_count, cycles_count;
        u64 iter_count, iter_cycles;
+       u64 from_count;
 
        branch_count = clist->branch_count;
        predicted_count = clist->predicted_count;
@@ -1429,11 +1436,12 @@ int callchain_list_counts__printf_value(struct callchain_list *clist,
        cycles_count = clist->cycles_count;
        iter_count = clist->iter_count;
        iter_cycles = clist->iter_cycles;
+       from_count = clist->from_count;
 
        return callchain_counts_printf(fp, bf, bfsize, branch_count,
                                       predicted_count, abort_count,
                                       cycles_count, iter_count, iter_cycles,
-                                      &clist->brtype_stat);
+                                      from_count, &clist->brtype_stat);
 }
 
 static void free_callchain_node(struct callchain_node *node)
index 154560b..99d38ac 100644 (file)
@@ -118,6 +118,7 @@ struct callchain_list {
                bool            has_children;
        };
        u64                     branch_count;
+       u64                     from_count;
        u64                     predicted_count;
        u64                     abort_count;
        u64                     cycles_count;
index 1ccbd33..383674f 100644 (file)
@@ -134,7 +134,12 @@ struct cpu_map *cpu_map__new(const char *cpu_list)
        if (!cpu_list)
                return cpu_map__read_all_cpu_map();
 
-       if (!isdigit(*cpu_list))
+       /*
+        * must handle the case of empty cpumap to cover
+        * TOPOLOGY header for NUMA nodes with no CPU
+        * ( e.g., because of CPU hotplug)
+        */
+       if (!isdigit(*cpu_list) && *cpu_list != '\0')
                goto out;
 
        while (isdigit(*cpu_list)) {
@@ -181,8 +186,10 @@ struct cpu_map *cpu_map__new(const char *cpu_list)
 
        if (nr_cpus > 0)
                cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
-       else
+       else if (*cpu_list != '\0')
                cpus = cpu_map__default_new();
+       else
+               cpus = cpu_map__dummy_new();
 invalid:
        free(tmp_cpus);
 out:
similarity index 71%
rename from tools/perf/util/find-vdso-map.c
rename to tools/perf/util/find-map.c
index d7823e3..7b23005 100644 (file)
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
-static int find_vdso_map(void **start, void **end)
+static int find_map(void **start, void **end, const char *name)
 {
        FILE *maps;
        char line[128];
@@ -7,7 +7,7 @@ static int find_vdso_map(void **start, void **end)
 
        maps = fopen("/proc/self/maps", "r");
        if (!maps) {
-               fprintf(stderr, "vdso: cannot open maps\n");
+               fprintf(stderr, "cannot open maps\n");
                return -1;
        }
 
@@ -21,8 +21,7 @@ static int find_vdso_map(void **start, void **end)
                if (m < 0)
                        continue;
 
-               if (!strncmp(&line[m], VDSO__MAP_NAME,
-                            sizeof(VDSO__MAP_NAME) - 1))
+               if (!strncmp(&line[m], name, strlen(name)))
                        found = 1;
        }
 
index 6fcb3bc..143f705 100644 (file)
@@ -2005,7 +2005,7 @@ static void save_iterations(struct iterations *iter,
 {
        int i;
 
-       iter->nr_loop_iter = nr;
+       iter->nr_loop_iter++;
        iter->cycles = 0;
 
        for (i = 0; i < nr; i++)
index 93f74d8..42c3e5a 100644 (file)
@@ -28,7 +28,7 @@ struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = {
 static char mem_loads_name[100];
 static bool mem_loads_name__init;
 
-char *perf_mem_events__name(int i)
+char * __weak perf_mem_events__name(int i)
 {
        if (i == PERF_MEM_EVENTS__LOAD) {
                if (!mem_loads_name__init) {
index 8975895..ea523d3 100644 (file)
@@ -391,8 +391,10 @@ void ordered_events__free(struct ordered_events *oe)
         * Current buffer might not have all the events allocated
         * yet, we need to free only allocated ones ...
         */
-       list_del(&oe->buffer->list);
-       ordered_events_buffer__free(oe->buffer, oe->buffer_idx, oe);
+       if (oe->buffer) {
+               list_del(&oe->buffer->list);
+               ordered_events_buffer__free(oe->buffer, oe->buffer_idx, oe);
+       }
 
        /* ... and continue with the rest */
        list_for_each_entry_safe(buffer, tmp, &oe->to_free, list) {
index 63f758c..64d1f36 100644 (file)
@@ -17,6 +17,8 @@ if cc == "clang":
             vars[var] = sub("-mcet", "", vars[var])
         if not clang_has_option("-fcf-protection"):
             vars[var] = sub("-fcf-protection", "", vars[var])
+        if not clang_has_option("-fstack-clash-protection"):
+            vars[var] = sub("-fstack-clash-protection", "", vars[var])
 
 from distutils.core import setup, Extension
 
index 9005fbe..23092fd 100644 (file)
@@ -109,7 +109,6 @@ static int strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap)
                        return ret;
                }
                len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved);
-               va_end(ap_saved);
                if (len > strbuf_avail(sb)) {
                        pr_debug("this should not happen, your vsnprintf is broken");
                        va_end(ap_saved);
index 66a84d5..dca7dfa 100644 (file)
 #define EM_AARCH64     183  /* ARM 64 bit */
 #endif
 
+#ifndef ELF32_ST_VISIBILITY
+#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
+#endif
+
+/* For ELF64 the definitions are the same.  */
+#ifndef ELF64_ST_VISIBILITY
+#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)
+#endif
+
+/* How to extract information held in the st_other field.  */
+#ifndef GELF_ST_VISIBILITY
+#define GELF_ST_VISIBILITY(val)        ELF64_ST_VISIBILITY (val)
+#endif
+
 typedef Elf64_Nhdr GElf_Nhdr;
 
 #ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
@@ -87,6 +101,11 @@ static inline uint8_t elf_sym__type(const GElf_Sym *sym)
        return GELF_ST_TYPE(sym->st_info);
 }
 
+static inline uint8_t elf_sym__visibility(const GElf_Sym *sym)
+{
+       return GELF_ST_VISIBILITY(sym->st_other);
+}
+
 #ifndef STT_GNU_IFUNC
 #define STT_GNU_IFUNC 10
 #endif
@@ -111,7 +130,9 @@ static inline int elf_sym__is_label(const GElf_Sym *sym)
        return elf_sym__type(sym) == STT_NOTYPE &&
                sym->st_name != 0 &&
                sym->st_shndx != SHN_UNDEF &&
-               sym->st_shndx != SHN_ABS;
+               sym->st_shndx != SHN_ABS &&
+               elf_sym__visibility(sym) != STV_HIDDEN &&
+               elf_sym__visibility(sym) != STV_INTERNAL;
 }
 
 static bool elf_sym__filter(GElf_Sym *sym)
index 01f2c73..48efad6 100644 (file)
@@ -614,6 +614,7 @@ out:
 static bool symbol__is_idle(const char *name)
 {
        const char * const idle_symbols[] = {
+               "arch_cpu_idle",
                "cpu_idle",
                "cpu_startup_entry",
                "intel_idle",
index 741af20..3702cba 100644 (file)
 #include "debug.h"
 
 /*
- * Include definition of find_vdso_map() also used in perf-read-vdso.c for
+ * Include definition of find_map() also used in perf-read-vdso.c for
  * building perf-read-vdso32 and perf-read-vdsox32.
  */
-#include "find-vdso-map.c"
+#include "find-map.c"
 
 #define VDSO__TEMP_FILE_NAME "/tmp/perf-vdso.so-XXXXXX"
 
@@ -76,7 +76,7 @@ static char *get_file(struct vdso_file *vdso_file)
        if (vdso_file->found)
                return vdso_file->temp_file_name;
 
-       if (vdso_file->error || find_vdso_map(&start, &end))
+       if (vdso_file->error || find_map(&start, &end, VDSO__MAP_NAME))
                return NULL;
 
        size = end - start;
index e752384..2d4baf5 100644 (file)
@@ -18,8 +18,8 @@ ssize_t security_show(struct device *dev,
         * For the test version we need to poll the "hardware" in order
         * to get the updated status for unlock testing.
         */
-       nvdimm->sec.state = nvdimm_security_state(nvdimm, false);
-       nvdimm->sec.ext_state = nvdimm_security_state(nvdimm, true);
+       nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER);
+       nvdimm->sec.ext_state = nvdimm_security_state(nvdimm, NVDIMM_MASTER);
 
        switch (nvdimm->sec.state) {
        case NVDIMM_SECURITY_DISABLED:
index 1a2bd15..400ee81 100644 (file)
@@ -10,6 +10,7 @@ TARGETS += drivers/dma-buf
 TARGETS += efivarfs
 TARGETS += exec
 TARGETS += filesystems
+TARGETS += filesystems/binderfs
 TARGETS += firmware
 TARGETS += ftrace
 TARGETS += futex
index 4a97850..dd093bd 100644 (file)
@@ -28,3 +28,4 @@ flow_dissector_load
 test_netcnt
 test_section_names
 test_tcpnotify_user
+test_libbpf
index 73aa6d8..41ab7a3 100644 (file)
@@ -55,7 +55,10 @@ TEST_PROGS := test_kmod.sh \
        test_flow_dissector.sh \
        test_xdp_vlan.sh
 
-TEST_PROGS_EXTENDED := with_addr.sh
+TEST_PROGS_EXTENDED := with_addr.sh \
+       with_tunnels.sh \
+       tcp_client.py \
+       tcp_server.py
 
 # Compile but not part of 'make run_tests'
 TEST_GEN_PROGS_EXTENDED = test_libbpf_open test_sock_addr test_skb_cgroup_id_user \
index 315a44f..84fd6f1 100644 (file)
@@ -13,7 +13,7 @@ static inline unsigned int bpf_num_possible_cpus(void)
        unsigned int start, end, possible_cpus = 0;
        char buff[128];
        FILE *fp;
-       int n;
+       int len, n, i, j = 0;
 
        fp = fopen(fcpu, "r");
        if (!fp) {
@@ -21,17 +21,27 @@ static inline unsigned int bpf_num_possible_cpus(void)
                exit(1);
        }
 
-       while (fgets(buff, sizeof(buff), fp)) {
-               n = sscanf(buff, "%u-%u", &start, &end);
-               if (n == 0) {
-                       printf("Failed to retrieve # possible CPUs!\n");
-                       exit(1);
-               } else if (n == 1) {
-                       end = start;
+       if (!fgets(buff, sizeof(buff), fp)) {
+               printf("Failed to read %s!\n", fcpu);
+               exit(1);
+       }
+
+       len = strlen(buff);
+       for (i = 0; i <= len; i++) {
+               if (buff[i] == ',' || buff[i] == '\0') {
+                       buff[i] = '\0';
+                       n = sscanf(&buff[j], "%u-%u", &start, &end);
+                       if (n <= 0) {
+                               printf("Failed to retrieve # possible CPUs!\n");
+                               exit(1);
+                       } else if (n == 1) {
+                               end = start;
+                       }
+                       possible_cpus += end - start + 1;
+                       j = i + 1;
                }
-               possible_cpus = start == 0 ? end + 1 : 0;
-               break;
        }
+
        fclose(fp);
 
        return possible_cpus;
index cf16948..6692a40 100644 (file)
@@ -155,7 +155,7 @@ void cleanup_cgroup_environment(void)
  * This function creates a cgroup under the top level workdir and returns the
  * file descriptor. It is idempotent.
  *
- * On success, it returns the file descriptor. On failure it returns 0.
+ * On success, it returns the file descriptor. On failure it returns -1.
  * If there is a failure, it prints the error to stderr.
  */
 int create_and_get_cgroup(const char *path)
@@ -166,13 +166,13 @@ int create_and_get_cgroup(const char *path)
        format_cgroup_path(cgroup_path, path);
        if (mkdir(cgroup_path, 0777) && errno != EEXIST) {
                log_err("mkdiring cgroup %s .. %s", path, cgroup_path);
-               return 0;
+               return -1;
        }
 
        fd = open(cgroup_path, O_RDONLY);
        if (fd < 0) {
                log_err("Opening Cgroup");
-               return 0;
+               return -1;
        }
 
        return fd;
index 8bcd380..91420fa 100644 (file)
@@ -1881,13 +1881,12 @@ static struct btf_raw_test raw_tests[] = {
 },
 
 {
-       .descr = "func proto (CONST=>TYPEDEF=>FUNC_PROTO)",
+       .descr = "func proto (TYPEDEF=>FUNC_PROTO)",
        .raw_types = {
                BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
                BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),               /* [2] */
-               BTF_CONST_ENC(4),                               /* [3] */
-               BTF_TYPEDEF_ENC(NAME_TBD, 5),                   /* [4] */
-               BTF_FUNC_PROTO_ENC(0, 2),                       /* [5] */
+               BTF_TYPEDEF_ENC(NAME_TBD, 4),                   /* [3] */
+               BTF_FUNC_PROTO_ENC(0, 2),                       /* [4] */
                        BTF_FUNC_PROTO_ARG_ENC(0, 1),
                        BTF_FUNC_PROTO_ARG_ENC(0, 2),
                BTF_END_RAW,
@@ -1901,8 +1900,6 @@ static struct btf_raw_test raw_tests[] = {
        .key_type_id = 1,
        .value_type_id = 1,
        .max_entries = 4,
-       .btf_load_err = true,
-       .err_str = "Invalid type_id",
 },
 
 {
@@ -3526,6 +3523,8 @@ struct pprint_mapv {
                ENUM_TWO,
                ENUM_THREE,
        } aenum;
+       uint32_t ui32b;
+       uint32_t bits2c:2;
 };
 
 static struct btf_raw_test pprint_test_template[] = {
@@ -3568,7 +3567,7 @@ static struct btf_raw_test pprint_test_template[] = {
                BTF_ENUM_ENC(NAME_TBD, 2),
                BTF_ENUM_ENC(NAME_TBD, 3),
                /* struct pprint_mapv */                /* [16] */
-               BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 8), 32),
+               BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 10), 40),
                BTF_MEMBER_ENC(NAME_TBD, 11, 0),        /* uint32_t ui32 */
                BTF_MEMBER_ENC(NAME_TBD, 10, 32),       /* uint16_t ui16 */
                BTF_MEMBER_ENC(NAME_TBD, 12, 64),       /* int32_t si32 */
@@ -3577,9 +3576,11 @@ static struct btf_raw_test pprint_test_template[] = {
                BTF_MEMBER_ENC(NAME_TBD, 6, 126),       /* unused_bits2b */
                BTF_MEMBER_ENC(0, 14, 128),             /* union (anon) */
                BTF_MEMBER_ENC(NAME_TBD, 15, 192),      /* aenum */
+               BTF_MEMBER_ENC(NAME_TBD, 11, 224),      /* uint32_t ui32b */
+               BTF_MEMBER_ENC(NAME_TBD, 6, 256),       /* bits2c */
                BTF_END_RAW,
        },
-       BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum"),
+       BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c"),
        .key_size = sizeof(unsigned int),
        .value_size = sizeof(struct pprint_mapv),
        .key_type_id = 3,       /* unsigned int */
@@ -3628,7 +3629,7 @@ static struct btf_raw_test pprint_test_template[] = {
                BTF_ENUM_ENC(NAME_TBD, 2),
                BTF_ENUM_ENC(NAME_TBD, 3),
                /* struct pprint_mapv */                /* [16] */
-               BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 8), 32),
+               BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 10), 40),
                BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 0)),  /* uint32_t ui32 */
                BTF_MEMBER_ENC(NAME_TBD, 10, BTF_MEMBER_OFFSET(0, 32)), /* uint16_t ui16 */
                BTF_MEMBER_ENC(NAME_TBD, 12, BTF_MEMBER_OFFSET(0, 64)), /* int32_t si32 */
@@ -3637,9 +3638,11 @@ static struct btf_raw_test pprint_test_template[] = {
                BTF_MEMBER_ENC(NAME_TBD, 6, BTF_MEMBER_OFFSET(2, 126)), /* unused_bits2b */
                BTF_MEMBER_ENC(0, 14, BTF_MEMBER_OFFSET(0, 128)),       /* union (anon) */
                BTF_MEMBER_ENC(NAME_TBD, 15, BTF_MEMBER_OFFSET(0, 192)),        /* aenum */
+               BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 224)),        /* uint32_t ui32b */
+               BTF_MEMBER_ENC(NAME_TBD, 6, BTF_MEMBER_OFFSET(2, 256)), /* bits2c */
                BTF_END_RAW,
        },
-       BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum"),
+       BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c"),
        .key_size = sizeof(unsigned int),
        .value_size = sizeof(struct pprint_mapv),
        .key_type_id = 3,       /* unsigned int */
@@ -3690,7 +3693,7 @@ static struct btf_raw_test pprint_test_template[] = {
                BTF_ENUM_ENC(NAME_TBD, 2),
                BTF_ENUM_ENC(NAME_TBD, 3),
                /* struct pprint_mapv */                /* [16] */
-               BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 8), 32),
+               BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 10), 40),
                BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 0)),  /* uint32_t ui32 */
                BTF_MEMBER_ENC(NAME_TBD, 10, BTF_MEMBER_OFFSET(0, 32)), /* uint16_t ui16 */
                BTF_MEMBER_ENC(NAME_TBD, 12, BTF_MEMBER_OFFSET(0, 64)), /* int32_t si32 */
@@ -3699,13 +3702,15 @@ static struct btf_raw_test pprint_test_template[] = {
                BTF_MEMBER_ENC(NAME_TBD, 19, BTF_MEMBER_OFFSET(2, 126)),/* unused_bits2b */
                BTF_MEMBER_ENC(0, 14, BTF_MEMBER_OFFSET(0, 128)),       /* union (anon) */
                BTF_MEMBER_ENC(NAME_TBD, 15, BTF_MEMBER_OFFSET(0, 192)),        /* aenum */
+               BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 224)),        /* uint32_t ui32b */
+               BTF_MEMBER_ENC(NAME_TBD, 17, BTF_MEMBER_OFFSET(2, 256)),        /* bits2c */
                /* typedef unsigned int ___int */       /* [17] */
                BTF_TYPEDEF_ENC(NAME_TBD, 18),
                BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_VOLATILE, 0, 0), 6),      /* [18] */
                BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 15),        /* [19] */
                BTF_END_RAW,
        },
-       BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0___int"),
+       BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c\0___int"),
        .key_size = sizeof(unsigned int),
        .value_size = sizeof(struct pprint_mapv),
        .key_type_id = 3,       /* unsigned int */
@@ -3793,6 +3798,8 @@ static void set_pprint_mapv(struct pprint_mapv *v, uint32_t i,
                v->unused_bits2b = 3;
                v->ui64 = i;
                v->aenum = i & 0x03;
+               v->ui32b = 4;
+               v->bits2c = 1;
                v = (void *)v + rounded_value_size;
        }
 }
@@ -3955,7 +3962,8 @@ static int do_test_pprint(int test_num)
 
                        nexpected_line = snprintf(expected_line, sizeof(expected_line),
                                                  "%s%u: {%u,0,%d,0x%x,0x%x,0x%x,"
-                                                 "{%lu|[%u,%u,%u,%u,%u,%u,%u,%u]},%s}\n",
+                                                 "{%lu|[%u,%u,%u,%u,%u,%u,%u,%u]},%s,"
+                                                 "%u,0x%x}\n",
                                                  percpu_map ? "\tcpu" : "",
                                                  percpu_map ? cpu : next_key,
                                                  cmapv->ui32, cmapv->si32,
@@ -3967,7 +3975,9 @@ static int do_test_pprint(int test_num)
                                                  cmapv->ui8a[2], cmapv->ui8a[3],
                                                  cmapv->ui8a[4], cmapv->ui8a[5],
                                                  cmapv->ui8a[6], cmapv->ui8a[7],
-                                                 pprint_enum_str[cmapv->aenum]);
+                                                 pprint_enum_str[cmapv->aenum],
+                                                 cmapv->ui32b,
+                                                 cmapv->bits2c);
 
                        err = check_line(expected_line, nexpected_line,
                                         sizeof(expected_line), line);
index f448341..2fc4625 100644 (file)
@@ -81,7 +81,7 @@ int main(int argc, char **argv)
 
        /* Create a cgroup, get fd, and join it */
        cgroup_fd = create_and_get_cgroup(TEST_CGROUP);
-       if (!cgroup_fd) {
+       if (cgroup_fd < 0) {
                printf("Failed to create test cgroup\n");
                goto err;
        }
index 9c8b50b..76e4993 100644 (file)
@@ -43,7 +43,7 @@ int main(int argc, char **argv)
 
        /* Create a cgroup, get fd, and join it */
        cgroup_fd = create_and_get_cgroup(TEST_CGROUP);
-       if (!cgroup_fd) {
+       if (cgroup_fd < 0) {
                printf("Failed to create test cgroup\n");
                goto err;
        }
index 44ed7f2..c1da540 100644 (file)
@@ -65,7 +65,7 @@ int main(int argc, char **argv)
 
        /* Create a cgroup, get fd, and join it */
        cgroup_fd = create_and_get_cgroup(TEST_CGROUP);
-       if (!cgroup_fd) {
+       if (cgroup_fd < 0) {
                printf("Failed to create test cgroup\n");
                goto err;
        }
index 126fc62..25f0083 100644 (file)
@@ -1188,7 +1188,9 @@ static void test_stacktrace_build_id(void)
        int i, j;
        struct bpf_stack_build_id id_offs[PERF_MAX_STACK_DEPTH];
        int build_id_matches = 0;
+       int retry = 1;
 
+retry:
        err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
        if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
                goto out;
@@ -1301,6 +1303,19 @@ static void test_stacktrace_build_id(void)
                previous_key = key;
        } while (bpf_map_get_next_key(stackmap_fd, &previous_key, &key) == 0);
 
+       /* stack_map_get_build_id_offset() is racy and sometimes can return
+        * BPF_STACK_BUILD_ID_IP instead of BPF_STACK_BUILD_ID_VALID;
+        * try it one more time.
+        */
+       if (build_id_matches < 1 && retry--) {
+               ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
+               close(pmu_fd);
+               bpf_object__close(obj);
+               printf("%s:WARN:Didn't find expected build ID from the map, retrying\n",
+                      __func__);
+               goto retry;
+       }
+
        if (CHECK(build_id_matches < 1, "build id match",
                  "Didn't find expected build ID from the map\n"))
                goto disable_pmu;
@@ -1341,7 +1356,9 @@ static void test_stacktrace_build_id_nmi(void)
        int i, j;
        struct bpf_stack_build_id id_offs[PERF_MAX_STACK_DEPTH];
        int build_id_matches = 0;
+       int retry = 1;
 
+retry:
        err = bpf_prog_load(file, BPF_PROG_TYPE_PERF_EVENT, &obj, &prog_fd);
        if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
                return;
@@ -1436,6 +1453,19 @@ static void test_stacktrace_build_id_nmi(void)
                previous_key = key;
        } while (bpf_map_get_next_key(stackmap_fd, &previous_key, &key) == 0);
 
+       /* stack_map_get_build_id_offset() is racy and sometimes can return
+        * BPF_STACK_BUILD_ID_IP instead of BPF_STACK_BUILD_ID_VALID;
+        * try it one more time.
+        */
+       if (build_id_matches < 1 && retry--) {
+               ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
+               close(pmu_fd);
+               bpf_object__close(obj);
+               printf("%s:WARN:Didn't find expected build ID from the map, retrying\n",
+                      __func__);
+               goto retry;
+       }
+
        if (CHECK(build_id_matches < 1, "build id match",
                  "Didn't find expected build ID from the map\n"))
                goto disable_pmu;
index c121cc5..9220747 100644 (file)
@@ -164,7 +164,7 @@ int main(int argc, char **argv)
                goto err;
 
        cgfd = create_and_get_cgroup(CGROUP_PATH);
-       if (!cgfd)
+       if (cgfd < 0)
                goto err;
 
        if (join_cgroup(CGROUP_PATH))
index b8ebe2f..561ffb6 100644 (file)
@@ -458,7 +458,7 @@ int main(int argc, char **argv)
                goto err;
 
        cgfd = create_and_get_cgroup(CG_PATH);
-       if (!cgfd)
+       if (cgfd < 0)
                goto err;
 
        if (join_cgroup(CG_PATH))
index 73b7493..3f110ea 100644 (file)
@@ -44,6 +44,7 @@
 #define SERV6_V4MAPPED_IP      "::ffff:192.168.0.4"
 #define SRC6_IP                        "::1"
 #define SRC6_REWRITE_IP                "::6"
+#define WILDCARD6_IP           "::"
 #define SERV6_PORT             6060
 #define SERV6_REWRITE_PORT     6666
 
@@ -85,12 +86,14 @@ static int bind4_prog_load(const struct sock_addr_test *test);
 static int bind6_prog_load(const struct sock_addr_test *test);
 static int connect4_prog_load(const struct sock_addr_test *test);
 static int connect6_prog_load(const struct sock_addr_test *test);
+static int sendmsg_allow_prog_load(const struct sock_addr_test *test);
 static int sendmsg_deny_prog_load(const struct sock_addr_test *test);
 static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test);
 static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test);
+static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test);
 
 static struct sock_addr_test tests[] = {
        /* bind */
@@ -463,6 +466,34 @@ static struct sock_addr_test tests[] = {
                SYSCALL_ENOTSUPP,
        },
        {
+               "sendmsg6: set dst IP = [::] (BSD'ism)",
+               sendmsg6_rw_wildcard_prog_load,
+               BPF_CGROUP_UDP6_SENDMSG,
+               BPF_CGROUP_UDP6_SENDMSG,
+               AF_INET6,
+               SOCK_DGRAM,
+               SERV6_IP,
+               SERV6_PORT,
+               SERV6_REWRITE_IP,
+               SERV6_REWRITE_PORT,
+               SRC6_REWRITE_IP,
+               SUCCESS,
+       },
+       {
+               "sendmsg6: preserve dst IP = [::] (BSD'ism)",
+               sendmsg_allow_prog_load,
+               BPF_CGROUP_UDP6_SENDMSG,
+               BPF_CGROUP_UDP6_SENDMSG,
+               AF_INET6,
+               SOCK_DGRAM,
+               WILDCARD6_IP,
+               SERV6_PORT,
+               SERV6_REWRITE_IP,
+               SERV6_PORT,
+               SRC6_IP,
+               SUCCESS,
+       },
+       {
                "sendmsg6: deny call",
                sendmsg_deny_prog_load,
                BPF_CGROUP_UDP6_SENDMSG,
@@ -734,16 +765,27 @@ static int connect6_prog_load(const struct sock_addr_test *test)
        return load_path(test, CONNECT6_PROG_PATH);
 }
 
-static int sendmsg_deny_prog_load(const struct sock_addr_test *test)
+static int sendmsg_ret_only_prog_load(const struct sock_addr_test *test,
+                                     int32_t rc)
 {
        struct bpf_insn insns[] = {
-               /* return 0 */
-               BPF_MOV64_IMM(BPF_REG_0, 0),
+               /* return rc */
+               BPF_MOV64_IMM(BPF_REG_0, rc),
                BPF_EXIT_INSN(),
        };
        return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn));
 }
 
+static int sendmsg_allow_prog_load(const struct sock_addr_test *test)
+{
+       return sendmsg_ret_only_prog_load(test, /*rc*/ 1);
+}
+
+static int sendmsg_deny_prog_load(const struct sock_addr_test *test)
+{
+       return sendmsg_ret_only_prog_load(test, /*rc*/ 0);
+}
+
 static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test)
 {
        struct sockaddr_in dst4_rw_addr;
@@ -864,6 +906,11 @@ static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test)
        return sendmsg6_rw_dst_asm_prog_load(test, SERV6_V4MAPPED_IP);
 }
 
+static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test)
+{
+       return sendmsg6_rw_dst_asm_prog_load(test, WILDCARD6_IP);
+}
+
 static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test)
 {
        return load_path(test, SENDMSG6_PROG_PATH);
@@ -1395,7 +1442,7 @@ int main(int argc, char **argv)
                goto err;
 
        cgfd = create_and_get_cgroup(CG_PATH);
-       if (!cgfd)
+       if (cgfd < 0)
                goto err;
 
        if (join_cgroup(CG_PATH))
index b6c2c60..fc7832e 100644 (file)
@@ -202,7 +202,7 @@ int main(int argc, char **argv)
                goto err;
 
        cgfd = create_and_get_cgroup(CG_PATH);
-       if (!cgfd)
+       if (cgfd < 0)
                goto err;
 
        if (join_cgroup(CG_PATH))
index e6eebda..716b4e3 100644 (file)
@@ -103,7 +103,7 @@ int main(int argc, char **argv)
                goto err;
 
        cg_fd = create_and_get_cgroup(cg_path);
-       if (!cg_fd)
+       if (cg_fd < 0)
                goto err;
 
        if (join_cgroup(cg_path))
index ff3c452..4e43537 100644 (file)
@@ -115,7 +115,7 @@ int main(int argc, char **argv)
                goto err;
 
        cg_fd = create_and_get_cgroup(cg_path);
-       if (!cg_fd)
+       if (cg_fd < 0)
                goto err;
 
        if (join_cgroup(cg_path))
index 10d4444..2fd90d4 100644 (file)
@@ -6934,6 +6934,126 @@ static struct bpf_test tests[] = {
                .retval = 1,
        },
        {
+               "map access: mixing value pointer and scalar, 1",
+               .insns = {
+                       // load map value pointer into r0 and r2
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
+                       BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -16),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_FP, -16, 0),
+                       BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
+                       BPF_EXIT_INSN(),
+                       // load some number from the map into r1
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       // depending on r1, branch:
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 3),
+                       // branch A
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0),
+                       BPF_JMP_A(2),
+                       // branch B
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0x100000),
+                       // common instruction
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_3),
+                       // depending on r1, branch:
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
+                       // branch A
+                       BPF_JMP_A(4),
+                       // branch B
+                       BPF_MOV64_IMM(BPF_REG_0, 0x13371337),
+                       // verifier follows fall-through
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 0x100000, 2),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+                       // fake-dead code; targeted from branch A to
+                       // prevent dead code sanitization
+                       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 1 },
+               .result = ACCEPT,
+               .result_unpriv = REJECT,
+               .errstr_unpriv = "R2 tried to add from different pointers or scalars",
+               .retval = 0,
+       },
+       {
+               "map access: mixing value pointer and scalar, 2",
+               .insns = {
+                       // load map value pointer into r0 and r2
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
+                       BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -16),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_FP, -16, 0),
+                       BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
+                       BPF_EXIT_INSN(),
+                       // load some number from the map into r1
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       // depending on r1, branch:
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
+                       // branch A
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0x100000),
+                       BPF_JMP_A(2),
+                       // branch B
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0),
+                       // common instruction
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_3),
+                       // depending on r1, branch:
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
+                       // branch A
+                       BPF_JMP_A(4),
+                       // branch B
+                       BPF_MOV64_IMM(BPF_REG_0, 0x13371337),
+                       // verifier follows fall-through
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 0x100000, 2),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+                       // fake-dead code; targeted from branch A to
+                       // prevent dead code sanitization
+                       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 1 },
+               .result = ACCEPT,
+               .result_unpriv = REJECT,
+               .errstr_unpriv = "R2 tried to add from different maps or paths",
+               .retval = 0,
+       },
+       {
+               "sanitation: alu with different scalars",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
+                       BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -16),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_FP, -16, 0),
+                       BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
+                       BPF_EXIT_INSN(),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0x100000),
+                       BPF_JMP_A(2),
+                       BPF_MOV64_IMM(BPF_REG_2, 42),
+                       BPF_MOV64_IMM(BPF_REG_3, 0x100001),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_3),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 1 },
+               .result = ACCEPT,
+               .retval = 0x100000,
+       },
+       {
                "map access: value_ptr += known scalar, upper oob arith, test 1",
                .insns = {
                        BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
index bab13dd..0d26b5e 100755 (executable)
@@ -37,6 +37,10 @@ prerequisite()
                exit $ksft_skip
        fi
 
+       present_cpus=`cat $SYSFS/devices/system/cpu/present`
+       present_max=${present_cpus##*-}
+       echo "present_cpus = $present_cpus present_max = $present_max"
+
        echo -e "\t Cpus in online state: $online_cpus"
 
        offline_cpus=`cat $SYSFS/devices/system/cpu/offline`
@@ -151,6 +155,8 @@ online_cpus=0
 online_max=0
 offline_cpus=0
 offline_max=0
+present_cpus=0
+present_max=0
 
 while getopts e:ahp: opt; do
        case $opt in
@@ -190,9 +196,10 @@ if [ $allcpus -eq 0 ]; then
        online_cpu_expect_success $online_max
 
        if [[ $offline_cpus -gt 0 ]]; then
-               echo -e "\t offline to online to offline: cpu $offline_max"
-               online_cpu_expect_success $offline_max
-               offline_cpu_expect_success $offline_max
+               echo -e "\t offline to online to offline: cpu $present_max"
+               online_cpu_expect_success $present_max
+               offline_cpu_expect_success $present_max
+               online_cpu $present_max
        fi
        exit 0
 else
index 94fdbf2..c4cf6e6 100755 (executable)
@@ -25,6 +25,7 @@ ALL_TESTS="
        lag_unlink_slaves_test
        lag_dev_deletion_test
        vlan_interface_uppers_test
+       bridge_extern_learn_test
        devlink_reload_test
 "
 NUM_NETIFS=2
@@ -541,6 +542,25 @@ vlan_interface_uppers_test()
        ip link del dev br0
 }
 
+bridge_extern_learn_test()
+{
+       # Test that externally learned entries added from user space are
+       # marked as offloaded
+       RET=0
+
+       ip link add name br0 type bridge
+       ip link set dev $swp1 master br0
+
+       bridge fdb add de:ad:be:ef:13:37 dev $swp1 master extern_learn
+
+       bridge fdb show brport $swp1 | grep de:ad:be:ef:13:37 | grep -q offload
+       check_err $? "fdb entry not marked as offloaded when should"
+
+       log_test "externally learned fdb entry"
+
+       ip link del dev br0
+}
+
 devlink_reload_test()
 {
        # Test that after executing all the above configuration tests, a
index dcf9f4e..ae6146e 100755 (executable)
@@ -847,6 +847,24 @@ sanitization_vlan_aware_test()
 
        log_test "vlan-aware - failed enslavement to vlan-aware bridge"
 
+       bridge vlan del vid 10 dev vxlan20
+       bridge vlan add vid 20 dev vxlan20 pvid untagged
+
+       # Test that offloading of an unsupported tunnel fails when it is
+       # triggered by addition of VLAN to a local port
+       RET=0
+
+       # TOS must be set to inherit
+       ip link set dev vxlan10 type vxlan tos 42
+
+       ip link set dev $swp1 master br0
+       bridge vlan add vid 10 dev $swp1 &> /dev/null
+       check_fail $?
+
+       log_test "vlan-aware - failed vlan addition to a local port"
+
+       ip link set dev vxlan10 type vxlan tos inherit
+
        ip link del dev vxlan20
        ip link del dev vxlan10
        ip link del dev br0
diff --git a/tools/testing/selftests/filesystems/binderfs/.gitignore b/tools/testing/selftests/filesystems/binderfs/.gitignore
new file mode 100644 (file)
index 0000000..8a5d9bf
--- /dev/null
@@ -0,0 +1 @@
+binderfs_test
diff --git a/tools/testing/selftests/filesystems/binderfs/Makefile b/tools/testing/selftests/filesystems/binderfs/Makefile
new file mode 100644 (file)
index 0000000..58cb659
--- /dev/null
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+CFLAGS += -I../../../../../usr/include/
+TEST_GEN_PROGS := binderfs_test
+
+include ../../lib.mk
diff --git a/tools/testing/selftests/filesystems/binderfs/binderfs_test.c b/tools/testing/selftests/filesystems/binderfs/binderfs_test.c
new file mode 100644 (file)
index 0000000..8c2ed96
--- /dev/null
@@ -0,0 +1,275 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <linux/android/binder.h>
+#include <linux/android/binderfs.h>
+#include "../../kselftest.h"
+
+static ssize_t write_nointr(int fd, const void *buf, size_t count)
+{
+       ssize_t ret;
+again:
+       ret = write(fd, buf, count);
+       if (ret < 0 && errno == EINTR)
+               goto again;
+
+       return ret;
+}
+
+static void write_to_file(const char *filename, const void *buf, size_t count,
+                         int allowed_errno)
+{
+       int fd, saved_errno;
+       ssize_t ret;
+
+       fd = open(filename, O_WRONLY | O_CLOEXEC);
+       if (fd < 0)
+               ksft_exit_fail_msg("%s - Failed to open file %s\n",
+                                  strerror(errno), filename);
+
+       ret = write_nointr(fd, buf, count);
+       if (ret < 0) {
+               if (allowed_errno && (errno == allowed_errno)) {
+                       close(fd);
+                       return;
+               }
+
+               goto on_error;
+       }
+
+       if ((size_t)ret != count)
+               goto on_error;
+
+       close(fd);
+       return;
+
+on_error:
+       saved_errno = errno;
+       close(fd);
+       errno = saved_errno;
+
+       if (ret < 0)
+               ksft_exit_fail_msg("%s - Failed to write to file %s\n",
+                                  strerror(errno), filename);
+
+       ksft_exit_fail_msg("Failed to write to file %s\n", filename);
+}
+
+static void change_to_userns(void)
+{
+       int ret;
+       uid_t uid;
+       gid_t gid;
+       /* {g,u}id_map files only allow a max of 4096 bytes written to them */
+       char idmap[4096];
+
+       uid = getuid();
+       gid = getgid();
+
+       ret = unshare(CLONE_NEWUSER);
+       if (ret < 0)
+               ksft_exit_fail_msg("%s - Failed to unshare user namespace\n",
+                                  strerror(errno));
+
+       write_to_file("/proc/self/setgroups", "deny", strlen("deny"), ENOENT);
+
+       ret = snprintf(idmap, sizeof(idmap), "0 %d 1", uid);
+       if (ret < 0 || (size_t)ret >= sizeof(idmap))
+               ksft_exit_fail_msg("%s - Failed to prepare uid mapping\n",
+                                  strerror(errno));
+
+       write_to_file("/proc/self/uid_map", idmap, strlen(idmap), 0);
+
+       ret = snprintf(idmap, sizeof(idmap), "0 %d 1", gid);
+       if (ret < 0 || (size_t)ret >= sizeof(idmap))
+               ksft_exit_fail_msg("%s - Failed to prepare uid mapping\n",
+                                  strerror(errno));
+
+       write_to_file("/proc/self/gid_map", idmap, strlen(idmap), 0);
+
+       ret = setgid(0);
+       if (ret)
+               ksft_exit_fail_msg("%s - Failed to setgid(0)\n",
+                                  strerror(errno));
+
+       ret = setuid(0);
+       if (ret)
+               ksft_exit_fail_msg("%s - Failed to setgid(0)\n",
+                                  strerror(errno));
+}
+
+static void change_to_mountns(void)
+{
+       int ret;
+
+       ret = unshare(CLONE_NEWNS);
+       if (ret < 0)
+               ksft_exit_fail_msg("%s - Failed to unshare mount namespace\n",
+                                  strerror(errno));
+
+       ret = mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0);
+       if (ret < 0)
+               ksft_exit_fail_msg("%s - Failed to mount / as private\n",
+                                  strerror(errno));
+}
+
+static void rmdir_protect_errno(const char *dir)
+{
+       int saved_errno = errno;
+       (void)rmdir(dir);
+       errno = saved_errno;
+}
+
+static void __do_binderfs_test(void)
+{
+       int fd, ret, saved_errno;
+       size_t len;
+       ssize_t wret;
+       bool keep = false;
+       struct binderfs_device device = { 0 };
+       struct binder_version version = { 0 };
+
+       change_to_mountns();
+
+       ret = mkdir("/dev/binderfs", 0755);
+       if (ret < 0) {
+               if (errno != EEXIST)
+                       ksft_exit_fail_msg(
+                               "%s - Failed to create binderfs mountpoint\n",
+                               strerror(errno));
+
+               keep = true;
+       }
+
+       ret = mount(NULL, "/dev/binderfs", "binder", 0, 0);
+       if (ret < 0) {
+               if (errno != ENODEV)
+                       ksft_exit_fail_msg("%s - Failed to mount binderfs\n",
+                                          strerror(errno));
+
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_skip(
+                       "The Android binderfs filesystem is not available\n");
+       }
+
+       /* binderfs mount test passed */
+       ksft_inc_pass_cnt();
+
+       memcpy(device.name, "my-binder", strlen("my-binder"));
+
+       fd = open("/dev/binderfs/binder-control", O_RDONLY | O_CLOEXEC);
+       if (fd < 0)
+               ksft_exit_fail_msg(
+                       "%s - Failed to open binder-control device\n",
+                       strerror(errno));
+
+       ret = ioctl(fd, BINDER_CTL_ADD, &device);
+       saved_errno = errno;
+       close(fd);
+       errno = saved_errno;
+       if (ret < 0) {
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_fail_msg(
+                       "%s - Failed to allocate new binder device\n",
+                       strerror(errno));
+       }
+
+       ksft_print_msg(
+               "Allocated new binder device with major %d, minor %d, and name %s\n",
+               device.major, device.minor, device.name);
+
+       /* binder device allocation test passed */
+       ksft_inc_pass_cnt();
+
+       fd = open("/dev/binderfs/my-binder", O_CLOEXEC | O_RDONLY);
+       if (fd < 0) {
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_fail_msg("%s - Failed to open my-binder device\n",
+                                  strerror(errno));
+       }
+
+       ret = ioctl(fd, BINDER_VERSION, &version);
+       saved_errno = errno;
+       close(fd);
+       errno = saved_errno;
+       if (ret < 0) {
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_fail_msg(
+                       "%s - Failed to open perform BINDER_VERSION request\n",
+                       strerror(errno));
+       }
+
+       ksft_print_msg("Detected binder version: %d\n",
+                      version.protocol_version);
+
+       /* binder transaction with binderfs binder device passed */
+       ksft_inc_pass_cnt();
+
+       ret = unlink("/dev/binderfs/my-binder");
+       if (ret < 0) {
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_fail_msg("%s - Failed to delete binder device\n",
+                                  strerror(errno));
+       }
+
+       /* binder device removal passed */
+       ksft_inc_pass_cnt();
+
+       ret = unlink("/dev/binderfs/binder-control");
+       if (!ret) {
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_fail_msg("Managed to delete binder-control device\n");
+       } else if (errno != EPERM) {
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_fail_msg(
+                       "%s - Failed to delete binder-control device but exited with unexpected error code\n",
+                       strerror(errno));
+       }
+
+       /* binder-control device removal failed as expected */
+       ksft_inc_xfail_cnt();
+
+on_error:
+       ret = umount2("/dev/binderfs", MNT_DETACH);
+       keep ?: rmdir_protect_errno("/dev/binderfs");
+       if (ret < 0)
+               ksft_exit_fail_msg("%s - Failed to unmount binderfs\n",
+                                  strerror(errno));
+
+       /* binderfs unmount test passed */
+       ksft_inc_pass_cnt();
+}
+
+static void binderfs_test_privileged()
+{
+       if (geteuid() != 0)
+               ksft_print_msg(
+                       "Tests are not run as root. Skipping privileged tests\n");
+       else
+               __do_binderfs_test();
+}
+
+static void binderfs_test_unprivileged()
+{
+       change_to_userns();
+       __do_binderfs_test();
+}
+
+int main(int argc, char *argv[])
+{
+       binderfs_test_privileged();
+       binderfs_test_unprivileged();
+       ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/filesystems/binderfs/config b/tools/testing/selftests/filesystems/binderfs/config
new file mode 100644 (file)
index 0000000..02dd6cc
--- /dev/null
@@ -0,0 +1,3 @@
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDERFS=y
+CONFIG_ANDROID_BINDER_IPC=y
index f8d468f..aaa1e9f 100644 (file)
@@ -37,7 +37,7 @@ static int get_debugfs(char **path)
        struct libmnt_table *tb;
        struct libmnt_iter *itr = NULL;
        struct libmnt_fs *fs;
-       int found = 0;
+       int found = 0, ret;
 
        cxt = mnt_new_context();
        if (!cxt)
@@ -58,8 +58,11 @@ static int get_debugfs(char **path)
                        break;
                }
        }
-       if (found)
-               asprintf(path, "%s/gpio", mnt_fs_get_target(fs));
+       if (found) {
+               ret = asprintf(path, "%s/gpio", mnt_fs_get_target(fs));
+               if (ret < 0)
+                       err(EXIT_FAILURE, "failed to format string");
+       }
 
        mnt_free_iter(itr);
        mnt_free_context(cxt);
index f4ba8eb..ad06489 100644 (file)
@@ -1,5 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 TEST_PROGS := ir_loopback.sh
 TEST_GEN_PROGS_EXTENDED := ir_loopback
+APIDIR := ../../../include/uapi
+CFLAGS += -Wall -O2 -I$(APIDIR)
 
 include ../lib.mk
index 23022e9..b52cfde 100644 (file)
@@ -571,7 +571,7 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
         * already exist.
         */
        region = (struct userspace_mem_region *) userspace_mem_region_find(
-               vm, guest_paddr, guest_paddr + npages * vm->page_size);
+               vm, guest_paddr, (guest_paddr + npages * vm->page_size) - 1);
        if (region != NULL)
                TEST_ASSERT(false, "overlapping userspace_mem_region already "
                        "exists\n"
@@ -587,15 +587,10 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
                region = region->next) {
                if (region->region.slot == slot)
                        break;
-               if ((guest_paddr <= (region->region.guest_phys_addr
-                               + region->region.memory_size))
-                       && ((guest_paddr + npages * vm->page_size)
-                               >= region->region.guest_phys_addr))
-                       break;
        }
        if (region != NULL)
                TEST_ASSERT(false, "A mem region with the requested slot "
-                       "or overlapping physical memory range already exists.\n"
+                       "already exists.\n"
                        "  requested slot: %u paddr: 0x%lx npages: 0x%lx\n"
                        "  existing slot: %u paddr: 0x%lx size: 0x%lx",
                        slot, guest_paddr, npages,
index ea3c73e..c49c2a2 100644 (file)
@@ -103,6 +103,12 @@ int main(int argc, char *argv[])
 
        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);
+
        run = vcpu_state(vm, VCPU_ID);
 
        vcpu_regs_get(vm, VCPU_ID, &regs1);
index f8f3e90..1e6d14d 100644 (file)
@@ -21,6 +21,6 @@ TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict tls
 KSFT_KHDR_INSTALL := 1
 include ../lib.mk
 
-$(OUTPUT)/reuseport_bpf_numa: LDFLAGS += -lnuma
+$(OUTPUT)/reuseport_bpf_numa: LDLIBS += -lnuma
 $(OUTPUT)/tcp_mmap: LDFLAGS += -lpthread
 $(OUTPUT)/tcp_inq: LDFLAGS += -lpthread
index d8313d0..b90dff8 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 
-ALL_TESTS="ping_ipv4 ping_ipv6 learning flooding"
+ALL_TESTS="ping_ipv4 ping_ipv6 learning flooding vlan_deletion extern_learn"
 NUM_NETIFS=4
 CHECK_TC="yes"
 source lib.sh
@@ -96,6 +96,51 @@ flooding()
        flood_test $swp2 $h1 $h2
 }
 
+vlan_deletion()
+{
+       # Test that the deletion of a VLAN on a bridge port does not affect
+       # the PVID VLAN
+       log_info "Add and delete a VLAN on bridge port $swp1"
+
+       bridge vlan add vid 10 dev $swp1
+       bridge vlan del vid 10 dev $swp1
+
+       ping_ipv4
+       ping_ipv6
+}
+
+extern_learn()
+{
+       local mac=de:ad:be:ef:13:37
+       local ageing_time
+
+       # Test that externally learned FDB entries can roam, but not age out
+       RET=0
+
+       bridge fdb add de:ad:be:ef:13:37 dev $swp1 master extern_learn vlan 1
+
+       bridge fdb show brport $swp1 | grep -q de:ad:be:ef:13:37
+       check_err $? "Did not find FDB entry when should"
+
+       # Wait for 10 seconds after the ageing time to make sure the FDB entry
+       # was not aged out
+       ageing_time=$(bridge_ageing_time_get br0)
+       sleep $((ageing_time + 10))
+
+       bridge fdb show brport $swp1 | grep -q de:ad:be:ef:13:37
+       check_err $? "FDB entry was aged out when should not"
+
+       $MZ $h2 -c 1 -p 64 -a $mac -t ip -q
+
+       bridge fdb show brport $swp2 | grep -q de:ad:be:ef:13:37
+       check_err $? "FDB entry did not roam when should"
+
+       log_test "Externally learned FDB entry - ageing & roaming"
+
+       bridge fdb del de:ad:be:ef:13:37 dev $swp2 master vlan 1 &> /dev/null
+       bridge fdb del de:ad:be:ef:13:37 dev $swp1 master vlan 1 &> /dev/null
+}
+
 trap cleanup EXIT
 
 setup_prepare
index 56cef3b..bb10e33 100755 (executable)
@@ -629,7 +629,7 @@ __test_ecn_decap()
        RET=0
 
        tc filter add dev $h1 ingress pref 77 prot ip \
-               flower ip_tos $decapped_tos action pass
+               flower ip_tos $decapped_tos action drop
        sleep 1
        vxlan_encapped_ping_test v2 v1 192.0.2.17 \
                                 $orig_inner_tos $orig_outer_tos \
index 61ae278..5d56cc0 100644 (file)
@@ -203,6 +203,7 @@ static void send_udp_frags(int fd_raw, struct sockaddr *addr,
 {
        struct ip *iphdr = (struct ip *)ip_frame;
        struct ip6_hdr *ip6hdr = (struct ip6_hdr *)ip_frame;
+       const bool ipv4 = !ipv6;
        int res;
        int offset;
        int frag_len;
@@ -239,19 +240,53 @@ static void send_udp_frags(int fd_raw, struct sockaddr *addr,
                iphdr->ip_sum = 0;
        }
 
+       /* Occasionally test in-order fragments. */
+       if (!cfg_overlap && (rand() % 100 < 15)) {
+               offset = 0;
+               while (offset < (UDP_HLEN + payload_len)) {
+                       send_fragment(fd_raw, addr, alen, offset, ipv6);
+                       offset += max_frag_len;
+               }
+               return;
+       }
+
+       /* Occasionally test IPv4 "runs" (see net/ipv4/ip_fragment.c) */
+       if (ipv4 && !cfg_overlap && (rand() % 100 < 20) &&
+                       (payload_len > 9 * max_frag_len)) {
+               offset = 6 * max_frag_len;
+               while (offset < (UDP_HLEN + payload_len)) {
+                       send_fragment(fd_raw, addr, alen, offset, ipv6);
+                       offset += max_frag_len;
+               }
+               offset = 3 * max_frag_len;
+               while (offset < 6 * max_frag_len) {
+                       send_fragment(fd_raw, addr, alen, offset, ipv6);
+                       offset += max_frag_len;
+               }
+               offset = 0;
+               while (offset < 3 * max_frag_len) {
+                       send_fragment(fd_raw, addr, alen, offset, ipv6);
+                       offset += max_frag_len;
+               }
+               return;
+       }
+
        /* Odd fragments. */
        offset = max_frag_len;
        while (offset < (UDP_HLEN + payload_len)) {
                send_fragment(fd_raw, addr, alen, offset, ipv6);
+               /* IPv4 ignores duplicates, so randomly send a duplicate. */
+               if (ipv4 && (1 == rand() % 100))
+                       send_fragment(fd_raw, addr, alen, offset, ipv6);
                offset += 2 * max_frag_len;
        }
 
        if (cfg_overlap) {
                /* Send an extra random fragment. */
-               offset = rand() % (UDP_HLEN + payload_len - 1);
-               /* sendto() returns EINVAL if offset + frag_len is too small. */
                if (ipv6) {
                        struct ip6_frag *fraghdr = (struct ip6_frag *)(ip_frame + IP6_HLEN);
+                       /* sendto() returns EINVAL if offset + frag_len is too small. */
+                       offset = rand() % (UDP_HLEN + payload_len - 1);
                        frag_len = max_frag_len + rand() % 256;
                        /* In IPv6 if !!(frag_len % 8), the fragment is dropped. */
                        frag_len &= ~0x7;
@@ -259,13 +294,29 @@ static void send_udp_frags(int fd_raw, struct sockaddr *addr,
                        ip6hdr->ip6_plen = htons(frag_len);
                        frag_len += IP6_HLEN;
                } else {
-                       frag_len = IP4_HLEN + UDP_HLEN + rand() % 256;
+                       /* In IPv4, duplicates and some fragments completely inside
+                        * previously sent fragments are dropped/ignored. So
+                        * random offset and frag_len can result in a dropped
+                        * fragment instead of a dropped queue/packet. So we
+                        * hard-code offset and frag_len.
+                        *
+                        * See ade446403bfb ("net: ipv4: do not handle duplicate
+                        * fragments as overlapping").
+                        */
+                       if (max_frag_len * 4 < payload_len || max_frag_len < 16) {
+                               /* not enough payload to play with random offset and frag_len. */
+                               offset = 8;
+                               frag_len = IP4_HLEN + UDP_HLEN + max_frag_len;
+                       } else {
+                               offset = rand() % (payload_len / 2);
+                               frag_len = 2 * max_frag_len + 1 + rand() % 256;
+                       }
                        iphdr->ip_off = htons(offset / 8 | IP4_MF);
                        iphdr->ip_len = htons(frag_len);
                }
                res = sendto(fd_raw, ip_frame, frag_len, 0, addr, alen);
                if (res < 0)
-                       error(1, errno, "sendto overlap");
+                       error(1, errno, "sendto overlap: %d", frag_len);
                if (res != frag_len)
                        error(1, 0, "sendto overlap: %d vs %d", (int)res, frag_len);
                frag_counter++;
@@ -275,6 +326,9 @@ static void send_udp_frags(int fd_raw, struct sockaddr *addr,
        offset = 0;
        while (offset < (UDP_HLEN + payload_len)) {
                send_fragment(fd_raw, addr, alen, offset, ipv6);
+               /* IPv4 ignores duplicates, so randomly send a duplicate. */
+               if (ipv4 && (1 == rand() % 100))
+                       send_fragment(fd_raw, addr, alen, offset, ipv6);
                offset += 2 * max_frag_len;
        }
 }
@@ -282,7 +336,11 @@ static void send_udp_frags(int fd_raw, struct sockaddr *addr,
 static void run_test(struct sockaddr *addr, socklen_t alen, bool ipv6)
 {
        int fd_tx_raw, fd_rx_udp;
-       struct timeval tv = { .tv_sec = 0, .tv_usec = 10 * 1000 };
+       /* Frag queue timeout is set to one second in the calling script;
+        * socket timeout should be just a bit longer to avoid tests interfering
+        * with each other.
+        */
+       struct timeval tv = { .tv_sec = 1, .tv_usec = 10 };
        int idx;
        int min_frag_len = ipv6 ? 1280 : 8;
 
@@ -308,12 +366,32 @@ static void run_test(struct sockaddr *addr, socklen_t alen, bool ipv6)
                        payload_len += (rand() % 4096)) {
                if (cfg_verbose)
                        printf("payload_len: %d\n", payload_len);
-               max_frag_len = min_frag_len;
-               do {
+
+               if (cfg_overlap) {
+                       /* With overlaps, one send/receive pair below takes
+                        * at least one second (== timeout) to run, so there
+                        * is not enough test time to run a nested loop:
+                        * the full overlap test takes 20-30 seconds.
+                        */
+                       max_frag_len = min_frag_len +
+                               rand() % (1500 - FRAG_HLEN - min_frag_len);
                        send_udp_frags(fd_tx_raw, addr, alen, ipv6);
                        recv_validate_udp(fd_rx_udp);
-                       max_frag_len += 8 * (rand() % 8);
-               } while (max_frag_len < (1500 - FRAG_HLEN) && max_frag_len <= payload_len);
+               } else {
+                       /* Without overlaps, each packet reassembly (== one
+                        * send/receive pair below) takes very little time to
+                        * run, so we can easily afford more thourough testing
+                        * with a nested loop: the full non-overlap test takes
+                        * less than one second).
+                        */
+                       max_frag_len = min_frag_len;
+                       do {
+                               send_udp_frags(fd_tx_raw, addr, alen, ipv6);
+                               recv_validate_udp(fd_rx_udp);
+                               max_frag_len += 8 * (rand() % 8);
+                       } while (max_frag_len < (1500 - FRAG_HLEN) &&
+                                max_frag_len <= payload_len);
+               }
        }
 
        /* Cleanup. */
index f346727..7dd79a9 100755 (executable)
@@ -11,10 +11,17 @@ readonly NETNS="ns-$(mktemp -u XXXXXX)"
 setup() {
        ip netns add "${NETNS}"
        ip -netns "${NETNS}" link set lo up
+
        ip netns exec "${NETNS}" sysctl -w net.ipv4.ipfrag_high_thresh=9000000 >/dev/null 2>&1
        ip netns exec "${NETNS}" sysctl -w net.ipv4.ipfrag_low_thresh=7000000 >/dev/null 2>&1
+       ip netns exec "${NETNS}" sysctl -w net.ipv4.ipfrag_time=1 >/dev/null 2>&1
+
        ip netns exec "${NETNS}" sysctl -w net.ipv6.ip6frag_high_thresh=9000000 >/dev/null 2>&1
        ip netns exec "${NETNS}" sysctl -w net.ipv6.ip6frag_low_thresh=7000000 >/dev/null 2>&1
+       ip netns exec "${NETNS}" sysctl -w net.ipv6.ip6frag_time=1 >/dev/null 2>&1
+
+       # DST cache can get full with a lot of frags, with GC not keeping up with the test.
+       ip netns exec "${NETNS}" sysctl -w net.ipv6.route.max_size=65536 >/dev/null 2>&1
 }
 
 cleanup() {
@@ -27,7 +34,6 @@ setup
 echo "ipv4 defrag"
 ip netns exec "${NETNS}" ./ip_defrag -4
 
-
 echo "ipv4 defrag with overlaps"
 ip netns exec "${NETNS}" ./ip_defrag -4o
 
@@ -37,3 +43,4 @@ ip netns exec "${NETNS}" ./ip_defrag -6
 echo "ipv6 defrag with overlaps"
 ip netns exec "${NETNS}" ./ip_defrag -6o
 
+echo "all tests done"
index 8db35b9..71d7fdc 100755 (executable)
@@ -28,6 +28,19 @@ KEY_AES=0x0123456789abcdef0123456789012345
 SPI1=0x1
 SPI2=0x2
 
+do_esp_policy() {
+    local ns=$1
+    local me=$2
+    local remote=$3
+    local lnet=$4
+    local rnet=$5
+
+    # 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 100 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 100 action allow
+}
+
 do_esp() {
     local ns=$1
     local me=$2
@@ -40,10 +53,59 @@ do_esp() {
     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 100 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 100 action allow
+    do_esp_policy $ns $me $remote $lnet $rnet
+}
+
+# add policies with different netmasks, to make sure kernel carries
+# the policies contained within new netmask over when search tree is
+# re-built.
+# peer netns that are supposed to be encapsulated via esp have addresses
+# in the 10.0.1.0/24 and 10.0.2.0/24 subnets, respectively.
+#
+# Adding a policy for '10.0.1.0/23' will make it necessary to
+# alter the prefix of 10.0.1.0 subnet.
+# In case new prefix overlaps with existing node, the node and all
+# policies it carries need to be merged with the existing one(s).
+#
+# Do that here.
+do_overlap()
+{
+    local ns=$1
+
+    # adds new nodes to tree (neither network exists yet in policy database).
+    ip -net $ns xfrm policy add src 10.1.0.0/24 dst 10.0.0.0/24 dir fwd priority 200 action block
+
+    # adds a new node in the 10.0.0.0/24 tree (dst node exists).
+    ip -net $ns xfrm policy add src 10.2.0.0/24 dst 10.0.0.0/24 dir fwd priority 200 action block
+
+    # adds a 10.2.0.0/23 node, but for different dst.
+    ip -net $ns xfrm policy add src 10.2.0.0/23 dst 10.0.1.0/24 dir fwd priority 200 action block
+
+    # dst now overlaps with the 10.0.1.0/24 ESP policy in fwd.
+    # kernel must 'promote' existing one (10.0.0.0/24) to 10.0.0.0/23.
+    # But 10.0.0.0/23 also includes existing 10.0.1.0/24, so that node
+    # also has to be merged too, including source-sorted subtrees.
+    # old:
+    # 10.0.0.0/24 (node 1 in dst tree of the bin)
+    #    10.1.0.0/24 (node in src tree of dst node 1)
+    #    10.2.0.0/24 (node in src tree of dst node 1)
+    # 10.0.1.0/24 (node 2 in dst tree of the bin)
+    #    10.0.2.0/24 (node in src tree of dst node 2)
+    #    10.2.0.0/24 (node in src tree of dst node 2)
+    #
+    # The next 'policy add' adds dst '10.0.0.0/23', which means
+    # that dst node 1 and dst node 2 have to be merged including
+    # the sub-tree.  As no duplicates are allowed, policies in
+    # the two '10.0.2.0/24' are also merged.
+    #
+    # after the 'add', internal search tree should look like this:
+    # 10.0.0.0/23 (node in dst tree of bin)
+    #     10.0.2.0/24 (node in src tree of dst node)
+    #     10.1.0.0/24 (node in src tree of dst node)
+    #     10.2.0.0/24 (node in src tree of dst node)
+    #
+    # 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
 }
 
 do_esp_policy_get_check() {
@@ -160,6 +222,41 @@ check_xfrm() {
        return $lret
 }
 
+check_exceptions()
+{
+       logpostfix="$1"
+       local lret=0
+
+       # ping to .254 should be excluded from the tunnel (exception is in place).
+       check_xfrm 0 254
+       if [ $? -ne 0 ]; then
+               echo "FAIL: expected ping to .254 to fail ($logpostfix)"
+               lret=1
+       else
+               echo "PASS: ping to .254 bypassed ipsec tunnel ($logpostfix)"
+       fi
+
+       # ping to .253 should use use ipsec due to direct policy exception.
+       check_xfrm 1 253
+       if [ $? -ne 0 ]; then
+               echo "FAIL: expected ping to .253 to use ipsec tunnel ($logpostfix)"
+               lret=1
+       else
+               echo "PASS: direct policy matches ($logpostfix)"
+       fi
+
+       # ping to .2 should use ipsec.
+       check_xfrm 1 2
+       if [ $? -ne 0 ]; then
+               echo "FAIL: expected ping to .2 to use ipsec tunnel ($logpostfix)"
+               lret=1
+       else
+               echo "PASS: policy matches ($logpostfix)"
+       fi
+
+       return $lret
+}
+
 #check for needed privileges
 if [ "$(id -u)" -ne 0 ];then
        echo "SKIP: Need root privileges"
@@ -270,33 +367,45 @@ do_exception ns4 10.0.3.10 10.0.3.1 10.0.1.253 10.0.1.240/28
 do_exception ns3 dead:3::1 dead:3::10 dead:2::fd  dead:2:f0::/96
 do_exception ns4 dead:3::10 dead:3::1 dead:1::fd  dead:1:f0::/96
 
-# ping to .254 should now be excluded from the tunnel
-check_xfrm 0 254
+check_exceptions "exceptions"
 if [ $? -ne 0 ]; then
-       echo "FAIL: expected ping to .254 to fail"
        ret=1
-else
-       echo "PASS: ping to .254 bypassed ipsec tunnel"
 fi
 
-# ping to .253 should use use ipsec due to direct policy exception.
-check_xfrm 1 253
-if [ $? -ne 0 ]; then
-       echo "FAIL: expected ping to .253 to use ipsec tunnel"
-       ret=1
-else
-       echo "PASS: direct policy matches"
-fi
+# insert block policies with adjacent/overlapping netmasks
+do_overlap ns3
 
-# ping to .2 should use ipsec.
-check_xfrm 1 2
+check_exceptions "exceptions and block policies"
 if [ $? -ne 0 ]; then
-       echo "FAIL: expected ping to .2 to use ipsec tunnel"
        ret=1
-else
-       echo "PASS: policy matches"
 fi
 
+for n in ns3 ns4;do
+       ip -net $n xfrm policy set hthresh4 28 24 hthresh6 126 125
+       sleep $((RANDOM%5))
+done
+
+check_exceptions "exceptions and block policies after hresh changes"
+
+# full flush of policy db, check everything gets freed incl. internal meta data
+ip -net ns3 xfrm policy flush
+
+do_esp_policy ns3 10.0.3.1 10.0.3.10 10.0.1.0/24 10.0.2.0/24
+do_exception ns3 10.0.3.1 10.0.3.10 10.0.2.253 10.0.2.240/28
+
+# move inexact policies to hash table
+ip -net ns3 xfrm policy set hthresh4 16 16
+
+sleep $((RANDOM%5))
+check_exceptions "exceptions and block policies after hthresh change in ns3"
+
+# restore original hthresh settings -- move policies back to tables
+for n in ns3 ns4;do
+       ip -net $n xfrm policy set hthresh4 32 32 hthresh6 128 128
+       sleep $((RANDOM%5))
+done
+check_exceptions "exceptions and block policies after hresh change to normal"
+
 for i in 1 2 3 4;do ip netns del ns$i;done
 
 exit $ret
index 47ed6ce..c9ff2b4 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 # Makefile for netfilter selftests
 
-TEST_PROGS := nft_trans_stress.sh
+TEST_PROGS := nft_trans_stress.sh nft_nat.sh
 
 include ../lib.mk
diff --git a/tools/testing/selftests/netfilter/nft_nat.sh b/tools/testing/selftests/netfilter/nft_nat.sh
new file mode 100755 (executable)
index 0000000..8ec7668
--- /dev/null
@@ -0,0 +1,762 @@
+#!/bin/bash
+#
+# This test is for basic NAT functionality: snat, dnat, redirect, masquerade.
+#
+
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+ret=0
+
+nft --version > /dev/null 2>&1
+if [ $? -ne 0 ];then
+       echo "SKIP: Could not run test without nft tool"
+       exit $ksft_skip
+fi
+
+ip -Version > /dev/null 2>&1
+if [ $? -ne 0 ];then
+       echo "SKIP: Could not run test without ip tool"
+       exit $ksft_skip
+fi
+
+ip netns add ns0
+ip netns add ns1
+ip netns add ns2
+
+ip link add veth0 netns ns0 type veth peer name eth0 netns ns1
+ip link add veth1 netns ns0 type veth peer name eth0 netns ns2
+
+ip -net ns0 link set lo up
+ip -net ns0 link set veth0 up
+ip -net ns0 addr add 10.0.1.1/24 dev veth0
+ip -net ns0 addr add dead:1::1/64 dev veth0
+
+ip -net ns0 link set veth1 up
+ip -net ns0 addr add 10.0.2.1/24 dev veth1
+ip -net ns0 addr add dead:2::1/64 dev veth1
+
+for i in 1 2; do
+  ip -net ns$i link set lo up
+  ip -net ns$i link set eth0 up
+  ip -net ns$i addr add 10.0.$i.99/24 dev eth0
+  ip -net ns$i route add default via 10.0.$i.1
+  ip -net ns$i addr add dead:$i::99/64 dev eth0
+  ip -net ns$i route add default via dead:$i::1
+done
+
+bad_counter()
+{
+       local ns=$1
+       local counter=$2
+       local expect=$3
+
+       echo "ERROR: $counter counter in $ns has unexpected value (expected $expect)" 1>&2
+       ip netns exec $ns nft list counter inet filter $counter 1>&2
+}
+
+check_counters()
+{
+       ns=$1
+       local lret=0
+
+       cnt=$(ip netns exec $ns nft list counter inet filter ns0in | grep -q "packets 1 bytes 84")
+       if [ $? -ne 0 ]; then
+               bad_counter $ns ns0in "packets 1 bytes 84"
+               lret=1
+       fi
+       cnt=$(ip netns exec $ns nft list counter inet filter ns0out | grep -q "packets 1 bytes 84")
+       if [ $? -ne 0 ]; then
+               bad_counter $ns ns0out "packets 1 bytes 84"
+               lret=1
+       fi
+
+       expect="packets 1 bytes 104"
+       cnt=$(ip netns exec $ns nft list counter inet filter ns0in6 | grep -q "$expect")
+       if [ $? -ne 0 ]; then
+               bad_counter $ns ns0in6 "$expect"
+               lret=1
+       fi
+       cnt=$(ip netns exec $ns nft list counter inet filter ns0out6 | grep -q "$expect")
+       if [ $? -ne 0 ]; then
+               bad_counter $ns ns0out6 "$expect"
+               lret=1
+       fi
+
+       return $lret
+}
+
+check_ns0_counters()
+{
+       local ns=$1
+       local lret=0
+
+       cnt=$(ip netns exec ns0 nft list counter inet filter ns0in | grep -q "packets 0 bytes 0")
+       if [ $? -ne 0 ]; then
+               bad_counter ns0 ns0in "packets 0 bytes 0"
+               lret=1
+       fi
+
+       cnt=$(ip netns exec ns0 nft list counter inet filter ns0in6 | grep -q "packets 0 bytes 0")
+       if [ $? -ne 0 ]; then
+               bad_counter ns0 ns0in6 "packets 0 bytes 0"
+               lret=1
+       fi
+
+       cnt=$(ip netns exec ns0 nft list counter inet filter ns0out | grep -q "packets 0 bytes 0")
+       if [ $? -ne 0 ]; then
+               bad_counter ns0 ns0out "packets 0 bytes 0"
+               lret=1
+       fi
+       cnt=$(ip netns exec ns0 nft list counter inet filter ns0out6 | grep -q "packets 0 bytes 0")
+       if [ $? -ne 0 ]; then
+               bad_counter ns0 ns0out6 "packets 0 bytes 0"
+               lret=1
+       fi
+
+       for dir in "in" "out" ; do
+               expect="packets 1 bytes 84"
+               cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 $ns$dir "$expect"
+                       lret=1
+               fi
+
+               expect="packets 1 bytes 104"
+               cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir}6 | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 $ns$dir6 "$expect"
+                       lret=1
+               fi
+       done
+
+       return $lret
+}
+
+reset_counters()
+{
+       for i in 0 1 2;do
+               ip netns exec ns$i nft reset counters inet > /dev/null
+       done
+}
+
+test_local_dnat6()
+{
+       local lret=0
+ip netns exec ns0 nft -f - <<EOF
+table ip6 nat {
+       chain output {
+               type nat hook output priority 0; policy accept;
+               ip6 daddr dead:1::99 dnat to dead:2::99
+       }
+}
+EOF
+       if [ $? -ne 0 ]; then
+               echo "SKIP: Could not add add ip6 dnat hook"
+               return $ksft_skip
+       fi
+
+       # ping netns1, expect rewrite to netns2
+       ip netns exec ns0 ping -q -c 1 dead:1::99 > /dev/null
+       if [ $? -ne 0 ]; then
+               lret=1
+               echo "ERROR: ping6 failed"
+               return $lret
+       fi
+
+       expect="packets 0 bytes 0"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       expect="packets 1 bytes 104"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 ns2$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # expect 0 count in ns1
+       expect="packets 0 bytes 0"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # expect 1 packet in ns2
+       expect="packets 1 bytes 104"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       test $lret -eq 0 && echo "PASS: ipv6 ping to ns1 was NATted to ns2"
+       ip netns exec ns0 nft flush chain ip6 nat output
+
+       return $lret
+}
+
+test_local_dnat()
+{
+       local lret=0
+ip netns exec ns0 nft -f - <<EOF
+table ip nat {
+       chain output {
+               type nat hook output priority 0; policy accept;
+               ip daddr 10.0.1.99 dnat to 10.0.2.99
+       }
+}
+EOF
+       # ping netns1, expect rewrite to netns2
+       ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null
+       if [ $? -ne 0 ]; then
+               lret=1
+               echo "ERROR: ping failed"
+               return $lret
+       fi
+
+       expect="packets 0 bytes 0"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 ns2$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # expect 0 count in ns1
+       expect="packets 0 bytes 0"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # expect 1 packet in ns2
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       test $lret -eq 0 && echo "PASS: ping to ns1 was NATted to ns2"
+
+       ip netns exec ns0 nft flush chain ip nat output
+
+       reset_counters
+       ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null
+       if [ $? -ne 0 ]; then
+               lret=1
+               echo "ERROR: ping failed"
+               return $lret
+       fi
+
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+       expect="packets 0 bytes 0"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 ns2$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # expect 1 count in ns1
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # expect 0 packet in ns2
+       expect="packets 0 bytes 0"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns2$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       test $lret -eq 0 && echo "PASS: ping to ns1 OK after nat output chain flush"
+
+       return $lret
+}
+
+
+test_masquerade6()
+{
+       local lret=0
+
+       ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
+
+       ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannot ping ns1 from ns2 via ipv6"
+               return 1
+               lret=1
+       fi
+
+       expect="packets 1 bytes 104"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns2$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       reset_counters
+
+# add masquerading rule
+ip netns exec ns0 nft -f - <<EOF
+table ip6 nat {
+       chain postrouting {
+               type nat hook postrouting priority 0; policy accept;
+               meta oif veth0 masquerade
+       }
+}
+EOF
+       ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannot ping ns1 from ns2 with active ipv6 masquerading"
+               lret=1
+       fi
+
+       # ns1 should have seen packets from ns0, due to masquerade
+       expect="packets 1 bytes 104"
+       for dir in "in6" "out6" ; do
+
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # ns1 should not have seen packets from ns2, due to masquerade
+       expect="packets 0 bytes 0"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       ip netns exec ns0 nft flush chain ip6 nat postrouting
+       if [ $? -ne 0 ]; then
+               echo "ERROR: Could not flush ip6 nat postrouting" 1>&2
+               lret=1
+       fi
+
+       test $lret -eq 0 && echo "PASS: IPv6 masquerade for ns2"
+
+       return $lret
+}
+
+test_masquerade()
+{
+       local lret=0
+
+       ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
+       ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
+
+       ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: canot ping ns1 from ns2"
+               lret=1
+       fi
+
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns2$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       reset_counters
+
+# add masquerading rule
+ip netns exec ns0 nft -f - <<EOF
+table ip nat {
+       chain postrouting {
+               type nat hook postrouting priority 0; policy accept;
+               meta oif veth0 masquerade
+       }
+}
+EOF
+       ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannot ping ns1 from ns2 with active ip masquerading"
+               lret=1
+       fi
+
+       # ns1 should have seen packets from ns0, due to masquerade
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # ns1 should not have seen packets from ns2, due to masquerade
+       expect="packets 0 bytes 0"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       ip netns exec ns0 nft flush chain ip nat postrouting
+       if [ $? -ne 0 ]; then
+               echo "ERROR: Could not flush nat postrouting" 1>&2
+               lret=1
+       fi
+
+       test $lret -eq 0 && echo "PASS: IP masquerade for ns2"
+
+       return $lret
+}
+
+test_redirect6()
+{
+       local lret=0
+
+       ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
+
+       ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannnot ping ns1 from ns2 via ipv6"
+               lret=1
+       fi
+
+       expect="packets 1 bytes 104"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns2$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       reset_counters
+
+# add redirect rule
+ip netns exec ns0 nft -f - <<EOF
+table ip6 nat {
+       chain prerouting {
+               type nat hook prerouting priority 0; policy accept;
+               meta iif veth1 meta l4proto icmpv6 ip6 saddr dead:2::99 ip6 daddr dead:1::99 redirect
+       }
+}
+EOF
+       ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannot ping ns1 from ns2 with active ip6 redirect"
+               lret=1
+       fi
+
+       # ns1 should have seen no packets from ns2, due to redirection
+       expect="packets 0 bytes 0"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # ns0 should have seen packets from ns2, due to masquerade
+       expect="packets 1 bytes 104"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       ip netns exec ns0 nft delete table ip6 nat
+       if [ $? -ne 0 ]; then
+               echo "ERROR: Could not delete ip6 nat table" 1>&2
+               lret=1
+       fi
+
+       test $lret -eq 0 && echo "PASS: IPv6 redirection for ns2"
+
+       return $lret
+}
+
+test_redirect()
+{
+       local lret=0
+
+       ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
+       ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
+
+       ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannot ping ns1 from ns2"
+               lret=1
+       fi
+
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns2$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       reset_counters
+
+# add redirect rule
+ip netns exec ns0 nft -f - <<EOF
+table ip nat {
+       chain prerouting {
+               type nat hook prerouting priority 0; policy accept;
+               meta iif veth1 ip protocol icmp ip saddr 10.0.2.99 ip daddr 10.0.1.99 redirect
+       }
+}
+EOF
+       ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannot ping ns1 from ns2 with active ip redirect"
+               lret=1
+       fi
+
+       # ns1 should have seen no packets from ns2, due to redirection
+       expect="packets 0 bytes 0"
+       for dir in "in" "out" ; do
+
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # ns0 should have seen packets from ns2, due to masquerade
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       ip netns exec ns0 nft delete table ip nat
+       if [ $? -ne 0 ]; then
+               echo "ERROR: Could not delete nat table" 1>&2
+               lret=1
+       fi
+
+       test $lret -eq 0 && echo "PASS: IP redirection for ns2"
+
+       return $lret
+}
+
+
+# ip netns exec ns0 ping -c 1 -q 10.0.$i.99
+for i in 0 1 2; do
+ip netns exec ns$i nft -f - <<EOF
+table inet filter {
+       counter ns0in {}
+       counter ns1in {}
+       counter ns2in {}
+
+       counter ns0out {}
+       counter ns1out {}
+       counter ns2out {}
+
+       counter ns0in6 {}
+       counter ns1in6 {}
+       counter ns2in6 {}
+
+       counter ns0out6 {}
+       counter ns1out6 {}
+       counter ns2out6 {}
+
+       map nsincounter {
+               type ipv4_addr : counter
+               elements = { 10.0.1.1 : "ns0in",
+                            10.0.2.1 : "ns0in",
+                            10.0.1.99 : "ns1in",
+                            10.0.2.99 : "ns2in" }
+       }
+
+       map nsincounter6 {
+               type ipv6_addr : counter
+               elements = { dead:1::1 : "ns0in6",
+                            dead:2::1 : "ns0in6",
+                            dead:1::99 : "ns1in6",
+                            dead:2::99 : "ns2in6" }
+       }
+
+       map nsoutcounter {
+               type ipv4_addr : counter
+               elements = { 10.0.1.1 : "ns0out",
+                            10.0.2.1 : "ns0out",
+                            10.0.1.99: "ns1out",
+                            10.0.2.99: "ns2out" }
+       }
+
+       map nsoutcounter6 {
+               type ipv6_addr : counter
+               elements = { dead:1::1 : "ns0out6",
+                            dead:2::1 : "ns0out6",
+                            dead:1::99 : "ns1out6",
+                            dead:2::99 : "ns2out6" }
+       }
+
+       chain input {
+               type filter hook input priority 0; policy accept;
+               counter name ip saddr map @nsincounter
+               icmpv6 type { "echo-request", "echo-reply" } counter name ip6 saddr map @nsincounter6
+       }
+       chain output {
+               type filter hook output priority 0; policy accept;
+               counter name ip daddr map @nsoutcounter
+               icmpv6 type { "echo-request", "echo-reply" } counter name ip6 daddr map @nsoutcounter6
+       }
+}
+EOF
+done
+
+sleep 3
+# test basic connectivity
+for i in 1 2; do
+  ip netns exec ns0 ping -c 1 -q 10.0.$i.99 > /dev/null
+  if [ $? -ne 0 ];then
+       echo "ERROR: Could not reach other namespace(s)" 1>&2
+       ret=1
+  fi
+
+  ip netns exec ns0 ping -c 1 -q dead:$i::99 > /dev/null
+  if [ $? -ne 0 ];then
+       echo "ERROR: Could not reach other namespace(s) via ipv6" 1>&2
+       ret=1
+  fi
+  check_counters ns$i
+  if [ $? -ne 0 ]; then
+       ret=1
+  fi
+
+  check_ns0_counters ns$i
+  if [ $? -ne 0 ]; then
+       ret=1
+  fi
+  reset_counters
+done
+
+if [ $ret -eq 0 ];then
+       echo "PASS: netns routing/connectivity: ns0 can reach ns1 and ns2"
+fi
+
+reset_counters
+test_local_dnat
+test_local_dnat6
+
+reset_counters
+test_masquerade
+test_masquerade6
+
+reset_counters
+test_redirect
+test_redirect6
+
+for i in 0 1 2; do ip netns del ns$i;done
+
+exit $ret
index 9050eee..1de8bd8 100644 (file)
@@ -9,6 +9,3 @@ all: $(TEST_PROGS)
 top_srcdir = ../../../../..
 KSFT_KHDR_INSTALL := 1
 include ../../lib.mk
-
-clean:
-       rm -fr $(TEST_GEN_FILES)
index 2e563d1..d1bbafb 100644 (file)
@@ -240,7 +240,7 @@ static void __recv_errmsg_cmsg(struct msghdr *msg, int payload_len)
                            cm->cmsg_type == IP_RECVERR) ||
                           (cm->cmsg_level == SOL_IPV6 &&
                            cm->cmsg_type == IPV6_RECVERR) ||
-                          (cm->cmsg_level = SOL_PACKET &&
+                          (cm->cmsg_level == SOL_PACKET &&
                            cm->cmsg_type == PACKET_TX_TIMESTAMP)) {
                        serr = (void *) CMSG_DATA(cm);
                        if (serr->ee_errno != ENOMSG ||
index 82121a8..29bac5e 100644 (file)
@@ -10,4 +10,5 @@
 /proc-uptime-002
 /read
 /self
+/setns-dcache
 /thread-self
index 1c12c34..434d033 100644 (file)
@@ -14,6 +14,7 @@ TEST_GEN_PROGS += proc-uptime-001
 TEST_GEN_PROGS += proc-uptime-002
 TEST_GEN_PROGS += read
 TEST_GEN_PROGS += self
+TEST_GEN_PROGS += setns-dcache
 TEST_GEN_PROGS += thread-self
 
 include ../lib.mk
diff --git a/tools/testing/selftests/proc/setns-dcache.c b/tools/testing/selftests/proc/setns-dcache.c
new file mode 100644 (file)
index 0000000..60ab197
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright Â© 2019 Alexey Dobriyan <adobriyan@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Test that setns(CLONE_NEWNET) points to new /proc/net content even
+ * if old one is in dcache.
+ *
+ * FIXME /proc/net/unix is under CONFIG_UNIX which can be disabled.
+ */
+#undef NDEBUG
+#include <assert.h>
+#include <errno.h>
+#include <sched.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+
+static pid_t pid = -1;
+
+static void f(void)
+{
+       if (pid > 0) {
+               kill(pid, SIGTERM);
+       }
+}
+
+int main(void)
+{
+       int fd[2];
+       char _ = 0;
+       int nsfd;
+
+       atexit(f);
+
+       /* Check for priviledges and syscall availability straight away. */
+       if (unshare(CLONE_NEWNET) == -1) {
+               if (errno == ENOSYS || errno == EPERM) {
+                       return 4;
+               }
+               return 1;
+       }
+       /* Distinguisher between two otherwise empty net namespaces. */
+       if (socket(AF_UNIX, SOCK_STREAM, 0) == -1) {
+               return 1;
+       }
+
+       if (pipe(fd) == -1) {
+               return 1;
+       }
+
+       pid = fork();
+       if (pid == -1) {
+               return 1;
+       }
+
+       if (pid == 0) {
+               if (unshare(CLONE_NEWNET) == -1) {
+                       return 1;
+               }
+
+               if (write(fd[1], &_, 1) != 1) {
+                       return 1;
+               }
+
+               pause();
+
+               return 0;
+       }
+
+       if (read(fd[0], &_, 1) != 1) {
+               return 1;
+       }
+
+       {
+               char buf[64];
+               snprintf(buf, sizeof(buf), "/proc/%u/ns/net", pid);
+               nsfd = open(buf, O_RDONLY);
+               if (nsfd == -1) {
+                       return 1;
+               }
+       }
+
+       /* Reliably pin dentry into dcache. */
+       (void)open("/proc/net/unix", O_RDONLY);
+
+       if (setns(nsfd, CLONE_NEWNET) == -1) {
+               return 1;
+       }
+
+       kill(pid, SIGTERM);
+       pid = 0;
+
+       {
+               char buf[4096];
+               ssize_t rv;
+               int fd;
+
+               fd = open("/proc/net/unix", O_RDONLY);
+               if (fd == -1) {
+                       return 1;
+               }
+
+#define S "Num       RefCount Protocol Flags    Type St Inode Path\n"
+               rv = read(fd, buf, sizeof(buf));
+
+               assert(rv == strlen(S));
+               assert(memcmp(buf, S, strlen(S)) == 0);
+       }
+
+       return 0;
+}
index e20b017..b206553 100644 (file)
@@ -145,15 +145,12 @@ TEST_F(rtc, alarm_alm_set) {
 
        rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
        ASSERT_NE(-1, rc);
-       EXPECT_NE(0, rc);
+       ASSERT_NE(0, rc);
 
        /* Disable alarm interrupts */
        rc = ioctl(self->fd, RTC_AIE_OFF, 0);
        ASSERT_NE(-1, rc);
 
-       if (rc == 0)
-               return;
-
        rc = read(self->fd, &data, sizeof(unsigned long));
        ASSERT_NE(-1, rc);
        TH_LOG("data: %lx", data);
@@ -202,7 +199,109 @@ TEST_F(rtc, alarm_wkalm_set) {
 
        rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
        ASSERT_NE(-1, rc);
-       EXPECT_NE(0, rc);
+       ASSERT_NE(0, rc);
+
+       rc = read(self->fd, &data, sizeof(unsigned long));
+       ASSERT_NE(-1, rc);
+
+       rc = ioctl(self->fd, RTC_RD_TIME, &tm);
+       ASSERT_NE(-1, rc);
+
+       new = timegm((struct tm *)&tm);
+       ASSERT_EQ(new, secs);
+}
+
+TEST_F(rtc, alarm_alm_set_minute) {
+       struct timeval tv = { .tv_sec = 62 };
+       unsigned long data;
+       struct rtc_time tm;
+       fd_set readfds;
+       time_t secs, new;
+       int rc;
+
+       rc = ioctl(self->fd, RTC_RD_TIME, &tm);
+       ASSERT_NE(-1, rc);
+
+       secs = timegm((struct tm *)&tm) + 60 - tm.tm_sec;
+       gmtime_r(&secs, (struct tm *)&tm);
+
+       rc = ioctl(self->fd, RTC_ALM_SET, &tm);
+       if (rc == -1) {
+               ASSERT_EQ(EINVAL, errno);
+               TH_LOG("skip alarms are not supported.");
+               return;
+       }
+
+       rc = ioctl(self->fd, RTC_ALM_READ, &tm);
+       ASSERT_NE(-1, rc);
+
+       TH_LOG("Alarm time now set to %02d:%02d:%02d.",
+              tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+       /* Enable alarm interrupts */
+       rc = ioctl(self->fd, RTC_AIE_ON, 0);
+       ASSERT_NE(-1, rc);
+
+       FD_ZERO(&readfds);
+       FD_SET(self->fd, &readfds);
+
+       rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
+       ASSERT_NE(-1, rc);
+       ASSERT_NE(0, rc);
+
+       /* Disable alarm interrupts */
+       rc = ioctl(self->fd, RTC_AIE_OFF, 0);
+       ASSERT_NE(-1, rc);
+
+       rc = read(self->fd, &data, sizeof(unsigned long));
+       ASSERT_NE(-1, rc);
+       TH_LOG("data: %lx", data);
+
+       rc = ioctl(self->fd, RTC_RD_TIME, &tm);
+       ASSERT_NE(-1, rc);
+
+       new = timegm((struct tm *)&tm);
+       ASSERT_EQ(new, secs);
+}
+
+TEST_F(rtc, alarm_wkalm_set_minute) {
+       struct timeval tv = { .tv_sec = 62 };
+       struct rtc_wkalrm alarm = { 0 };
+       struct rtc_time tm;
+       unsigned long data;
+       fd_set readfds;
+       time_t secs, new;
+       int rc;
+
+       rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time);
+       ASSERT_NE(-1, rc);
+
+       secs = timegm((struct tm *)&alarm.time) + 60 - alarm.time.tm_sec;
+       gmtime_r(&secs, (struct tm *)&alarm.time);
+
+       alarm.enabled = 1;
+
+       rc = ioctl(self->fd, RTC_WKALM_SET, &alarm);
+       if (rc == -1) {
+               ASSERT_EQ(EINVAL, errno);
+               TH_LOG("skip alarms are not supported.");
+               return;
+       }
+
+       rc = ioctl(self->fd, RTC_WKALM_RD, &alarm);
+       ASSERT_NE(-1, rc);
+
+       TH_LOG("Alarm time now set to %02d/%02d/%02d %02d:%02d:%02d.",
+              alarm.time.tm_mday, alarm.time.tm_mon + 1,
+              alarm.time.tm_year + 1900, alarm.time.tm_hour,
+              alarm.time.tm_min, alarm.time.tm_sec);
+
+       FD_ZERO(&readfds);
+       FD_SET(self->fd, &readfds);
+
+       rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
+       ASSERT_NE(-1, rc);
+       ASSERT_NE(0, rc);
 
        rc = read(self->fd, &data, sizeof(unsigned long));
        ASSERT_NE(-1, rc);
index fce7f4c..1760b3e 100644 (file)
@@ -9,7 +9,7 @@ BINARIES := seccomp_bpf seccomp_benchmark
 CFLAGS += -Wl,-no-as-needed -Wall
 
 seccomp_bpf: seccomp_bpf.c ../kselftest_harness.h
-       $(CC) $(CFLAGS) $(LDFLAGS) -lpthread $< -o $@
+       $(CC) $(CFLAGS) $(LDFLAGS) $< -lpthread -o $@
 
 TEST_PROGS += $(BINARIES)
 EXTRA_CLEAN := $(BINARIES)
index 067cb46..7e632b4 100644 (file)
@@ -1608,7 +1608,16 @@ TEST_F(TRACE_poke, getpid_runs_normally)
 #ifdef SYSCALL_NUM_RET_SHARE_REG
 # define EXPECT_SYSCALL_RETURN(val, action)    EXPECT_EQ(-1, action)
 #else
-# define EXPECT_SYSCALL_RETURN(val, action)    EXPECT_EQ(val, action)
+# define EXPECT_SYSCALL_RETURN(val, action)            \
+       do {                                            \
+               errno = 0;                              \
+               if (val < 0) {                          \
+                       EXPECT_EQ(-1, action);          \
+                       EXPECT_EQ(-(val), errno);       \
+               } else {                                \
+                       EXPECT_EQ(val, action);         \
+               }                                       \
+       } while (0)
 #endif
 
 /* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for
@@ -1647,7 +1656,7 @@ int get_syscall(struct __test_metadata *_metadata, pid_t tracee)
 
 /* Architecture-specific syscall changing routine. */
 void change_syscall(struct __test_metadata *_metadata,
-                   pid_t tracee, int syscall)
+                   pid_t tracee, int syscall, int result)
 {
        int ret;
        ARCH_REGS regs;
@@ -1706,7 +1715,7 @@ void change_syscall(struct __test_metadata *_metadata,
 #ifdef SYSCALL_NUM_RET_SHARE_REG
                TH_LOG("Can't modify syscall return on this architecture");
 #else
-               regs.SYSCALL_RET = EPERM;
+               regs.SYSCALL_RET = result;
 #endif
 
 #ifdef HAVE_GETREGS
@@ -1734,14 +1743,19 @@ void tracer_syscall(struct __test_metadata *_metadata, pid_t tracee,
        case 0x1002:
                /* change getpid to getppid. */
                EXPECT_EQ(__NR_getpid, get_syscall(_metadata, tracee));
-               change_syscall(_metadata, tracee, __NR_getppid);
+               change_syscall(_metadata, tracee, __NR_getppid, 0);
                break;
        case 0x1003:
-               /* skip gettid. */
+               /* skip gettid with valid return code. */
                EXPECT_EQ(__NR_gettid, get_syscall(_metadata, tracee));
-               change_syscall(_metadata, tracee, -1);
+               change_syscall(_metadata, tracee, -1, 45000);
                break;
        case 0x1004:
+               /* skip openat with error. */
+               EXPECT_EQ(__NR_openat, get_syscall(_metadata, tracee));
+               change_syscall(_metadata, tracee, -1, -ESRCH);
+               break;
+       case 0x1005:
                /* do nothing (allow getppid) */
                EXPECT_EQ(__NR_getppid, get_syscall(_metadata, tracee));
                break;
@@ -1774,9 +1788,11 @@ void tracer_ptrace(struct __test_metadata *_metadata, pid_t tracee,
        nr = get_syscall(_metadata, tracee);
 
        if (nr == __NR_getpid)
-               change_syscall(_metadata, tracee, __NR_getppid);
+               change_syscall(_metadata, tracee, __NR_getppid, 0);
+       if (nr == __NR_gettid)
+               change_syscall(_metadata, tracee, -1, 45000);
        if (nr == __NR_openat)
-               change_syscall(_metadata, tracee, -1);
+               change_syscall(_metadata, tracee, -1, -ESRCH);
 }
 
 FIXTURE_DATA(TRACE_syscall) {
@@ -1793,8 +1809,10 @@ FIXTURE_SETUP(TRACE_syscall)
                BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1002),
                BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_gettid, 0, 1),
                BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1003),
-               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
+               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_openat, 0, 1),
                BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1004),
+               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1005),
                BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
        };
 
@@ -1842,15 +1860,26 @@ TEST_F(TRACE_syscall, ptrace_syscall_redirected)
        EXPECT_NE(self->mypid, syscall(__NR_getpid));
 }
 
-TEST_F(TRACE_syscall, ptrace_syscall_dropped)
+TEST_F(TRACE_syscall, ptrace_syscall_errno)
+{
+       /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
+       teardown_trace_fixture(_metadata, self->tracer);
+       self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
+                                          true);
+
+       /* Tracer should skip the open syscall, resulting in ESRCH. */
+       EXPECT_SYSCALL_RETURN(-ESRCH, syscall(__NR_openat));
+}
+
+TEST_F(TRACE_syscall, ptrace_syscall_faked)
 {
        /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
        teardown_trace_fixture(_metadata, self->tracer);
        self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
                                           true);
 
-       /* Tracer should skip the open syscall, resulting in EPERM. */
-       EXPECT_SYSCALL_RETURN(EPERM, syscall(__NR_openat));
+       /* Tracer should skip the gettid syscall, resulting fake pid. */
+       EXPECT_SYSCALL_RETURN(45000, syscall(__NR_gettid));
 }
 
 TEST_F(TRACE_syscall, syscall_allowed)
@@ -1883,7 +1912,21 @@ TEST_F(TRACE_syscall, syscall_redirected)
        EXPECT_NE(self->mypid, syscall(__NR_getpid));
 }
 
-TEST_F(TRACE_syscall, syscall_dropped)
+TEST_F(TRACE_syscall, syscall_errno)
+{
+       long ret;
+
+       ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+       ASSERT_EQ(0, ret);
+
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
+       ASSERT_EQ(0, ret);
+
+       /* openat has been skipped and an errno return. */
+       EXPECT_SYSCALL_RETURN(-ESRCH, syscall(__NR_openat));
+}
+
+TEST_F(TRACE_syscall, syscall_faked)
 {
        long ret;
 
@@ -1894,8 +1937,7 @@ TEST_F(TRACE_syscall, syscall_dropped)
        ASSERT_EQ(0, ret);
 
        /* gettid has been skipped and an altered return value stored. */
-       EXPECT_SYSCALL_RETURN(EPERM, syscall(__NR_gettid));
-       EXPECT_NE(self->mytid, syscall(__NR_gettid));
+       EXPECT_SYSCALL_RETURN(45000, syscall(__NR_gettid));
 }
 
 TEST_F(TRACE_syscall, skip_after_RET_TRACE)
@@ -3044,7 +3086,7 @@ TEST(user_notification_basic)
        /* Check that the basic notification machinery works */
        listener = user_trap_syscall(__NR_getpid,
                                     SECCOMP_FILTER_FLAG_NEW_LISTENER);
-       EXPECT_GE(listener, 0);
+       ASSERT_GE(listener, 0);
 
        /* Installing a second listener in the chain should EBUSY */
        EXPECT_EQ(user_trap_syscall(__NR_getpid,
@@ -3103,7 +3145,7 @@ TEST(user_notification_kill_in_middle)
 
        listener = user_trap_syscall(__NR_getpid,
                                     SECCOMP_FILTER_FLAG_NEW_LISTENER);
-       EXPECT_GE(listener, 0);
+       ASSERT_GE(listener, 0);
 
        /*
         * Check that nothing bad happens when we kill the task in the middle
@@ -3152,7 +3194,7 @@ TEST(user_notification_signal)
 
        listener = user_trap_syscall(__NR_gettid,
                                     SECCOMP_FILTER_FLAG_NEW_LISTENER);
-       EXPECT_GE(listener, 0);
+       ASSERT_GE(listener, 0);
 
        pid = fork();
        ASSERT_GE(pid, 0);
@@ -3215,7 +3257,7 @@ TEST(user_notification_closed_listener)
 
        listener = user_trap_syscall(__NR_getpid,
                                     SECCOMP_FILTER_FLAG_NEW_LISTENER);
-       EXPECT_GE(listener, 0);
+       ASSERT_GE(listener, 0);
 
        /*
         * Check that we get an ENOSYS when the listener is closed.
@@ -3376,7 +3418,7 @@ TEST(seccomp_get_notif_sizes)
 {
        struct seccomp_notif_sizes sizes;
 
-       EXPECT_EQ(seccomp(SECCOMP_GET_NOTIF_SIZES, 0, &sizes), 0);
+       ASSERT_EQ(seccomp(SECCOMP_GET_NOTIF_SIZES, 0, &sizes), 0);
        EXPECT_EQ(sizes.seccomp_notif, sizeof(struct seccomp_notif));
        EXPECT_EQ(sizes.seccomp_notif_resp, sizeof(struct seccomp_notif_resp));
 }
index 637ea02..0da3545 100644 (file)
@@ -17,7 +17,7 @@
         "cmdUnderTest": "$TC actions add action ife encode allow mark pass index 2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 2",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*allow mark.*index 2",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*allow mark.*index 2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
@@ -41,7 +41,7 @@
         "cmdUnderTest": "$TC actions add action ife encode use mark 10 pipe index 2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 2",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*use mark.*index 2",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*use mark.*index 2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
@@ -65,7 +65,7 @@
         "cmdUnderTest": "$TC actions add action ife encode allow mark continue index 2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 2",
-        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0xED3E.*allow mark.*index 2",
+        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0[xX]ED3E.*allow mark.*index 2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
@@ -89,7 +89,7 @@
         "cmdUnderTest": "$TC actions add action ife encode use mark 789 drop index 2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 2",
-        "matchPattern": "action order [0-9]*: ife encode action drop.*type 0xED3E.*use mark 789.*index 2",
+        "matchPattern": "action order [0-9]*: ife encode action drop.*type 0[xX]ED3E.*use mark 789.*index 2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use mark 656768 reclassify index 2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 2",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xED3E.*use mark 656768.*index 2",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ED3E.*use mark 656768.*index 2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use mark 65 jump 1 index 2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 2",
-        "matchPattern": "action order [0-9]*: ife encode action jump 1.*type 0xED3E.*use mark 65.*index 2",
+        "matchPattern": "action order [0-9]*: ife encode action jump 1.*type 0[xX]ED3E.*use mark 65.*index 2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use mark 4294967295 reclassify index 90",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 90",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xED3E.*use mark 4294967295.*index 90",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ED3E.*use mark 4294967295.*index 90",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use mark 4294967295999 pipe index 90",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 90",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*use mark 4294967295999.*index 90",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*use mark 4294967295999.*index 90",
         "matchCount": "0",
         "teardown": []
     },
         "cmdUnderTest": "$TC actions add action ife encode allow prio pass index 9",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 9",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*allow prio.*index 9",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*allow prio.*index 9",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 7 pipe index 9",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 9",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*use prio 7.*index 9",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*use prio 7.*index 9",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 3 continue index 9",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 9",
-        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0xED3E.*use prio 3.*index 9",
+        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0[xX]ED3E.*use prio 3.*index 9",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow prio drop index 9",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 9",
-        "matchPattern": "action order [0-9]*: ife encode action drop.*type 0xED3E.*allow prio.*index 9",
+        "matchPattern": "action order [0-9]*: ife encode action drop.*type 0[xX]ED3E.*allow prio.*index 9",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 998877 reclassify index 9",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 9",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xED3E.*use prio 998877.*index 9",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ED3E.*use prio 998877.*index 9",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 998877 jump 10 index 9",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 9",
-        "matchPattern": "action order [0-9]*: ife encode action jump 10.*type 0xED3E.*use prio 998877.*index 9",
+        "matchPattern": "action order [0-9]*: ife encode action jump 10.*type 0[xX]ED3E.*use prio 998877.*index 9",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 4294967295 reclassify index 99",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 99",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xED3E.*use prio 4294967295.*index 99",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ED3E.*use prio 4294967295.*index 99",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 4294967298 pipe index 99",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 99",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*use prio 4294967298.*index 99",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*use prio 4294967298.*index 99",
         "matchCount": "0",
         "teardown": []
     },
         "cmdUnderTest": "$TC actions add action ife encode allow tcindex pass index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*allow tcindex.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*allow tcindex.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use tcindex 111 pipe index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*use tcindex 111.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*use tcindex 111.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use tcindex 1 continue index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0xED3E.*use tcindex 1.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0[xX]ED3E.*use tcindex 1.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use tcindex 1 continue index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0xED3E.*use tcindex 1.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0[xX]ED3E.*use tcindex 1.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow tcindex drop index 77",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 77",
-        "matchPattern": "action order [0-9]*: ife encode action drop.*type 0xED3E.*allow tcindex.*index 77",
+        "matchPattern": "action order [0-9]*: ife encode action drop.*type 0[xX]ED3E.*allow tcindex.*index 77",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow tcindex reclassify index 77",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 77",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xED3E.*allow tcindex.*index 77",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ED3E.*allow tcindex.*index 77",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow tcindex jump 999 index 77",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 77",
-        "matchPattern": "action order [0-9]*: ife encode action jump 999.*type 0xED3E.*allow tcindex.*index 77",
+        "matchPattern": "action order [0-9]*: ife encode action jump 999.*type 0[xX]ED3E.*allow tcindex.*index 77",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use tcindex 65535 pass index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*use tcindex 65535.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*use tcindex 65535.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use tcindex 65539 pipe index 1",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*use tcindex 65539.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*use tcindex 65539.*index 1",
         "matchCount": "0",
         "teardown": []
     },
         "cmdUnderTest": "$TC actions add action ife encode allow mark src 00:11:22:33:44:55 pipe index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*allow mark src 00:11:22:33:44:55.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*allow mark src 00:11:22:33:44:55.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 9876 dst 00:11:22:33:44:55 reclassify index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xED3E.*use prio 9876 dst 00:11:22:33:44:55.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ED3E.*use prio 9876 dst 00:11:22:33:44:55.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow tcindex src 00:aa:bb:cc:dd:ee dst 00:11:22:33:44:55 pass index 11",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 11",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*allow tcindex dst 00:11:22:33:44:55 src 00:aa:bb:cc:dd:ee .*index 11",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*allow tcindex dst 00:11:22:33:44:55 src 00:aa:bb:cc:dd:ee .*index 11",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use mark 7 type 0xfefe pass index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xFEFE.*use mark 7.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]FEFE.*use mark 7.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 444 type 0xabba pipe index 21",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 21",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xABBA.*use prio 444.*index 21",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ABBA.*use prio 444.*index 21",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use tcindex 5000 type 0xabcd reclassify index 21",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 21",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xABCD.*use tcindex 5000.*index 21",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ABCD.*use tcindex 5000.*index 21",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
     },
     {
         "id": "fac3",
-        "name": "Create valid ife encode action with index at 32-bit maximnum",
+        "name": "Create valid ife encode action with index at 32-bit maximum",
         "category": [
             "actions",
             "ife"
         "cmdUnderTest": "$TC actions add action ife encode allow mark pass index 4294967295",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 4294967295",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*allow mark.*index 4294967295",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*allow mark.*index 4294967295",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife decode pass index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife decode action pass.*type 0x0.*allow mark allow tcindex allow prio.*index 1",
+        "matchPattern": "action order [0-9]*: ife decode action pass.*type 0(x0)?.*allow mark allow tcindex allow prio.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife decode pipe index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife decode action pipe.*type 0x0.*allow mark allow tcindex allow prio.*index 1",
+        "matchPattern": "action order [0-9]*: ife decode action pipe.*type 0(x0)?.*allow mark allow tcindex allow prio.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife decode continue index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife decode action continue.*type 0x0.*allow mark allow tcindex allow prio.*index 1",
+        "matchPattern": "action order [0-9]*: ife decode action continue.*type 0(x0)?.*allow mark allow tcindex allow prio.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife decode drop index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife decode action drop.*type 0x0.*allow mark allow tcindex allow prio.*index 1",
+        "matchPattern": "action order [0-9]*: ife decode action drop.*type 0(x0)?.*allow mark allow tcindex allow prio.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife decode reclassify index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife decode action reclassify.*type 0x0.*allow mark allow tcindex allow prio.*index 1",
+        "matchPattern": "action order [0-9]*: ife decode action reclassify.*type 0(x0)?.*allow mark allow tcindex allow prio.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife decode jump 10 index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife decode action jump 10.*type 0x0.*allow mark allow tcindex allow prio.*index 1",
+        "matchPattern": "action order [0-9]*: ife decode action jump 10.*type 0(x0)?.*allow mark allow tcindex allow prio.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow mark pass index 4294967295999",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 4294967295999",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*allow mark.*index 4294967295999",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*allow mark.*index 4294967295999",
         "matchCount": "0",
         "teardown": []
     },
         "cmdUnderTest": "$TC actions add action ife encode allow mark kuka index 4",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 4",
-        "matchPattern": "action order [0-9]*: ife encode action kuka.*type 0xED3E.*allow mark.*index 4",
+        "matchPattern": "action order [0-9]*: ife encode action kuka.*type 0[xX]ED3E.*allow mark.*index 4",
         "matchCount": "0",
         "teardown": []
     },
         "cmdUnderTest": "$TC actions add action ife encode allow prio pipe index 4 cookie aabbccddeeff112233445566778800a1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 4",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*allow prio.*index 4.*cookie aabbccddeeff112233445566778800a1",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*allow prio.*index 4.*cookie aabbccddeeff112233445566778800a1",
         "matchCount": "1",
         "teardown": [
            "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow foo pipe index 4",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 4",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*allow foo.*index 4",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*allow foo.*index 4",
         "matchCount": "0",
         "teardown": []
     },
         "cmdUnderTest": "$TC actions add action ife encode allow prio type 70000 pipe index 4",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 4",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0x11170.*allow prio.*index 4",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]11170.*allow prio.*index 4",
         "matchCount": "0",
         "teardown": []
     },
index 10b2d89..e7e15a7 100644 (file)
         ]
     },
     {
-        "id": "ba4e",
-        "name": "Add tunnel_key set action with missing mandatory id parameter",
-        "category": [
-            "actions",
-            "tunnel_key"
-        ],
-        "setup": [
-            [
-                "$TC actions flush action tunnel_key",
-                0,
-                1,
-                255
-            ]
-        ],
-        "cmdUnderTest": "$TC actions add action tunnel_key set src_ip 10.10.10.1 dst_ip 20.20.20.2",
-        "expExitCode": "255",
-        "verifyCmd": "$TC actions list action tunnel_key",
-        "matchPattern": "action order [0-9]+: tunnel_key set.*src_ip 10.10.10.1.*dst_ip 20.20.20.2",
-        "matchCount": "0",
-        "teardown": [
-           [
-               "$TC actions flush action tunnel_key",
-               0,
-               1,
-               255
-           ]
-        ]
-    },
-    {
         "id": "a5e0",
         "name": "Add tunnel_key set action with invalid src_ip parameter",
         "category": [
         "cmdUnderTest": "$TC actions add action tunnel_key set src_ip 10.10.10.1 dst_ip 10.10.10.2 id 7 index 4 cookie aa11bb22cc33dd44ee55ff66aa11b1b2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action tunnel_key index 4",
-        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 10.10.10.1.*dst_ip 10.10.10.2.*key_id 7.*dst_port 0.*csum pipe.*index 4 ref.*cookie aa11bb22cc33dd44ee55ff66aa11b1b2",
+        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 10.10.10.1.*dst_ip 10.10.10.2.*key_id 7.*csum pipe.*index 4 ref.*cookie aa11bb22cc33dd44ee55ff66aa11b1b2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action tunnel_key"
index c02683c..7656c7c 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 CFLAGS += -O3 -Wl,-no-as-needed -Wall
-LDFLAGS += -lrt -lpthread -lm
+LDLIBS += -lrt -lpthread -lm
 
 # these are all "safe" tests that don't modify
 # system time or require escalated privileges
index 880b96f..c0534e2 100644 (file)
@@ -25,6 +25,7 @@ struct gup_benchmark {
        __u64 size;
        __u32 nr_pages_per_call;
        __u32 flags;
+       __u64 expansion[10];    /* For future use */
 };
 
 int main(int argc, char **argv)
index 50f7e92..bf1bb15 100644 (file)
@@ -1503,7 +1503,7 @@ exit:
                exit(20);
        }
        if (successes != total_nr_tests) {
-               eprintf("ERROR: succeded fewer than number of tries (%d != %d)\n",
+               eprintf("ERROR: succeeded fewer than number of tries (%d != %d)\n",
                                successes, total_nr_tests);
                exit(21);
        }
index 460b4bd..5d546dc 100644 (file)
@@ -1133,6 +1133,21 @@ void test_pkey_syscalls_bad_args(int *ptr, u16 pkey)
        pkey_assert(err);
 }
 
+void become_child(void)
+{
+       pid_t forkret;
+
+       forkret = fork();
+       pkey_assert(forkret >= 0);
+       dprintf3("[%d] fork() ret: %d\n", getpid(), forkret);
+
+       if (!forkret) {
+               /* in the child */
+               return;
+       }
+       exit(0);
+}
+
 /* Assumes that all pkeys other than 'pkey' are unallocated */
 void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
 {
@@ -1141,7 +1156,7 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
        int nr_allocated_pkeys = 0;
        int i;
 
-       for (i = 0; i < NR_PKEYS*2; i++) {
+       for (i = 0; i < NR_PKEYS*3; i++) {
                int new_pkey;
                dprintf1("%s() alloc loop: %d\n", __func__, i);
                new_pkey = alloc_pkey();
@@ -1152,21 +1167,27 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
                if ((new_pkey == -1) && (errno == ENOSPC)) {
                        dprintf2("%s() failed to allocate pkey after %d tries\n",
                                __func__, nr_allocated_pkeys);
-                       break;
+               } else {
+                       /*
+                        * Ensure the number of successes never
+                        * exceeds the number of keys supported
+                        * in the hardware.
+                        */
+                       pkey_assert(nr_allocated_pkeys < NR_PKEYS);
+                       allocated_pkeys[nr_allocated_pkeys++] = new_pkey;
                }
-               pkey_assert(nr_allocated_pkeys < NR_PKEYS);
-               allocated_pkeys[nr_allocated_pkeys++] = new_pkey;
+
+               /*
+                * Make sure that allocation state is properly
+                * preserved across fork().
+                */
+               if (i == NR_PKEYS*2)
+                       become_child();
        }
 
        dprintf3("%s()::%d\n", __func__, __LINE__);
 
        /*
-        * ensure it did not reach the end of the loop without
-        * failure:
-        */
-       pkey_assert(i < NR_PKEYS*2);
-
-       /*
         * There are 16 pkeys supported in hardware.  Three are
         * allocated by the time we get here:
         *   1. The default key (0)
index 00a26a8..9731133 100644 (file)
@@ -44,7 +44,6 @@ int main()
 #include <stdbool.h>
 #include <sys/ptrace.h>
 #include <sys/user.h>
-#include <sys/ucontext.h>
 #include <link.h>
 #include <sys/auxv.h>
 #include <dlfcn.h>
index 89a2444..59e417e 100644 (file)
@@ -6,7 +6,7 @@ VERSION = 1.0
 
 BINDIR=usr/bin
 WARNFLAGS=-Wall -Wshadow -W -Wformat -Wimplicit-function-declaration -Wimplicit-int
-override CFLAGS+= -O1 ${WARNFLAGS}
+override CFLAGS+= $(call cc-option,-O3,-O1) ${WARNFLAGS}
 # Add "-fstack-protector" only if toolchain supports it.
 override CFLAGS+= $(call cc-option,-fstack-protector-strong)
 CC?= $(CROSS_COMPILE)gcc
index 18fc112..d3a8755 100644 (file)
@@ -5,7 +5,9 @@
  * Example use:
  * cat /sys/kernel/debug/page_owner > page_owner_full.txt
  * grep -v ^PFN page_owner_full.txt > page_owner.txt
- * ./sort page_owner.txt sorted_page_owner.txt
+ * ./page_owner_sort page_owner.txt sorted_page_owner.txt
+ *
+ * See Documentation/vm/page_owner.rst
 */
 
 #include <stdio.h>
index 9e350fd..9c486fa 100644 (file)
@@ -626,6 +626,13 @@ static void vcpu_req_sleep(struct kvm_vcpu *vcpu)
                /* Awaken to handle a signal, request we sleep again later. */
                kvm_make_request(KVM_REQ_SLEEP, vcpu);
        }
+
+       /*
+        * Make sure we will observe a potential reset request if we've
+        * observed a change to the power state. Pairs with the smp_wmb() in
+        * kvm_psci_vcpu_on().
+        */
+       smp_rmb();
 }
 
 static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu)
@@ -639,6 +646,9 @@ static void check_vcpu_requests(struct kvm_vcpu *vcpu)
                if (kvm_check_request(KVM_REQ_SLEEP, vcpu))
                        vcpu_req_sleep(vcpu);
 
+               if (kvm_check_request(KVM_REQ_VCPU_RESET, vcpu))
+                       kvm_reset_vcpu(vcpu);
+
                /*
                 * Clear IRQ_PENDING requests that were made to guarantee
                 * that a VCPU sees new virtual interrupts.
index fbdf3ac..30251e2 100644 (file)
@@ -1695,11 +1695,14 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 
        vma_pagesize = vma_kernel_pagesize(vma);
        /*
-        * PUD level may not exist for a VM but PMD is guaranteed to
-        * exist.
+        * The stage2 has a minimum of 2 level table (For arm64 see
+        * kvm_arm_setup_stage2()). Hence, we are guaranteed that we can
+        * use PMD_SIZE huge mappings (even when the PMD is folded into PGD).
+        * As for PUD huge maps, we must make sure that we have at least
+        * 3 levels, i.e, PMD is not folded.
         */
        if ((vma_pagesize == PMD_SIZE ||
-            (vma_pagesize == PUD_SIZE && kvm_stage2_has_pud(kvm))) &&
+            (vma_pagesize == PUD_SIZE && kvm_stage2_has_pmd(kvm))) &&
            !force_pte) {
                gfn = (fault_ipa & huge_page_mask(hstate_vma(vma))) >> PAGE_SHIFT;
        }
index 9b73d3a..34d08ee 100644 (file)
@@ -104,12 +104,10 @@ static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu)
 
 static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 {
+       struct vcpu_reset_state *reset_state;
        struct kvm *kvm = source_vcpu->kvm;
        struct kvm_vcpu *vcpu = NULL;
-       struct swait_queue_head *wq;
        unsigned long cpu_id;
-       unsigned long context_id;
-       phys_addr_t target_pc;
 
        cpu_id = smccc_get_arg1(source_vcpu) & MPIDR_HWID_BITMASK;
        if (vcpu_mode_is_32bit(source_vcpu))
@@ -130,32 +128,30 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
                        return PSCI_RET_INVALID_PARAMS;
        }
 
-       target_pc = smccc_get_arg2(source_vcpu);
-       context_id = smccc_get_arg3(source_vcpu);
+       reset_state = &vcpu->arch.reset_state;
 
-       kvm_reset_vcpu(vcpu);
-
-       /* Gracefully handle Thumb2 entry point */
-       if (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) {
-               target_pc &= ~((phys_addr_t) 1);
-               vcpu_set_thumb(vcpu);
-       }
+       reset_state->pc = smccc_get_arg2(source_vcpu);
 
        /* Propagate caller endianness */
-       if (kvm_vcpu_is_be(source_vcpu))
-               kvm_vcpu_set_be(vcpu);
+       reset_state->be = kvm_vcpu_is_be(source_vcpu);
 
-       *vcpu_pc(vcpu) = target_pc;
        /*
         * NOTE: We always update r0 (or x0) because for PSCI v0.1
         * the general puspose registers are undefined upon CPU_ON.
         */
-       smccc_set_retval(vcpu, context_id, 0, 0, 0);
-       vcpu->arch.power_off = false;
-       smp_mb();               /* Make sure the above is visible */
+       reset_state->r0 = smccc_get_arg3(source_vcpu);
+
+       WRITE_ONCE(reset_state->reset, true);
+       kvm_make_request(KVM_REQ_VCPU_RESET, vcpu);
 
-       wq = kvm_arch_vcpu_wq(vcpu);
-       swake_up_one(wq);
+       /*
+        * Make sure the reset request is observed if the change to
+        * power_state is observed.
+        */
+       smp_wmb();
+
+       vcpu->arch.power_off = false;
+       kvm_vcpu_wake_up(vcpu);
 
        return PSCI_RET_SUCCESS;
 }
index 07aa900..1f62f2b 100644 (file)
@@ -251,9 +251,9 @@ static int vgic_debug_show(struct seq_file *s, void *v)
                return 0;
        }
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        print_irq_state(s, irq, vcpu);
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
        vgic_put_irq(kvm, irq);
        return 0;
index c0c0b88..3bdb31e 100644 (file)
@@ -64,7 +64,7 @@ void kvm_vgic_early_init(struct kvm *kvm)
        struct vgic_dist *dist = &kvm->arch.vgic;
 
        INIT_LIST_HEAD(&dist->lpi_list_head);
-       spin_lock_init(&dist->lpi_list_lock);
+       raw_spin_lock_init(&dist->lpi_list_lock);
 }
 
 /* CREATION */
@@ -171,7 +171,7 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
 
                irq->intid = i + VGIC_NR_PRIVATE_IRQS;
                INIT_LIST_HEAD(&irq->ap_list);
-               spin_lock_init(&irq->irq_lock);
+               raw_spin_lock_init(&irq->irq_lock);
                irq->vcpu = NULL;
                irq->target_vcpu = vcpu0;
                kref_init(&irq->refcount);
@@ -206,7 +206,7 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
        vgic_cpu->sgi_iodev.base_addr = VGIC_ADDR_UNDEF;
 
        INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
-       spin_lock_init(&vgic_cpu->ap_list_lock);
+       raw_spin_lock_init(&vgic_cpu->ap_list_lock);
 
        /*
         * Enable and configure all SGIs to be edge-triggered and
@@ -216,7 +216,7 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
                struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
 
                INIT_LIST_HEAD(&irq->ap_list);
-               spin_lock_init(&irq->irq_lock);
+               raw_spin_lock_init(&irq->irq_lock);
                irq->intid = i;
                irq->vcpu = NULL;
                irq->target_vcpu = vcpu;
@@ -231,13 +231,6 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
                        irq->config = VGIC_CONFIG_LEVEL;
                }
 
-               /*
-                * GICv3 can only be created via the KVM_DEVICE_CREATE API and
-                * so we always know the emulation type at this point as it's
-                * either explicitly configured as GICv3, or explicitly
-                * configured as GICv2, or not configured yet which also
-                * implies GICv2.
-                */
                if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
                        irq->group = 1;
                else
@@ -281,7 +274,7 @@ int vgic_init(struct kvm *kvm)
 {
        struct vgic_dist *dist = &kvm->arch.vgic;
        struct kvm_vcpu *vcpu;
-       int ret = 0, i;
+       int ret = 0, i, idx;
 
        if (vgic_initialized(kvm))
                return 0;
@@ -298,6 +291,19 @@ int vgic_init(struct kvm *kvm)
        if (ret)
                goto out;
 
+       /* Initialize groups on CPUs created before the VGIC type was known */
+       kvm_for_each_vcpu(idx, vcpu, kvm) {
+               struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+
+               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)
+                               irq->group = 1;
+                       else
+                               irq->group = 0;
+               }
+       }
+
        if (vgic_has_its(kvm)) {
                ret = vgic_v4_init(kvm);
                if (ret)
index eb2a390..ab3f477 100644 (file)
@@ -65,7 +65,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
 
        INIT_LIST_HEAD(&irq->lpi_list);
        INIT_LIST_HEAD(&irq->ap_list);
-       spin_lock_init(&irq->irq_lock);
+       raw_spin_lock_init(&irq->irq_lock);
 
        irq->config = VGIC_CONFIG_EDGE;
        kref_init(&irq->refcount);
@@ -73,7 +73,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
        irq->target_vcpu = vcpu;
        irq->group = 1;
 
-       spin_lock_irqsave(&dist->lpi_list_lock, flags);
+       raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
 
        /*
         * There could be a race with another vgic_add_lpi(), so we need to
@@ -101,7 +101,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
        dist->lpi_list_count++;
 
 out_unlock:
-       spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
+       raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
 
        /*
         * We "cache" the configuration table entries in our struct vgic_irq's.
@@ -287,7 +287,7 @@ static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
        if (ret)
                return ret;
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
        if (!filter_vcpu || filter_vcpu == irq->target_vcpu) {
                irq->priority = LPI_PROP_PRIORITY(prop);
@@ -299,7 +299,7 @@ static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
                }
        }
 
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
        if (irq->hw)
                return its_prop_update_vlpi(irq->host_irq, prop, needs_inv);
@@ -332,7 +332,7 @@ int vgic_copy_lpi_list(struct kvm *kvm, struct kvm_vcpu *vcpu, u32 **intid_ptr)
        if (!intids)
                return -ENOMEM;
 
-       spin_lock_irqsave(&dist->lpi_list_lock, flags);
+       raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
        list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
                if (i == irq_count)
                        break;
@@ -341,7 +341,7 @@ int vgic_copy_lpi_list(struct kvm *kvm, struct kvm_vcpu *vcpu, u32 **intid_ptr)
                        continue;
                intids[i++] = irq->intid;
        }
-       spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
+       raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
 
        *intid_ptr = intids;
        return i;
@@ -352,9 +352,9 @@ static int update_affinity(struct vgic_irq *irq, struct kvm_vcpu *vcpu)
        int ret = 0;
        unsigned long flags;
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        irq->target_vcpu = vcpu;
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
        if (irq->hw) {
                struct its_vlpi_map map;
@@ -455,7 +455,7 @@ static int its_sync_lpi_pending_table(struct kvm_vcpu *vcpu)
                }
 
                irq = vgic_get_irq(vcpu->kvm, NULL, intids[i]);
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                irq->pending_latch = pendmask & (1U << bit_nr);
                vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
                vgic_put_irq(vcpu->kvm, irq);
@@ -612,7 +612,7 @@ static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
                return irq_set_irqchip_state(irq->host_irq,
                                             IRQCHIP_STATE_PENDING, true);
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        irq->pending_latch = true;
        vgic_queue_irq_unlock(kvm, irq, flags);
 
index 738b65d..b535fff 100644 (file)
@@ -147,7 +147,7 @@ static void vgic_mmio_write_sgir(struct kvm_vcpu *source_vcpu,
 
                irq = vgic_get_irq(source_vcpu->kvm, vcpu, intid);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                irq->pending_latch = true;
                irq->source |= 1U << source_vcpu->vcpu_id;
 
@@ -191,13 +191,13 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid + i);
                int target;
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                irq->targets = (val >> (i * 8)) & cpu_mask;
                target = irq->targets ? __ffs(irq->targets) : 0;
                irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target);
 
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                vgic_put_irq(vcpu->kvm, irq);
        }
 }
@@ -230,13 +230,13 @@ static void vgic_mmio_write_sgipendc(struct kvm_vcpu *vcpu,
        for (i = 0; i < len; i++) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                irq->source &= ~((val >> (i * 8)) & 0xff);
                if (!irq->source)
                        irq->pending_latch = false;
 
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                vgic_put_irq(vcpu->kvm, irq);
        }
 }
@@ -252,7 +252,7 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
        for (i = 0; i < len; i++) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                irq->source |= (val >> (i * 8)) & 0xff;
 
@@ -260,7 +260,7 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
                        irq->pending_latch = true;
                        vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
                } else {
-                       spin_unlock_irqrestore(&irq->irq_lock, flags);
+                       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                }
                vgic_put_irq(vcpu->kvm, irq);
        }
index b3d1f09..4a12322 100644 (file)
@@ -169,13 +169,13 @@ static void vgic_mmio_write_irouter(struct kvm_vcpu *vcpu,
        if (!irq)
                return;
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
        /* We only care about and preserve Aff0, Aff1 and Aff2. */
        irq->mpidr = val & GENMASK(23, 0);
        irq->target_vcpu = kvm_mpidr_to_vcpu(vcpu->kvm, irq->mpidr);
 
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
        vgic_put_irq(vcpu->kvm, irq);
 }
 
@@ -281,7 +281,7 @@ static int vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu,
        for (i = 0; i < len * 8; i++) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                if (test_bit(i, &val)) {
                        /*
                         * pending_latch is set irrespective of irq type
@@ -292,7 +292,7 @@ static int vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu,
                        vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
                } else {
                        irq->pending_latch = false;
-                       spin_unlock_irqrestore(&irq->irq_lock, flags);
+                       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                }
 
                vgic_put_irq(vcpu->kvm, irq);
@@ -957,7 +957,7 @@ void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg, bool allow_group1)
 
                irq = vgic_get_irq(vcpu->kvm, c_vcpu, sgi);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                /*
                 * An access targetting Group0 SGIs can only generate
@@ -968,7 +968,7 @@ void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg, bool allow_group1)
                        irq->pending_latch = true;
                        vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
                } else {
-                       spin_unlock_irqrestore(&irq->irq_lock, flags);
+                       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                }
 
                vgic_put_irq(vcpu->kvm, irq);
index ceeda7e..7de42fb 100644 (file)
@@ -77,7 +77,7 @@ void vgic_mmio_write_group(struct kvm_vcpu *vcpu, gpa_t addr,
        for (i = 0; i < len * 8; i++) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                irq->group = !!(val & BIT(i));
                vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
 
@@ -120,7 +120,7 @@ void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
        for_each_set_bit(i, &val, len * 8) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                irq->enabled = true;
                vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
 
@@ -139,11 +139,11 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
        for_each_set_bit(i, &val, len * 8) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                irq->enabled = false;
 
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                vgic_put_irq(vcpu->kvm, irq);
        }
 }
@@ -160,10 +160,10 @@ unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
                unsigned long flags;
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                if (irq_is_pending(irq))
                        value |= (1U << i);
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
                vgic_put_irq(vcpu->kvm, irq);
        }
@@ -215,7 +215,7 @@ 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);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                if (irq->hw)
                        vgic_hw_irq_spending(vcpu, irq, is_uaccess);
                else
@@ -262,14 +262,14 @@ 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);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                if (irq->hw)
                        vgic_hw_irq_cpending(vcpu, irq, is_uaccess);
                else
                        irq->pending_latch = false;
 
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                vgic_put_irq(vcpu->kvm, irq);
        }
 }
@@ -311,7 +311,7 @@ static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
        unsigned long flags;
        struct kvm_vcpu *requester_vcpu = vgic_get_mmio_requester_vcpu();
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
        if (irq->hw) {
                vgic_hw_irq_change_active(vcpu, irq, active, !requester_vcpu);
@@ -342,7 +342,7 @@ static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
        if (irq->active)
                vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
        else
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 }
 
 /*
@@ -485,10 +485,10 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
        for (i = 0; i < len; i++) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                /* Narrow the priority range to what we actually support */
                irq->priority = (val >> (i * 8)) & GENMASK(7, 8 - VGIC_PRI_BITS);
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
                vgic_put_irq(vcpu->kvm, irq);
        }
@@ -534,14 +534,14 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
                        continue;
 
                irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                if (test_bit(i * 2 + 1, &val))
                        irq->config = VGIC_CONFIG_EDGE;
                else
                        irq->config = VGIC_CONFIG_LEVEL;
 
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                vgic_put_irq(vcpu->kvm, irq);
        }
 }
@@ -590,12 +590,12 @@ void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid,
                 * restore irq config before line level.
                 */
                new_level = !!(val & (1U << i));
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                irq->line_level = new_level;
                if (new_level)
                        vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
                else
-                       spin_unlock_irqrestore(&irq->irq_lock, flags);
+                       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
                vgic_put_irq(vcpu->kvm, irq);
        }
index 69b892a..d91a893 100644 (file)
@@ -84,7 +84,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
 
                irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
 
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&irq->irq_lock);
 
                /* Always preserve the active bit */
                irq->active = !!(val & GICH_LR_ACTIVE_BIT);
@@ -127,7 +127,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
                                vgic_irq_set_phys_active(irq, false);
                }
 
-               spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&irq->irq_lock);
                vgic_put_irq(vcpu->kvm, irq);
        }
 
index 9c0dd23..4ee0aeb 100644 (file)
@@ -76,7 +76,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
                if (!irq)       /* An LPI could have been unmapped. */
                        continue;
 
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&irq->irq_lock);
 
                /* Always preserve the active bit */
                irq->active = !!(val & ICH_LR_ACTIVE_BIT);
@@ -119,7 +119,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
                                vgic_irq_set_phys_active(irq, false);
                }
 
-               spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&irq->irq_lock);
                vgic_put_irq(vcpu->kvm, irq);
        }
 
@@ -347,9 +347,9 @@ retry:
 
        status = val & (1 << bit_nr);
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        if (irq->target_vcpu != vcpu) {
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                goto retry;
        }
        irq->pending_latch = status;
index 870b118..abd9c73 100644 (file)
@@ -54,11 +54,11 @@ struct vgic_global kvm_vgic_global_state __ro_after_init = {
  * When taking more than one ap_list_lock at the same time, always take the
  * lowest numbered VCPU's ap_list_lock first, so:
  *   vcpuX->vcpu_id < vcpuY->vcpu_id:
- *     spin_lock(vcpuX->arch.vgic_cpu.ap_list_lock);
- *     spin_lock(vcpuY->arch.vgic_cpu.ap_list_lock);
+ *     raw_spin_lock(vcpuX->arch.vgic_cpu.ap_list_lock);
+ *     raw_spin_lock(vcpuY->arch.vgic_cpu.ap_list_lock);
  *
  * Since the VGIC must support injecting virtual interrupts from ISRs, we have
- * to use the spin_lock_irqsave/spin_unlock_irqrestore versions of outer
+ * to use the raw_spin_lock_irqsave/raw_spin_unlock_irqrestore versions of outer
  * spinlocks for any lock that may be taken while injecting an interrupt.
  */
 
@@ -72,7 +72,7 @@ static struct vgic_irq *vgic_get_lpi(struct kvm *kvm, u32 intid)
        struct vgic_irq *irq = NULL;
        unsigned long flags;
 
-       spin_lock_irqsave(&dist->lpi_list_lock, flags);
+       raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
 
        list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
                if (irq->intid != intid)
@@ -88,7 +88,7 @@ static struct vgic_irq *vgic_get_lpi(struct kvm *kvm, u32 intid)
        irq = NULL;
 
 out_unlock:
-       spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
+       raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
 
        return irq;
 }
@@ -138,15 +138,15 @@ void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq)
        if (irq->intid < VGIC_MIN_LPI)
                return;
 
-       spin_lock_irqsave(&dist->lpi_list_lock, flags);
+       raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
        if (!kref_put(&irq->refcount, vgic_irq_release)) {
-               spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
+               raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
                return;
        };
 
        list_del(&irq->lpi_list);
        dist->lpi_list_count--;
-       spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
+       raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
 
        kfree(irq);
 }
@@ -244,8 +244,8 @@ static int vgic_irq_cmp(void *priv, struct list_head *a, struct list_head *b)
        bool penda, pendb;
        int ret;
 
-       spin_lock(&irqa->irq_lock);
-       spin_lock_nested(&irqb->irq_lock, SINGLE_DEPTH_NESTING);
+       raw_spin_lock(&irqa->irq_lock);
+       raw_spin_lock_nested(&irqb->irq_lock, SINGLE_DEPTH_NESTING);
 
        if (irqa->active || irqb->active) {
                ret = (int)irqb->active - (int)irqa->active;
@@ -263,8 +263,8 @@ static int vgic_irq_cmp(void *priv, struct list_head *a, struct list_head *b)
        /* Both pending and enabled, sort by priority */
        ret = irqa->priority - irqb->priority;
 out:
-       spin_unlock(&irqb->irq_lock);
-       spin_unlock(&irqa->irq_lock);
+       raw_spin_unlock(&irqb->irq_lock);
+       raw_spin_unlock(&irqa->irq_lock);
        return ret;
 }
 
@@ -325,7 +325,7 @@ retry:
                 * not need to be inserted into an ap_list and there is also
                 * no more work for us to do.
                 */
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
                /*
                 * We have to kick the VCPU here, because we could be
@@ -347,12 +347,12 @@ retry:
         * We must unlock the irq lock to take the ap_list_lock where
         * we are going to insert this new pending interrupt.
         */
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
        /* someone can do stuff here, which we re-check below */
 
-       spin_lock_irqsave(&vcpu->arch.vgic_cpu.ap_list_lock, flags);
-       spin_lock(&irq->irq_lock);
+       raw_spin_lock_irqsave(&vcpu->arch.vgic_cpu.ap_list_lock, flags);
+       raw_spin_lock(&irq->irq_lock);
 
        /*
         * Did something change behind our backs?
@@ -367,10 +367,11 @@ retry:
         */
 
        if (unlikely(irq->vcpu || vcpu != vgic_target_oracle(irq))) {
-               spin_unlock(&irq->irq_lock);
-               spin_unlock_irqrestore(&vcpu->arch.vgic_cpu.ap_list_lock, flags);
+               raw_spin_unlock(&irq->irq_lock);
+               raw_spin_unlock_irqrestore(&vcpu->arch.vgic_cpu.ap_list_lock,
+                                          flags);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                goto retry;
        }
 
@@ -382,8 +383,8 @@ retry:
        list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);
        irq->vcpu = vcpu;
 
-       spin_unlock(&irq->irq_lock);
-       spin_unlock_irqrestore(&vcpu->arch.vgic_cpu.ap_list_lock, flags);
+       raw_spin_unlock(&irq->irq_lock);
+       raw_spin_unlock_irqrestore(&vcpu->arch.vgic_cpu.ap_list_lock, flags);
 
        kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu);
        kvm_vcpu_kick(vcpu);
@@ -430,11 +431,11 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
        if (!irq)
                return -EINVAL;
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
        if (!vgic_validate_injection(irq, level, owner)) {
                /* Nothing to see here, move along... */
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                vgic_put_irq(kvm, irq);
                return 0;
        }
@@ -494,9 +495,9 @@ int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
 
        BUG_ON(!irq);
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        ret = kvm_vgic_map_irq(vcpu, irq, host_irq, get_input_level);
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
        vgic_put_irq(vcpu->kvm, irq);
 
        return ret;
@@ -519,11 +520,11 @@ void kvm_vgic_reset_mapped_irq(struct kvm_vcpu *vcpu, u32 vintid)
        if (!irq->hw)
                goto out;
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        irq->active = false;
        irq->pending_latch = false;
        irq->line_level = false;
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 out:
        vgic_put_irq(vcpu->kvm, irq);
 }
@@ -539,9 +540,9 @@ int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid)
        irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
        BUG_ON(!irq);
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        kvm_vgic_unmap_irq(irq);
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
        vgic_put_irq(vcpu->kvm, irq);
 
        return 0;
@@ -571,12 +572,12 @@ int kvm_vgic_set_owner(struct kvm_vcpu *vcpu, unsigned int intid, void *owner)
                return -EINVAL;
 
        irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        if (irq->owner && irq->owner != owner)
                ret = -EEXIST;
        else
                irq->owner = owner;
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
        return ret;
 }
@@ -597,13 +598,13 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
        DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());
 
 retry:
-       spin_lock(&vgic_cpu->ap_list_lock);
+       raw_spin_lock(&vgic_cpu->ap_list_lock);
 
        list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) {
                struct kvm_vcpu *target_vcpu, *vcpuA, *vcpuB;
                bool target_vcpu_needs_kick = false;
 
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&irq->irq_lock);
 
                BUG_ON(vcpu != irq->vcpu);
 
@@ -616,7 +617,7 @@ retry:
                         */
                        list_del(&irq->ap_list);
                        irq->vcpu = NULL;
-                       spin_unlock(&irq->irq_lock);
+                       raw_spin_unlock(&irq->irq_lock);
 
                        /*
                         * This vgic_put_irq call matches the
@@ -631,14 +632,14 @@ retry:
 
                if (target_vcpu == vcpu) {
                        /* We're on the right CPU */
-                       spin_unlock(&irq->irq_lock);
+                       raw_spin_unlock(&irq->irq_lock);
                        continue;
                }
 
                /* This interrupt looks like it has to be migrated. */
 
-               spin_unlock(&irq->irq_lock);
-               spin_unlock(&vgic_cpu->ap_list_lock);
+               raw_spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&vgic_cpu->ap_list_lock);
 
                /*
                 * Ensure locking order by always locking the smallest
@@ -652,10 +653,10 @@ retry:
                        vcpuB = vcpu;
                }
 
-               spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
-               spin_lock_nested(&vcpuB->arch.vgic_cpu.ap_list_lock,
-                                SINGLE_DEPTH_NESTING);
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
+               raw_spin_lock_nested(&vcpuB->arch.vgic_cpu.ap_list_lock,
+                                     SINGLE_DEPTH_NESTING);
+               raw_spin_lock(&irq->irq_lock);
 
                /*
                 * If the affinity has been preserved, move the
@@ -675,9 +676,9 @@ retry:
                        target_vcpu_needs_kick = true;
                }
 
-               spin_unlock(&irq->irq_lock);
-               spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
-               spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
+               raw_spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
+               raw_spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
 
                if (target_vcpu_needs_kick) {
                        kvm_make_request(KVM_REQ_IRQ_PENDING, target_vcpu);
@@ -687,7 +688,7 @@ retry:
                goto retry;
        }
 
-       spin_unlock(&vgic_cpu->ap_list_lock);
+       raw_spin_unlock(&vgic_cpu->ap_list_lock);
 }
 
 static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
@@ -741,10 +742,10 @@ static int compute_ap_list_depth(struct kvm_vcpu *vcpu,
        list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
                int w;
 
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&irq->irq_lock);
                /* GICv2 SGIs can count for more than one... */
                w = vgic_irq_get_lr_count(irq);
-               spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&irq->irq_lock);
 
                count += w;
                *multi_sgi |= (w > 1);
@@ -770,7 +771,7 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
        count = 0;
 
        list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&irq->irq_lock);
 
                /*
                 * If we have multi-SGIs in the pipeline, we need to
@@ -780,7 +781,7 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
                 * the AP list has been sorted already.
                 */
                if (multi_sgi && irq->priority > prio) {
-                       spin_unlock(&irq->irq_lock);
+                       _raw_spin_unlock(&irq->irq_lock);
                        break;
                }
 
@@ -791,7 +792,7 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
                                prio = irq->priority;
                }
 
-               spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&irq->irq_lock);
 
                if (count == kvm_vgic_global_state.nr_lr) {
                        if (!list_is_last(&irq->ap_list,
@@ -872,9 +873,9 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
 
        DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());
 
-       spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
+       raw_spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
        vgic_flush_lr_state(vcpu);
-       spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+       raw_spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
 
        if (can_access_vgic_from_kernel())
                vgic_restore_state(vcpu);
@@ -918,20 +919,20 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
 
        vgic_get_vmcr(vcpu, &vmcr);
 
-       spin_lock_irqsave(&vgic_cpu->ap_list_lock, flags);
+       raw_spin_lock_irqsave(&vgic_cpu->ap_list_lock, flags);
 
        list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&irq->irq_lock);
                pending = irq_is_pending(irq) && irq->enabled &&
                          !irq->active &&
                          irq->priority < vmcr.pmr;
-               spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&irq->irq_lock);
 
                if (pending)
                        break;
        }
 
-       spin_unlock_irqrestore(&vgic_cpu->ap_list_lock, flags);
+       raw_spin_unlock_irqrestore(&vgic_cpu->ap_list_lock, flags);
 
        return pending;
 }
@@ -963,11 +964,10 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid)
                return false;
 
        irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        map_is_active = irq->hw && irq->active;
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
        vgic_put_irq(vcpu->kvm, irq);
 
        return map_is_active;
 }
-
index 1f888a1..5858452 100644 (file)
@@ -1227,9 +1227,9 @@ int kvm_clear_dirty_log_protect(struct kvm *kvm,
 {
        struct kvm_memslots *slots;
        struct kvm_memory_slot *memslot;
-       int as_id, id, n;
+       int as_id, id;
        gfn_t offset;
-       unsigned long i;
+       unsigned long i, n;
        unsigned long *dirty_bitmap;
        unsigned long *dirty_bitmap_buffer;
 
@@ -1249,6 +1249,11 @@ int kvm_clear_dirty_log_protect(struct kvm *kvm,
                return -ENOENT;
 
        n = kvm_dirty_bitmap_bytes(memslot);
+
+       if (log->first_page > memslot->npages ||
+           log->num_pages > memslot->npages - log->first_page)
+                       return -EINVAL;
+
        *flush = false;
        dirty_bitmap_buffer = kvm_second_dirty_bitmap(memslot);
        if (copy_from_user(dirty_bitmap_buffer, log->dirty_bitmap, n))
@@ -2995,8 +3000,10 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
        if (ops->init)
                ops->init(dev);
 
+       kvm_get_kvm(kvm);
        ret = anon_inode_getfd(ops->name, &kvm_device_fops, dev, O_RDWR | O_CLOEXEC);
        if (ret < 0) {
+               kvm_put_kvm(kvm);
                mutex_lock(&kvm->lock);
                list_del(&dev->vm_node);
                mutex_unlock(&kvm->lock);
@@ -3004,7 +3011,6 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
                return ret;
        }
 
-       kvm_get_kvm(kvm);
        cd->fd = ret;
        return 0;
 }