Merge tag 'pinctrl-v5.8-4' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 1 Aug 2020 17:11:42 +0000 (10:11 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 1 Aug 2020 17:11:42 +0000 (10:11 -0700)
Pull pin control fix from Linus Walleij:
 "A single last minute pin control fix to the Qualcomm driver fixing
  missing dual edge PCH interrupts"

* tag 'pinctrl-v5.8-4' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl:
  pinctrl: qcom: Handle broken/missing PDC dual edge IRQs on sc7180

2077 files changed:
.gitignore
.mailmap
Documentation/ABI/testing/debugfs-driver-habanalabs
Documentation/ABI/testing/dev-kmsg
Documentation/ABI/testing/sysfs-bus-papr-pmem [new file with mode: 0644]
Documentation/ABI/testing/sysfs-platform-chipidea-usb-otg
Documentation/admin-guide/README.rst
Documentation/admin-guide/cgroup-v2.rst
Documentation/admin-guide/device-mapper/index.rst
Documentation/admin-guide/mm/transhuge.rst
Documentation/arm64/cpu-feature-registers.rst
Documentation/arm64/silicon-errata.rst
Documentation/arm64/sve.rst
Documentation/block/bfq-iosched.rst
Documentation/bpf/prog_cgroup_sockopt.rst
Documentation/core-api/dma-api.rst
Documentation/core-api/pin_user_pages.rst
Documentation/dev-tools/kcsan.rst
Documentation/dev-tools/kunit/faq.rst
Documentation/devicetree/bindings/Makefile
Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
Documentation/devicetree/bindings/bus/socionext,uniphier-system-bus.yaml
Documentation/devicetree/bindings/clock/imx27-clock.yaml
Documentation/devicetree/bindings/clock/imx31-clock.yaml
Documentation/devicetree/bindings/clock/imx5-clock.yaml
Documentation/devicetree/bindings/display/bridge/sii902x.txt
Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
Documentation/devicetree/bindings/display/imx/ldb.txt
Documentation/devicetree/bindings/display/panel/arm,versatile-tft-panel.yaml
Documentation/devicetree/bindings/display/rockchip/rockchip-drm.yaml
Documentation/devicetree/bindings/gpio/mediatek,mt7621-gpio.txt
Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.txt
Documentation/devicetree/bindings/media/allwinner,sun4i-a10-video-engine.yaml
Documentation/devicetree/bindings/misc/olpc,xo1.75-ec.txt
Documentation/devicetree/bindings/net/mediatek-bluetooth.txt
Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt
Documentation/devicetree/bindings/sound/audio-graph-card.txt
Documentation/devicetree/bindings/sound/simple-card.yaml
Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt
Documentation/devicetree/bindings/spi/amlogic,meson-gx-spicc.yaml
Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.txt
Documentation/devicetree/bindings/thermal/thermal-sensor.yaml
Documentation/devicetree/bindings/thermal/thermal-zones.yaml
Documentation/devicetree/bindings/thermal/ti,am654-thermal.yaml
Documentation/devicetree/bindings/timer/csky,mptimer.txt
Documentation/devicetree/bindings/usb/aspeed,usb-vhub.yaml
Documentation/devicetree/writing-schema.rst
Documentation/driver-api/media/v4l2-subdev.rst
Documentation/driver-api/ptp.rst
Documentation/filesystems/dax.txt
Documentation/filesystems/ext4/verity.rst
Documentation/filesystems/overlayfs.rst
Documentation/gpu/amdgpu.rst
Documentation/i2c/slave-eeprom-backend.rst
Documentation/i2c/smbus-protocol.rst
Documentation/kbuild/modules.rst
Documentation/kbuild/reproducible-builds.rst
Documentation/mips/ingenic-tcu.rst
Documentation/networking/arcnet.rst
Documentation/networking/ax25.rst
Documentation/networking/bareudp.rst
Documentation/networking/can_ucan_protocol.rst
Documentation/networking/dsa/dsa.rst
Documentation/networking/ieee802154.rst
Documentation/networking/ip-sysctl.rst
Documentation/networking/ipvs-sysctl.rst
Documentation/networking/rxrpc.rst
Documentation/powerpc/papr_hcalls.rst
Documentation/powerpc/vas-api.rst
Documentation/process/changes.rst
Documentation/process/coding-style.rst
Documentation/sh/index.rst
Documentation/userspace-api/media/conf_nitpick.py
Documentation/virt/kvm/api.rst
MAINTAINERS
Makefile
arch/arc/Kconfig
arch/arc/Makefile
arch/arc/include/asm/elf.h
arch/arc/include/asm/irqflags-compact.h
arch/arc/kernel/entry.S
arch/arc/kernel/head.S
arch/arc/kernel/setup.c
arch/arm/boot/dts/am335x-baltos.dtsi
arch/arm/boot/dts/am335x-boneblack-common.dtsi
arch/arm/boot/dts/am335x-boneblack-wireless.dts
arch/arm/boot/dts/am335x-boneblue.dts
arch/arm/boot/dts/am335x-bonegreen-wireless.dts
arch/arm/boot/dts/am335x-evm.dts
arch/arm/boot/dts/am335x-evmsk.dts
arch/arm/boot/dts/am335x-lxm.dts
arch/arm/boot/dts/am335x-moxa-uc-2100-common.dtsi
arch/arm/boot/dts/am335x-moxa-uc-8100-me-t.dts
arch/arm/boot/dts/am335x-pepper.dts
arch/arm/boot/dts/am335x-phycore-som.dtsi
arch/arm/boot/dts/am335x-pocketbeagle.dts
arch/arm/boot/dts/am33xx-l4.dtsi
arch/arm/boot/dts/am33xx.dtsi
arch/arm/boot/dts/am4372.dtsi
arch/arm/boot/dts/am437x-cm-t43.dts
arch/arm/boot/dts/am437x-gp-evm.dts
arch/arm/boot/dts/am437x-l4.dtsi
arch/arm/boot/dts/am437x-sk-evm.dts
arch/arm/boot/dts/am43x-epos-evm.dts
arch/arm/boot/dts/am5729-beagleboneai.dts
arch/arm/boot/dts/armada-38x.dtsi
arch/arm/boot/dts/bcm-nsp.dtsi
arch/arm/boot/dts/bcm47094-luxul-xwc-2000.dts
arch/arm/boot/dts/bcm958522er.dts
arch/arm/boot/dts/bcm958525er.dts
arch/arm/boot/dts/bcm958525xmc.dts
arch/arm/boot/dts/bcm958622hr.dts
arch/arm/boot/dts/bcm958623hr.dts
arch/arm/boot/dts/bcm958625hr.dts
arch/arm/boot/dts/bcm958625k.dts
arch/arm/boot/dts/dra7-evm-common.dtsi
arch/arm/boot/dts/dra7-l4.dtsi
arch/arm/boot/dts/imx6qdl-gw551x.dtsi
arch/arm/boot/dts/imx6qdl-icore.dtsi
arch/arm/boot/dts/imx6sx-sabreauto.dts
arch/arm/boot/dts/imx6sx-sdb.dtsi
arch/arm/boot/dts/imx6ul-kontron-n6x1x-s.dtsi
arch/arm/boot/dts/imx6ul-kontron-n6x1x-som-common.dtsi
arch/arm/boot/dts/keystone-k2g-evm.dts
arch/arm/boot/dts/meson.dtsi
arch/arm/boot/dts/motorola-cpcap-mapphone.dtsi
arch/arm/boot/dts/omap3-n900.dts
arch/arm/boot/dts/omap4-duovero-parlor.dts
arch/arm/boot/dts/omap4.dtsi
arch/arm/boot/dts/socfpga.dtsi
arch/arm/boot/dts/socfpga_arria10.dtsi
arch/arm/boot/dts/sun4i-a10.dtsi
arch/arm/boot/dts/sun5i.dtsi
arch/arm/boot/dts/sun7i-a20.dtsi
arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
arch/arm/include/asm/efi.h
arch/arm/include/asm/percpu.h
arch/arm/kernel/asm-offsets.c
arch/arm/kernel/ftrace.c
arch/arm/kernel/hw_breakpoint.c
arch/arm/kernel/kgdb.c
arch/arm/kernel/traps.c
arch/arm/kernel/vdso.c
arch/arm/mach-bcm/Kconfig
arch/arm/mach-imx/devices/devices-common.h
arch/arm/mach-imx/devices/platform-gpio-mxc.c
arch/arm/mach-imx/devices/platform-imx-dma.c
arch/arm/mach-imx/mm-imx21.c
arch/arm/mach-imx/mm-imx27.c
arch/arm/mach-imx/pm-imx5.c
arch/arm/mach-imx/pm-imx6.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-sti/board-dt.c
arch/arm/mm/alignment.c
arch/arm/mm/mmu.c
arch/arm/xen/enlighten.c
arch/arm64/Kconfig
arch/arm64/Kconfig.debug
arch/arm64/Makefile
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_nand.dts
arch/arm64/boot/dts/amlogic/meson-gxl-s805x-libretech-ac.dts
arch/arm64/boot/dts/amlogic/meson-gxl-s805x-p241.dts
arch/arm64/boot/dts/amlogic/meson-gxl-s805x.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
arch/arm64/boot/dts/freescale/imx8mm-beacon-som.dtsi
arch/arm64/boot/dts/freescale/imx8mm-evk.dts
arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts
arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts
arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
arch/arm64/configs/defconfig
arch/arm64/include/asm/alternative.h
arch/arm64/include/asm/arch_gicv3.h
arch/arm64/include/asm/arch_timer.h
arch/arm64/include/asm/checksum.h
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/cputype.h
arch/arm64/include/asm/debug-monitors.h
arch/arm64/include/asm/linkage.h
arch/arm64/include/asm/mmu.h
arch/arm64/include/asm/pgtable-prot.h
arch/arm64/include/asm/pgtable.h
arch/arm64/include/asm/smp.h
arch/arm64/include/asm/syscall.h
arch/arm64/include/asm/thread_info.h
arch/arm64/include/asm/vdso/clocksource.h
arch/arm64/include/asm/vdso/compat_gettimeofday.h
arch/arm64/kernel/Makefile
arch/arm64/kernel/alternative.c
arch/arm64/kernel/cpu_errata.c
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/debug-monitors.c
arch/arm64/kernel/entry-common.c
arch/arm64/kernel/entry.S
arch/arm64/kernel/fpsimd.c
arch/arm64/kernel/hw_breakpoint.c
arch/arm64/kernel/insn.c
arch/arm64/kernel/kgdb.c
arch/arm64/kernel/machine_kexec_file.c
arch/arm64/kernel/perf_regs.c
arch/arm64/kernel/probes/kprobes.c
arch/arm64/kernel/ptrace.c
arch/arm64/kernel/signal.c
arch/arm64/kernel/signal32.c
arch/arm64/kernel/syscall.c
arch/arm64/kernel/traps.c
arch/arm64/kernel/vdso.c
arch/arm64/kernel/vdso/Makefile
arch/arm64/kernel/vdso/sigreturn.S
arch/arm64/kernel/vdso32/Makefile
arch/arm64/kernel/vdso32/sigreturn.S [deleted file]
arch/arm64/kernel/vdso32/vdso.lds.S
arch/arm64/kernel/vmlinux.lds.S
arch/arm64/kvm/hyp-init.S
arch/arm64/kvm/pmu.c
arch/arm64/kvm/pvtime.c
arch/arm64/kvm/reset.c
arch/arm64/kvm/vgic/vgic-v4.c
arch/arm64/mm/init.c
arch/arm64/mm/mmu.c
arch/csky/kernel/ftrace.c
arch/ia64/include/asm/sections.h
arch/ia64/kernel/ftrace.c
arch/ia64/kernel/unwind_i.h
arch/m68k/kernel/setup_no.c
arch/m68k/mm/mcfmmu.c
arch/mips/boot/dts/ingenic/gcw0.dts
arch/mips/include/asm/unroll.h
arch/mips/kernel/kprobes.c
arch/mips/kernel/traps.c
arch/mips/kvm/emulate.c
arch/mips/kvm/mips.c
arch/mips/lantiq/xway/sysctrl.c
arch/mips/pci/pci-xtalk-bridge.c
arch/nds32/kernel/ftrace.c
arch/openrisc/kernel/dma.c
arch/parisc/include/asm/atomic.h
arch/parisc/include/asm/cmpxchg.h
arch/parisc/kernel/ftrace.c
arch/parisc/kernel/kgdb.c
arch/parisc/kernel/process.c
arch/parisc/lib/bitops.c
arch/parisc/lib/memcpy.c
arch/powerpc/include/asm/icswx.h
arch/powerpc/include/asm/nohash/32/pgtable.h
arch/powerpc/include/asm/sections.h
arch/powerpc/include/uapi/asm/papr_pdsm.h [new file with mode: 0644]
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/kgdb.c
arch/powerpc/kernel/kprobes.c
arch/powerpc/kernel/module_64.c
arch/powerpc/kernel/paca.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/trace/ftrace.c
arch/powerpc/kvm/book3s_64_mmu_radix.c
arch/powerpc/lib/inst.c
arch/powerpc/mm/book3s64/hash_utils.c
arch/powerpc/mm/book3s64/pkeys.c
arch/powerpc/mm/nohash/kaslr_booke.c
arch/powerpc/oprofile/backtrace.c
arch/powerpc/perf/callchain_32.c
arch/powerpc/perf/callchain_64.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/platforms/cell/spu_callbacks.c
arch/powerpc/platforms/powernv/vas-fault.c
arch/powerpc/platforms/pseries/papr_scm.c
arch/powerpc/sysdev/fsl_pci.c
arch/riscv/Kconfig
arch/riscv/include/asm/barrier.h
arch/riscv/include/asm/cmpxchg.h
arch/riscv/include/asm/gdb_xml.h
arch/riscv/include/asm/kgdb.h
arch/riscv/include/asm/thread_info.h
arch/riscv/kernel/ftrace.c
arch/riscv/kernel/kgdb.c
arch/riscv/kernel/patch.c
arch/riscv/kernel/sys_riscv.c
arch/riscv/kernel/traps.c
arch/riscv/kernel/vdso/Makefile
arch/riscv/kernel/vdso/vgettimeofday.c
arch/riscv/mm/init.c
arch/riscv/mm/kasan_init.c
arch/riscv/mm/pageattr.c
arch/s390/Kconfig
arch/s390/configs/debug_defconfig
arch/s390/configs/defconfig
arch/s390/configs/zfcpdump_defconfig
arch/s390/crypto/prng.c
arch/s390/include/asm/kvm_host.h
arch/s390/include/asm/syscall.h
arch/s390/include/asm/vdso.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/debug.c
arch/s390/kernel/early.c
arch/s390/kernel/entry.S
arch/s390/kernel/ftrace.c
arch/s390/kernel/ipl.c
arch/s390/kernel/perf_cpum_cf_events.c
arch/s390/kernel/perf_cpum_sf.c
arch/s390/kernel/ptrace.c
arch/s390/kernel/setup.c
arch/s390/kernel/time.c
arch/s390/kernel/uv.c
arch/s390/kernel/vdso64/Makefile
arch/s390/kernel/vdso64/clock_getres.S
arch/s390/mm/fault.c
arch/s390/mm/hugetlbpage.c
arch/s390/mm/maccess.c
arch/s390/pci/pci_event.c
arch/sh/include/asm/pgalloc.h
arch/sh/kernel/entry-common.S
arch/sh/kernel/ftrace.c
arch/sh/kernel/traps.c
arch/um/kernel/maccess.c
arch/x86/Kconfig
arch/x86/boot/compressed/Makefile
arch/x86/boot/compressed/head_64.S
arch/x86/entry/Makefile
arch/x86/entry/common.c
arch/x86/entry/entry_32.S
arch/x86/entry/entry_64_compat.S
arch/x86/events/Makefile
arch/x86/hyperv/hv_init.c
arch/x86/include/asm/bitops.h
arch/x86/include/asm/bug.h
arch/x86/include/asm/cpu.h
arch/x86/include/asm/cpumask.h
arch/x86/include/asm/fpu/internal.h
arch/x86/include/asm/idtentry.h
arch/x86/include/asm/io_bitmap.h
arch/x86/include/asm/iosf_mbi.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/mwait.h
arch/x86/include/asm/paravirt.h
arch/x86/include/asm/paravirt_types.h
arch/x86/include/asm/pgtable_types.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/ptrace.h
arch/x86/include/uapi/asm/kvm.h
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/msi.c
arch/x86/kernel/apic/vector.c
arch/x86/kernel/cpu/centaur.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/cpu.h
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/cpu/mce/core.c
arch/x86/kernel/cpu/resctrl/core.c
arch/x86/kernel/cpu/resctrl/internal.h
arch/x86/kernel/cpu/resctrl/rdtgroup.c
arch/x86/kernel/cpu/umwait.c
arch/x86/kernel/cpu/zhaoxin.c
arch/x86/kernel/dumpstack.c
arch/x86/kernel/fpu/core.c
arch/x86/kernel/fpu/xstate.c
arch/x86/kernel/ftrace.c
arch/x86/kernel/kgdb.c
arch/x86/kernel/kprobes/core.c
arch/x86/kernel/kprobes/opt.c
arch/x86/kernel/ldt.c
arch/x86/kernel/nmi.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/probe_roms.c
arch/x86/kernel/process.c
arch/x86/kernel/stacktrace.c
arch/x86/kernel/traps.c
arch/x86/kernel/unwind_orc.c
arch/x86/kernel/vmlinux.lds.S
arch/x86/kvm/kvm_cache_regs.h
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.h
arch/x86/kvm/mmu/mmu.c
arch/x86/kvm/mmu/paging_tmpl.h
arch/x86/kvm/svm/svm.c
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/vmcs.h
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/vmx/vmx.h
arch/x86/kvm/x86.c
arch/x86/lib/memcpy_64.S
arch/x86/lib/usercopy_64.c
arch/x86/math-emu/wm_sqrt.S
arch/x86/mm/fault.c
arch/x86/mm/init_32.c
arch/x86/mm/maccess.c
arch/x86/pci/pcbios.c
arch/x86/platform/intel-mid/sfi.c
arch/x86/platform/uv/uv_irq.c
arch/x86/power/cpu.c
arch/x86/purgatory/Makefile
arch/x86/xen/enlighten_pv.c
arch/x86/xen/xen-asm_64.S
arch/xtensa/include/asm/checksum.h
arch/xtensa/kernel/perf_event.c
arch/xtensa/kernel/setup.c
arch/xtensa/kernel/xtensa_ksyms.c
block/bio-integrity.c
block/blk-mq-debugfs.c
block/blk-mq-tag.c
block/blk-mq.c
block/keyslot-manager.c
block/partitions/ldm.c
block/partitions/ldm.h
crypto/af_alg.c
crypto/algboss.c
crypto/algif_aead.c
crypto/algif_hash.c
crypto/algif_skcipher.c
crypto/asymmetric_keys/public_key.c
crypto/drbg.c
drivers/acpi/acpi_configfs.c
drivers/acpi/dptf/dptf_power.c
drivers/acpi/fan.c
drivers/acpi/sysfs.c
drivers/amba/tegra-ahb.c
drivers/android/binder.c
drivers/android/binder_alloc.c
drivers/ata/libata-core.c
drivers/ata/libata-scsi.c
drivers/ata/sata_rcar.c
drivers/base/base.h
drivers/base/core.c
drivers/base/dd.c
drivers/base/power/trace.c
drivers/base/property.c
drivers/base/regmap/Kconfig
drivers/base/regmap/regmap-debugfs.c
drivers/base/regmap/regmap.c
drivers/block/drbd/drbd_int.h
drivers/block/drbd/drbd_protocol.h
drivers/block/loop.c
drivers/block/nbd.c
drivers/block/rbd.c
drivers/block/virtio_blk.c
drivers/block/zram/zram_drv.c
drivers/bus/ti-sysc.c
drivers/char/hw_random/ks-sa-rng.c
drivers/char/mem.c
drivers/char/random.c
drivers/char/tpm/st33zp24/i2c.c
drivers/char/tpm/st33zp24/spi.c
drivers/char/tpm/st33zp24/st33zp24.c
drivers/char/tpm/tpm-dev-common.c
drivers/char/tpm/tpm_ibmvtpm.c
drivers/char/tpm/tpm_tis.c
drivers/char/tpm/tpm_tis_core.c
drivers/char/tpm/tpm_tis_spi_main.c
drivers/char/virtio_console.c
drivers/clk/Kconfig
drivers/clk/clk-ast2600.c
drivers/clk/mvebu/Kconfig
drivers/clk/sifive/fu540-prci.c
drivers/clocksource/arm_arch_timer.c
drivers/clocksource/timer-ti-dm-systimer.c
drivers/counter/104-quad-8.c
drivers/cpufreq/intel_pstate.c
drivers/cpuidle/cpuidle.c
drivers/crypto/caam/Kconfig
drivers/crypto/caam/ctrl.c
drivers/crypto/caam/desc.h
drivers/crypto/caam/pdb.h
drivers/crypto/ccp/sev-dev.c
drivers/crypto/chelsio/chcr_crypto.h
drivers/crypto/chelsio/chtls/chtls_cm.c
drivers/crypto/chelsio/chtls/chtls_io.c
drivers/crypto/hisilicon/sgl.c
drivers/crypto/marvell/octeontx/otx_cptvf_algs.c
drivers/dio/dio.c
drivers/dma-buf/dma-buf.c
drivers/dma/dmatest.c
drivers/dma/dw/core.c
drivers/dma/fsl-edma-common.c
drivers/dma/fsl-edma-common.h
drivers/dma/fsl-edma.c
drivers/dma/idxd/cdev.c
drivers/dma/idxd/device.c
drivers/dma/idxd/idxd.h
drivers/dma/idxd/irq.c
drivers/dma/idxd/sysfs.c
drivers/dma/imx-sdma.c
drivers/dma/ioat/dma.c
drivers/dma/ioat/dma.h
drivers/dma/mcf-edma.c
drivers/dma/milbeaut-hdmac.c
drivers/dma/milbeaut-xdmac.c
drivers/dma/moxart-dma.c
drivers/dma/sh/usb-dmac.c
drivers/dma/tegra20-apb-dma.c
drivers/dma/tegra210-adma.c
drivers/dma/ti/edma.c
drivers/dma/ti/k3-udma-private.c
drivers/dma/ti/k3-udma.c
drivers/dma/timb_dma.c
drivers/edac/amd64_edac.c
drivers/firewire/core-cdev.c
drivers/firewire/core-transaction.c
drivers/firewire/core.h
drivers/firewire/nosy.c
drivers/firewire/ohci.c
drivers/firmware/dmi-sysfs.c
drivers/firmware/efi/Kconfig
drivers/firmware/efi/arm-init.c
drivers/firmware/efi/efi-pstore.c
drivers/firmware/efi/efi.c
drivers/firmware/efi/efivars.c
drivers/firmware/efi/esrt.c
drivers/firmware/efi/libstub/alignedmem.c
drivers/firmware/efi/libstub/arm32-stub.c
drivers/firmware/efi/libstub/arm64-stub.c
drivers/firmware/efi/libstub/efi-stub-helper.c
drivers/firmware/efi/libstub/efi-stub.c
drivers/firmware/efi/libstub/efistub.h
drivers/firmware/efi/libstub/file.c
drivers/firmware/efi/libstub/skip_spaces.c
drivers/firmware/efi/libstub/x86-stub.c
drivers/firmware/efi/vars.c
drivers/firmware/google/memconsole-coreboot.c
drivers/firmware/google/vpd.c
drivers/firmware/iscsi_ibft.c
drivers/firmware/pcdp.h
drivers/firmware/psci/psci_checker.c
drivers/firmware/qemu_fw_cfg.c
drivers/firmware/raspberrypi.c
drivers/fpga/Kconfig
drivers/fpga/dfl-afu-main.c
drivers/fpga/dfl-pci.c
drivers/gpio/gpio-arizona.c
drivers/gpio/gpio-pca953x.c
drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
drivers/gpu/drm/amd/amdkfd/kfd_priv.h
drivers/gpu/drm/amd/amdkfd/kfd_process.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_stream.c
drivers/gpu/drm/amd/display/dc/dsc/Makefile
drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
drivers/gpu/drm/amd/display/dc/dsc/rc_calc.c
drivers/gpu/drm/amd/display/dc/dsc/rc_calc.h
drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c
drivers/gpu/drm/amd/display/modules/color/color_gamma.c
drivers/gpu/drm/amd/powerplay/renoir_ppt.c
drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c
drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c
drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c
drivers/gpu/drm/aspeed/aspeed_gfx_drv.c
drivers/gpu/drm/bochs/bochs_kms.c
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
drivers/gpu/drm/bridge/nwl-dsi.c
drivers/gpu/drm/drm_encoder_slave.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_mipi_dbi.c
drivers/gpu/drm/drm_of.c
drivers/gpu/drm/drm_panel_orientation_quirks.c
drivers/gpu/drm/exynos/exynos_drm_dma.c
drivers/gpu/drm/exynos/exynos_drm_g2d.c
drivers/gpu/drm/exynos/exynos_drm_mic.c
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
drivers/gpu/drm/i915/display/intel_ddi.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/display/intel_display.h
drivers/gpu/drm/i915/display/intel_dp_mst.c
drivers/gpu/drm/i915/display/intel_fbc.c
drivers/gpu/drm/i915/display/intel_hdmi.c
drivers/gpu/drm/i915/gt/intel_context.c
drivers/gpu/drm/i915/gt/intel_engine_cs.c
drivers/gpu/drm/i915/gt/intel_lrc.c
drivers/gpu/drm/i915/gt/intel_ring.c
drivers/gpu/drm/i915/gt/intel_workarounds.c
drivers/gpu/drm/i915/gt/selftest_hangcheck.c
drivers/gpu/drm/i915/gt/selftest_lrc.c
drivers/gpu/drm/i915/gt/selftest_mocs.c
drivers/gpu/drm/i915/gt/selftest_ring.c [new file with mode: 0644]
drivers/gpu/drm/i915/gt/selftest_rps.c
drivers/gpu/drm/i915/gt/selftest_timeline.c
drivers/gpu/drm/i915/gt/selftest_workarounds.c
drivers/gpu/drm/i915/gt/shaders/README [new file with mode: 0644]
drivers/gpu/drm/i915/gt/shaders/clear_kernel/hsw.asm [new file with mode: 0644]
drivers/gpu/drm/i915/gt/shaders/clear_kernel/ivb.asm [new file with mode: 0644]
drivers/gpu/drm/i915/gvt/debugfs.c
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/mmio_context.h
drivers/gpu/drm/i915/gvt/reg.h
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_perf.c
drivers/gpu/drm/i915/i915_pmu.c
drivers/gpu/drm/i915/i915_priolist_types.h
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_vma.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
drivers/gpu/drm/lima/lima_pp.c
drivers/gpu/drm/mcde/mcde_display.c
drivers/gpu/drm/mcde/mcde_drv.c
drivers/gpu/drm/mediatek/Kconfig
drivers/gpu/drm/mediatek/mtk_drm_crtc.c
drivers/gpu/drm/mediatek/mtk_drm_drv.c
drivers/gpu/drm/mediatek/mtk_drm_plane.c
drivers/gpu/drm/mediatek/mtk_dsi.c
drivers/gpu/drm/mediatek/mtk_hdmi.c
drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c
drivers/gpu/drm/meson/meson_registers.h
drivers/gpu/drm/meson/meson_viu.c
drivers/gpu/drm/msm/adreno/a2xx_gpu.c
drivers/gpu/drm/msm/adreno/a6xx_gmu.c
drivers/gpu/drm/msm/adreno/a6xx_gpu.c
drivers/gpu/drm/msm/adreno/adreno_gpu.c
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
drivers/gpu/drm/msm/msm_submitqueue.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_dmem.c
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nouveau_svm.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c
drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
drivers/gpu/drm/panel/panel-simple.c
drivers/gpu/drm/radeon/ci_dpm.c
drivers/gpu/drm/radeon/ni_dpm.c
drivers/gpu/drm/rcar-du/Kconfig
drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
drivers/gpu/drm/sun4i/sun8i_mixer.c
drivers/gpu/drm/tegra/dc.c
drivers/gpu/drm/tegra/hub.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_bo_vm.c
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
drivers/gpu/host1x/bus.c
drivers/gpu/host1x/dev.c
drivers/hid/hid-alps.c
drivers/hid/hid-apple.c
drivers/hid/hid-ids.h
drivers/hid/hid-logitech-dj.c
drivers/hid/hid-logitech-hidpp.c
drivers/hid/hid-magicmouse.c
drivers/hid/hid-quirks.c
drivers/hid/hid-steam.c
drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
drivers/hv/vmbus_drv.c
drivers/hwmon/acpi_power_meter.c
drivers/hwmon/amd_energy.c
drivers/hwmon/aspeed-pwm-tacho.c
drivers/hwmon/bt1-pvt.c
drivers/hwmon/drivetemp.c
drivers/hwmon/emc2103.c
drivers/hwmon/max6697.c
drivers/hwmon/nct6775.c
drivers/hwmon/pmbus/Kconfig
drivers/hwmon/pmbus/adm1275.c
drivers/hwmon/pmbus/pmbus_core.c
drivers/hwmon/scmi-hwmon.c
drivers/hwtracing/coresight/coresight-cti.c
drivers/hwtracing/coresight/coresight-etm4x.c
drivers/hwtracing/intel_th/core.c
drivers/hwtracing/intel_th/pci.c
drivers/hwtracing/intel_th/sth.c
drivers/hwtracing/stm/policy.c
drivers/hwtracing/stm/stm.h
drivers/i2c/Kconfig
drivers/i2c/algos/i2c-algo-pca.c
drivers/i2c/busses/i2c-cadence.c
drivers/i2c/busses/i2c-designware-common.c
drivers/i2c/busses/i2c-designware-core.h
drivers/i2c/busses/i2c-designware-pcidrv.c
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-eg20t.c
drivers/i2c/busses/i2c-fsi.c
drivers/i2c/busses/i2c-mlxcpld.c
drivers/i2c/busses/i2c-qcom-geni.c
drivers/i2c/busses/i2c-rcar.c
drivers/i2c/i2c-core-base.c
drivers/i2c/i2c-core-slave.c
drivers/i2c/i2c-core-smbus.c
drivers/iio/accel/mma8452.c
drivers/iio/adc/ad7780.c
drivers/iio/adc/adi-axi-adc.c
drivers/iio/health/afe4403.c
drivers/iio/health/afe4404.c
drivers/iio/humidity/hdc100x.c
drivers/iio/humidity/hts221.h
drivers/iio/humidity/hts221_buffer.c
drivers/iio/industrialio-core.c
drivers/iio/magnetometer/ak8974.c
drivers/iio/pressure/ms5611_core.c
drivers/iio/pressure/zpa2326.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/counters.c
drivers/infiniband/core/cq.c
drivers/infiniband/core/mad.c
drivers/infiniband/core/rdma_core.c
drivers/infiniband/core/sa_query.c
drivers/infiniband/core/ucma.c
drivers/infiniband/hw/efa/efa_verbs.c
drivers/infiniband/hw/hfi1/debugfs.c
drivers/infiniband/hw/hfi1/init.c
drivers/infiniband/hw/hfi1/iowait.h
drivers/infiniband/hw/hfi1/ipoib.h
drivers/infiniband/hw/hfi1/ipoib_tx.c
drivers/infiniband/hw/hfi1/netdev_rx.c
drivers/infiniband/hw/hfi1/qp.c
drivers/infiniband/hw/hfi1/tid_rdma.c
drivers/infiniband/hw/hfi1/verbs_txreq.h
drivers/infiniband/hw/hns/hns_roce_device.h
drivers/infiniband/hw/hns/hns_roce_hw_v1.c
drivers/infiniband/hw/hns/hns_roce_hw_v2.c
drivers/infiniband/hw/hns/hns_roce_mr.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/odp.c
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/hw/mlx5/qpc.c
drivers/infiniband/hw/mlx5/srq_cmd.c
drivers/infiniband/hw/qedr/qedr_iw_cm.c
drivers/infiniband/sw/rdmavt/qp.c
drivers/infiniband/sw/rdmavt/rc.c
drivers/infiniband/sw/siw/siw_main.c
drivers/infiniband/sw/siw/siw_qp_rx.c
drivers/input/mouse/elan_i2c_core.c
drivers/input/mouse/synaptics.c
drivers/input/serio/hp_sdc.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/touchscreen/elants_i2c.c
drivers/interconnect/core.c
drivers/interconnect/qcom/msm8916.c
drivers/iommu/Kconfig
drivers/iommu/amd/amd_iommu.h
drivers/iommu/amd/iommu.c
drivers/iommu/arm-smmu-qcom.c
drivers/iommu/hyperv-iommu.c
drivers/iommu/intel/dmar.c
drivers/iommu/intel/iommu.c
drivers/iommu/intel/irq_remapping.c
drivers/iommu/iommu.c
drivers/iommu/qcom_iommu.c
drivers/iommu/sun50i-iommu.c
drivers/irqchip/Kconfig
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic.c
drivers/irqchip/irq-riscv-intc.c
drivers/md/bcache/btree.c
drivers/md/bcache/super.c
drivers/md/dm-integrity.c
drivers/md/dm-ioctl.c
drivers/md/dm-rq.c
drivers/md/dm-writecache.c
drivers/md/dm-zoned-metadata.c
drivers/md/dm-zoned-reclaim.c
drivers/md/dm-zoned-target.c
drivers/md/dm.c
drivers/media/platform/omap3isp/isp.c
drivers/media/platform/omap3isp/ispvideo.c
drivers/media/usb/pwc/pwc.h
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptscsih.c
drivers/mfd/ioc3.c
drivers/mfd/mt6360-core.c
drivers/misc/atmel-ssc.c
drivers/misc/habanalabs/command_submission.c
drivers/misc/habanalabs/debugfs.c
drivers/misc/habanalabs/device.c
drivers/misc/habanalabs/firmware_if.c
drivers/misc/habanalabs/gaudi/gaudi.c
drivers/misc/habanalabs/gaudi/gaudiP.h
drivers/misc/habanalabs/goya/goya.c
drivers/misc/habanalabs/habanalabs.h
drivers/misc/habanalabs/habanalabs_drv.c
drivers/misc/habanalabs/hwmon.c
drivers/misc/habanalabs/include/gaudi/gaudi_packets.h
drivers/misc/habanalabs/sysfs.c
drivers/misc/kgdbts.c
drivers/misc/mei/bus.c
drivers/misc/mei/hw-me-regs.h
drivers/misc/mei/hw-me.c
drivers/misc/mei/hw-me.h
drivers/misc/mei/pci-me.c
drivers/mmc/host/meson-gx-mmc.c
drivers/mmc/host/owl-mmc.c
drivers/mmc/host/sdhci-msm.c
drivers/mmc/host/sdhci-of-aspeed.c
drivers/mtd/mtdcore.c
drivers/mtd/nand/raw/nandsim.c
drivers/mtd/nand/raw/xway_nand.c
drivers/net/bareudp.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_netlink.c
drivers/net/can/peak_canfd/peak_pciefd_main.c
drivers/net/dsa/bcm_sf2.c
drivers/net/dsa/microchip/ksz8795.c
drivers/net/dsa/microchip/ksz9477.c
drivers/net/dsa/microchip/ksz9477_i2c.c
drivers/net/dsa/microchip/ksz_common.c
drivers/net/dsa/microchip/ksz_common.h
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/chip.h
drivers/net/dsa/sja1105/sja1105_ptp.c
drivers/net/dsa/sja1105/sja1105_vl.c
drivers/net/ethernet/aquantia/atlantic/aq_hw.h
drivers/net/ethernet/aquantia/atlantic/aq_nic.c
drivers/net/ethernet/aquantia/atlantic/aq_nic.h
drivers/net/ethernet/aquantia/atlantic/aq_phy.c
drivers/net/ethernet/aquantia/atlantic/aq_phy.h
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h
drivers/net/ethernet/atheros/ag71xx.c
drivers/net/ethernet/atheros/alx/main.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/broadcom/genet/bcmgenet.h
drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32_parse.h
drivers/net/ethernet/chelsio/cxgb4/l2t.c
drivers/net/ethernet/chelsio/cxgb4/sched.c
drivers/net/ethernet/chelsio/cxgb4/sge.c
drivers/net/ethernet/chelsio/cxgb4/smt.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
drivers/net/ethernet/chelsio/cxgb4vf/sge.c
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
drivers/net/ethernet/freescale/enetc/enetc.c
drivers/net/ethernet/freescale/enetc/enetc_hw.h
drivers/net/ethernet/freescale/enetc/enetc_pf.c
drivers/net/ethernet/freescale/fec.h
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/fec_ptp.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/hisilicon/hns/hns_enet.c
drivers/net/ethernet/hisilicon/hns3/hnae3.h
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c
drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
drivers/net/ethernet/marvell/sky2.c
drivers/net/ethernet/mediatek/mtk_star_emac.c
drivers/net/ethernet/mellanox/mlx5/core/en/dcbnl.h
drivers/net/ethernet/mellanox/mlx5/core/en/port.c
drivers/net/ethernet/mellanox/mlx5/core/en/port.h
drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h
drivers/net/ethernet/mellanox/mlx5/core/en/rep/neigh.c
drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
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_tc.c
drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_lgcy.c
drivers/net/ethernet/mellanox/mlx5/core/port.c
drivers/net/ethernet/mellanox/mlxsw/core.c
drivers/net/ethernet/mellanox/mlxsw/core_env.c
drivers/net/ethernet/mellanox/mlxsw/pci.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
drivers/net/ethernet/microchip/lan743x_main.c
drivers/net/ethernet/neterion/vxge/vxge-config.h
drivers/net/ethernet/neterion/vxge/vxge-main.c
drivers/net/ethernet/netronome/nfp/flower/main.c
drivers/net/ethernet/netronome/nfp/flower/main.h
drivers/net/ethernet/netronome/nfp/flower/offload.c
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
drivers/net/ethernet/pensando/ionic/ionic_lif.c
drivers/net/ethernet/pensando/ionic/ionic_lif.h
drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c
drivers/net/ethernet/pensando/ionic/ionic_txrx.c
drivers/net/ethernet/qlogic/qed/qed.h
drivers/net/ethernet/qlogic/qed/qed_cxt.c
drivers/net/ethernet/qlogic/qed/qed_debug.c
drivers/net/ethernet/qlogic/qed/qed_dev.c
drivers/net/ethernet/qlogic/qed/qed_int.c
drivers/net/ethernet/qlogic/qed/qed_int.h
drivers/net/ethernet/qlogic/qed/qed_iwarp.c
drivers/net/ethernet/qlogic/qed/qed_mcp.c
drivers/net/ethernet/qlogic/qed/qed_mcp.h
drivers/net/ethernet/qlogic/qed/qed_roce.c
drivers/net/ethernet/qlogic/qed/qed_vf.c
drivers/net/ethernet/qlogic/qede/qede_main.c
drivers/net/ethernet/qlogic/qede/qede_ptp.c
drivers/net/ethernet/qlogic/qede/qede_ptp.h
drivers/net/ethernet/qlogic/qede/qede_rdma.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
drivers/net/ethernet/realtek/r8169_main.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/rocker/rocker_main.c
drivers/net/ethernet/smsc/smc91x.c
drivers/net/ethernet/socionext/netsec.c
drivers/net/ethernet/socionext/sni_ave.c
drivers/net/ethernet/ti/am65-cpsw-nuss.c
drivers/net/ethernet/xilinx/xilinx_axienet.h
drivers/net/geneve.c
drivers/net/hippi/rrunner.c
drivers/net/ieee802154/adf7242.c
drivers/net/ipa/gsi.c
drivers/net/ipa/ipa_cmd.c
drivers/net/ipa/ipa_cmd.h
drivers/net/ipa/ipa_data-sdm845.c
drivers/net/ipa/ipa_endpoint.c
drivers/net/ipa/ipa_gsi.c
drivers/net/ipa/ipa_gsi.h
drivers/net/ipa/ipa_qmi_msg.c
drivers/net/macsec.c
drivers/net/macvlan.c
drivers/net/netdevsim/netdev.c
drivers/net/phy/Kconfig
drivers/net/phy/dp83640.c
drivers/net/phy/mscc/mscc_macsec.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/phy/phylink.c
drivers/net/phy/smsc.c
drivers/net/tun.c
drivers/net/usb/ax88172a.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/hso.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/smsc95xx.c
drivers/net/vxlan.c
drivers/net/wan/hdlc_x25.c
drivers/net/wan/lapbether.c
drivers/net/wan/x25_asy.c
drivers/net/wireguard/device.c
drivers/net/wireguard/device.h
drivers/net/wireguard/netlink.c
drivers/net/wireguard/noise.c
drivers/net/wireguard/queueing.h
drivers/net/wireguard/receive.c
drivers/net/wireguard/socket.c
drivers/net/wireless/ath/ath10k/ahb.c
drivers/net/wireless/ath/ath10k/pci.c
drivers/net/wireless/ath/ath9k/hif_usb.c
drivers/net/wireless/ath/wil6210/txrx.c
drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
drivers/net/wireless/mediatek/mt76/mt76.h
drivers/net/wireless/mediatek/mt76/mt7603/main.c
drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c
drivers/net/wireless/mediatek/mt76/mt7615/dma.c
drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h
drivers/net/wireless/mediatek/mt76/mt7615/mac.c
drivers/net/wireless/mediatek/mt76/mt7615/mac.h
drivers/net/wireless/mediatek/mt76/mt7615/main.c
drivers/net/wireless/mediatek/mt76/mt7615/mmio.c
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
drivers/net/wireless/mediatek/mt76/mt7615/usb.c
drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
drivers/net/wireless/mediatek/mt76/mt7915/main.c
drivers/net/wireless/mediatek/mt76/tx.c
drivers/net/wireless/mediatek/mt76/usb.c
drivers/net/xen-netfront.c
drivers/nfc/s3fwrn5/core.c
drivers/nvdimm/region_devs.c
drivers/nvdimm/security.c
drivers/nvme/host/core.c
drivers/nvme/host/multipath.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/nvme/host/rdma.c
drivers/nvme/host/tcp.c
drivers/nvme/target/loop.c
drivers/of/of_mdio.c
drivers/opp/of.c
drivers/oprofile/cpu_buffer.h
drivers/pci/controller/vmd.c
drivers/pci/pci.c
drivers/pci/quirks.c
drivers/perf/arm-cci.c
drivers/perf/arm-ccn.c
drivers/perf/arm_dsu_pmu.c
drivers/perf/arm_smmuv3_pmu.c
drivers/perf/arm_spe_pmu.c
drivers/perf/fsl_imx8_ddr_perf.c
drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
drivers/perf/qcom_l2_pmu.c
drivers/perf/qcom_l3_pmu.c
drivers/perf/thunderx2_pmu.c
drivers/perf/xgene_pmu.c
drivers/phy/allwinner/phy-sun4i-usb.c
drivers/phy/intel/phy-intel-combo.c
drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c
drivers/phy/samsung/phy-samsung-usb2.h
drivers/phy/ti/phy-am654-serdes.c
drivers/phy/ti/phy-j721e-wiz.c
drivers/pinctrl/freescale/pinctrl-imx.c
drivers/pinctrl/intel/pinctrl-baytrail.c
drivers/pinctrl/pinctrl-amd.h
drivers/pinctrl/pinctrl-mcp23s08_spi.c
drivers/pinctrl/pinctrl-single.c
drivers/pinctrl/qcom/pinctrl-ipq6018.c
drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
drivers/pinctrl/tegra/pinctrl-tegra.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/intel_speed_select_if/isst_if_common.h
drivers/platform/x86/intel_speed_select_if/isst_if_mbox_pci.c
drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c
drivers/platform/x86/thinkpad_acpi.c
drivers/rapidio/rio-scan.c
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/da903x-regulator.c [new file with mode: 0644]
drivers/regulator/da903x.c [deleted file]
drivers/regulator/da9063-regulator.c
drivers/regulator/helpers.c
drivers/regulator/pfuze100-regulator.c
drivers/regulator/qcom_smd-regulator.c
drivers/s390/cio/qdio.h
drivers/s390/cio/qdio_debug.c
drivers/s390/cio/qdio_main.c
drivers/s390/cio/vfio_ccw_chp.c
drivers/s390/crypto/zcrypt_ep11misc.c
drivers/s390/net/qeth_core_main.c
drivers/s390/scsi/zfcp_erp.c
drivers/s390/virtio/virtio_ccw.c
drivers/scsi/aic94xx/aic94xx_init.c
drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
drivers/scsi/ipr.c
drivers/scsi/isci/init.c
drivers/scsi/libfc/fc_rport.c
drivers/scsi/libiscsi.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/scsi/mpt3sas/mpt3sas_ctl.c
drivers/scsi/mvsas/mv_init.c
drivers/scsi/pm8001/pm8001_init.c
drivers/scsi/qla2xxx/qla_gs.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_nvme.c
drivers/scsi/scsi_devinfo.c
drivers/scsi/scsi_dh.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_transport_iscsi.c
drivers/scsi/scsi_transport_spi.c
drivers/scsi/ufs/ufs_bsg.c
drivers/soc/amlogic/meson-gx-socinfo.c
drivers/soc/imx/soc-imx.c
drivers/soc/imx/soc-imx8m.c
drivers/soc/ti/knav_qmss.h
drivers/soc/ti/omap_prm.c
drivers/soundwire/intel.c
drivers/spi/spi-fsl-dspi.c
drivers/spi/spi-mt65xx.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-rspi.c
drivers/spi/spi-sprd-adi.c
drivers/spi/spi-stm32-qspi.c
drivers/spi/spi-sun6i.c
drivers/spi/spidev.c
drivers/staging/comedi/drivers/addi_apci_1032.c
drivers/staging/comedi/drivers/addi_apci_1500.c
drivers/staging/comedi/drivers/addi_apci_1564.c
drivers/staging/comedi/drivers/ni_6527.c
drivers/staging/media/atomisp/Kconfig
drivers/staging/media/atomisp/Makefile
drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
drivers/staging/media/atomisp/include/linux/atomisp_platform.h
drivers/staging/media/atomisp/pci/atomisp-regs.h
drivers/staging/media/atomisp/pci/atomisp_acc.c
drivers/staging/media/atomisp/pci/atomisp_cmd.c
drivers/staging/media/atomisp/pci/atomisp_cmd.h
drivers/staging/media/atomisp/pci/atomisp_compat.h
drivers/staging/media/atomisp/pci/atomisp_compat_css20.c
drivers/staging/media/atomisp/pci/atomisp_compat_css20.h
drivers/staging/media/atomisp/pci/atomisp_drvfs.c
drivers/staging/media/atomisp/pci/atomisp_drvfs.h
drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c
drivers/staging/media/atomisp/pci/atomisp_internal.h
drivers/staging/media/atomisp/pci/atomisp_ioctl.c
drivers/staging/media/atomisp/pci/atomisp_v4l2.c
drivers/staging/media/atomisp/pci/base/refcount/src/refcount.c
drivers/staging/media/atomisp/pci/hive_types.h
drivers/staging/media/atomisp/pci/hmm/hmm.c
drivers/staging/media/atomisp/pci/isp2400_system_global.h
drivers/staging/media/atomisp/pci/isp2400_system_local.h [deleted file]
drivers/staging/media/atomisp/pci/isp2401_system_global.h
drivers/staging/media/atomisp/pci/isp2401_system_local.h [deleted file]
drivers/staging/media/atomisp/pci/sh_css.c
drivers/staging/media/atomisp/pci/system_global.h
drivers/staging/media/atomisp/pci/system_local.c [new file with mode: 0644]
drivers/staging/media/atomisp/pci/system_local.h
drivers/staging/rtl8723bs/core/rtw_wlan_util.c
drivers/staging/wfx/hif_tx.c
drivers/staging/wfx/hif_tx.h
drivers/staging/wfx/queue.c
drivers/staging/wfx/scan.c
drivers/staging/wlan-ng/prism2usb.c
drivers/thermal/cpufreq_cooling.c
drivers/thermal/imx_thermal.c
drivers/thermal/intel/int340x_thermal/int3400_thermal.c
drivers/thermal/intel/int340x_thermal/int3403_thermal.c
drivers/thermal/mtk_thermal.c
drivers/thermal/qcom/tsens.c
drivers/thermal/rcar_gen3_thermal.c
drivers/thermal/sprd_thermal.c
drivers/thunderbolt/tunnel.c
drivers/tty/serial/8250/8250_core.c
drivers/tty/serial/8250/8250_exar.c
drivers/tty/serial/8250/8250_mtk.c
drivers/tty/serial/cpm_uart/cpm_uart_core.c
drivers/tty/serial/kgdb_nmi.c
drivers/tty/serial/kgdboc.c
drivers/tty/serial/mxs-auart.c
drivers/tty/serial/serial-tegra.c
drivers/tty/serial/serial_core.c
drivers/tty/serial/sh-sci.c
drivers/tty/serial/xilinx_uartps.c
drivers/tty/vt/vt.c
drivers/uio/uio_pdrv_genirq.c
drivers/usb/c67x00/c67x00-sched.c
drivers/usb/cdns3/ep0.c
drivers/usb/cdns3/trace.h
drivers/usb/chipidea/core.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/quirks.c
drivers/usb/dwc2/gadget.c
drivers/usb/dwc2/platform.c
drivers/usb/dwc3/dwc3-exynos.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/early/ehci-dbgp.c
drivers/usb/gadget/function/f_uac1_legacy.c
drivers/usb/gadget/udc/atmel_usba_udc.c
drivers/usb/gadget/udc/gr_udc.c
drivers/usb/gadget/udc/mv_udc_core.c
drivers/usb/gadget/usbstring.c
drivers/usb/host/ehci-exynos.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ohci-sm501.c
drivers/usb/host/xhci-mtk-sch.c
drivers/usb/host/xhci-mtk.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-tegra.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/usbtest.c
drivers/usb/phy/phy-tegra-usb.c
drivers/usb/renesas_usbhs/fifo.c
drivers/usb/renesas_usbhs/fifo.h
drivers/usb/serial/ch341.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/cypress_m8.h
drivers/usb/serial/iuu_phoenix.c
drivers/usb/serial/option.c
drivers/usb/typec/mux/intel_pmc_mux.c
drivers/usb/typec/tcpm/tcpci_rt1711h.c
drivers/vdpa/vdpa.c
drivers/vfio/pci/vfio_pci.c
drivers/vfio/pci/vfio_pci_config.c
drivers/vhost/scsi.c
drivers/vhost/test.c
drivers/vhost/test.h
drivers/vhost/vdpa.c
drivers/video/backlight/tosa_lcd.c
drivers/video/fbdev/core/bitblit.c
drivers/video/fbdev/core/fbcon.c
drivers/video/fbdev/core/fbcon_ccw.c
drivers/video/fbdev/core/fbcon_cw.c
drivers/video/fbdev/core/fbcon_ud.c
drivers/video/fbdev/hpfb.c
drivers/video/fbdev/uvesafb.c
drivers/virt/vboxguest/vboxguest_core.c
drivers/virt/vboxguest/vboxguest_core.h
drivers/virt/vboxguest/vboxguest_linux.c
drivers/virt/vboxguest/vmmdev.h
drivers/virtio/Kconfig
drivers/virtio/virtio_balloon.c
drivers/virtio/virtio_mem.c
drivers/virtio/virtio_mmio.c
drivers/w1/w1_netlink.h
drivers/xen/xenbus/xenbus_client.c
fs/afs/cell.c
fs/afs/dir.c
fs/afs/dir_silly.c
fs/afs/file.c
fs/afs/flock.c
fs/afs/fs_operation.c
fs/afs/fs_probe.c
fs/afs/inode.c
fs/afs/internal.h
fs/afs/main.c
fs/afs/misc.c
fs/afs/server.c
fs/afs/write.c
fs/afs/yfsclient.c
fs/aio.c
fs/autofs/waitq.c
fs/block_dev.c
fs/btrfs/backref.c
fs/btrfs/block-group.c
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/discard.c
fs/btrfs/disk-io.c
fs/btrfs/extent_io.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/ref-verify.c
fs/btrfs/space-info.c
fs/btrfs/super.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h
fs/cachefiles/rdwr.c
fs/cifs/cifs_debug.c
fs/cifs/cifsfs.h
fs/cifs/connect.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/ioctl.c
fs/cifs/misc.c
fs/cifs/smb2misc.c
fs/cifs/smb2ops.c
fs/cifs/transport.c
fs/efivarfs/file.c
fs/efivarfs/super.c
fs/erofs/zdata.h
fs/exfat/dir.c
fs/exfat/exfat_fs.h
fs/exfat/file.c
fs/exfat/namei.c
fs/exfat/nls.c
fs/exfat/super.c
fs/ext4/Makefile
fs/ext4/dir.c
fs/ext4/ext4.h
fs/ext4/extents.c
fs/ext4/ialloc.c
fs/ext4/inode.c
fs/ext4/ioctl.c
fs/ext4/mballoc.c
fs/ext4/super.c
fs/ext4/verity.c
fs/ext4/xattr.c
fs/ext4/xattr.h
fs/ext4/xattr_hurd.c [new file with mode: 0644]
fs/fuse/file.c
fs/fuse/inode.c
fs/gfs2/aops.c
fs/gfs2/file.c
fs/gfs2/glock.c
fs/gfs2/glops.c
fs/gfs2/incore.h
fs/gfs2/inode.c
fs/gfs2/log.c
fs/gfs2/log.h
fs/gfs2/main.c
fs/gfs2/ops_fstype.c
fs/gfs2/recovery.c
fs/gfs2/super.c
fs/io-wq.c
fs/io-wq.h
fs/io_uring.c
fs/jbd2/journal.c
fs/jffs2/nodelist.h
fs/jffs2/summary.h
fs/namespace.c
fs/nfs/flexfilelayout/flexfilelayout.c
fs/nfs/nfs4namespace.c
fs/nfs/nfs4proc.c
fs/nfsd/nfs4state.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsd.h
fs/nfsd/vfs.c
fs/ocfs2/dlmglue.c
fs/ocfs2/ocfs2.h
fs/ocfs2/ocfs2_fs.h
fs/ocfs2/suballoc.c
fs/overlayfs/copy_up.c
fs/overlayfs/export.c
fs/overlayfs/file.c
fs/overlayfs/namei.c
fs/overlayfs/overlayfs.h
fs/overlayfs/super.c
fs/proc/bootconfig.c
fs/proc/kcore.c
fs/proc/proc_sysctl.c
fs/read_write.c
fs/squashfs/block.c
fs/squashfs/squashfs_fs.h
fs/xfs/xfs_log_cil.c
fs/xfs/xfs_log_priv.h
fs/zonefs/super.c
include/asm-generic/cacheflush.h
include/asm-generic/hugetlb.h
include/asm-generic/io.h
include/asm-generic/mmiowb.h
include/asm-generic/vmlinux.lds.h
include/crypto/if_alg.h
include/drm/drm_displayid.h
include/drm/drm_mode_config.h
include/keys/encrypted-type.h
include/keys/rxrpc-type.h
include/linux/atomic-fallback.h
include/linux/bits.h
include/linux/blkdev.h
include/linux/bpf-netns.h
include/linux/bpf.h
include/linux/btf.h
include/linux/can/skb.h
include/linux/cb710.h
include/linux/ceph/libceph.h
include/linux/cgroup-defs.h
include/linux/cgroup.h
include/linux/compiler-clang.h
include/linux/compiler-gcc.h
include/linux/compiler.h
include/linux/compiler_attributes.h
include/linux/compiler_types.h
include/linux/device-mapper.h
include/linux/device.h
include/linux/dma-buf.h
include/linux/dma-direct.h
include/linux/dma-mapping.h
include/linux/dmaengine.h
include/linux/efi.h
include/linux/filter.h
include/linux/fs.h
include/linux/fs_context.h
include/linux/fscache-cache.h
include/linux/host1x.h
include/linux/i2c.h
include/linux/ieee80211.h
include/linux/if_vlan.h
include/linux/input/elan-i2c-ids.h
include/linux/intel-iommu.h
include/linux/io-mapping.h
include/linux/irq_work.h
include/linux/jbd2.h
include/linux/kallsyms.h
include/linux/kexec.h
include/linux/kgdb.h
include/linux/kprobes.h
include/linux/kvm_host.h
include/linux/libata.h
include/linux/lsm_hook_defs.h
include/linux/mlx5/driver.h
include/linux/mlx5/mlx5_ifc.h
include/linux/mmzone.h
include/linux/mod_devicetable.h
include/linux/netdevice.h
include/linux/netfilter_ipv4/ip_tables.h
include/linux/netfilter_ipv6/ip6_tables.h
include/linux/overflow.h
include/linux/pci.h
include/linux/pgtable.h
include/linux/phy.h
include/linux/psp-sev.h
include/linux/qed/qed_chain.h
include/linux/random.h
include/linux/rhashtable.h
include/linux/scatterlist.h
include/linux/sched.h
include/linux/sched/jobctl.h
include/linux/sctp.h
include/linux/serial_core.h
include/linux/skmsg.h
include/linux/smp.h
include/linux/smp_types.h [new file with mode: 0644]
include/linux/swap.h
include/linux/syscalls.h
include/linux/task_work.h
include/linux/tcp.h
include/linux/tifm.h
include/linux/timekeeping.h
include/linux/tpm_eventlog.h
include/linux/uaccess.h
include/linux/vmalloc.h
include/linux/xattr.h
include/net/dst.h
include/net/flow_dissector.h
include/net/flow_offload.h
include/net/genetlink.h
include/net/gue.h
include/net/inet_ecn.h
include/net/ip_tunnels.h
include/net/netfilter/nf_flow_table.h
include/net/netns/bpf.h
include/net/pkt_sched.h
include/net/sctp/constants.h
include/net/sock.h
include/net/tc_act/tc_ct.h
include/net/xfrm.h
include/net/xsk_buff_pool.h
include/rdma/rdmavt_qp.h
include/sound/compress_driver.h
include/sound/dmaengine_pcm.h
include/sound/rt5670.h
include/sound/soc-dai.h
include/sound/soc.h
include/trace/events/block.h
include/trace/events/rxrpc.h
include/uapi/linux/bpf.h
include/uapi/linux/fb.h
include/uapi/linux/fs.h
include/uapi/linux/idxd.h
include/uapi/linux/input-event-codes.h
include/uapi/linux/io_uring.h
include/uapi/linux/mrp_bridge.h
include/uapi/linux/ndctl.h
include/uapi/linux/rds.h
include/uapi/linux/spi/spidev.h
include/uapi/linux/vboxguest.h
include/uapi/linux/vfio.h
include/uapi/linux/xattr.h
init/Kconfig
kernel/audit.c
kernel/audit.h
kernel/auditsc.c
kernel/bpf/btf.c
kernel/bpf/cgroup.c
kernel/bpf/devmap.c
kernel/bpf/net_namespace.c
kernel/bpf/reuseport_array.c
kernel/bpf/ringbuf.c
kernel/bpf/syscall.c
kernel/bpf/verifier.c
kernel/cgroup/cgroup.c
kernel/debug/debug_core.c
kernel/debug/gdbstub.c
kernel/debug/kdb/kdb_io.c
kernel/debug/kdb/kdb_main.c
kernel/debug/kdb/kdb_support.c
kernel/dma/Kconfig
kernel/dma/direct.c
kernel/dma/mapping.c
kernel/dma/pool.c
kernel/dma/remap.c
kernel/events/uprobes.c
kernel/fork.c
kernel/irq/manage.c
kernel/kallsyms.c
kernel/kexec_file.c
kernel/kprobes.c
kernel/kthread.c
kernel/module.c
kernel/nsproxy.c
kernel/padata.c
kernel/printk/printk.c
kernel/rcu/rcuperf.c
kernel/rcu/tree.c
kernel/sched/core.c
kernel/sched/deadline.c
kernel/sched/fair.c
kernel/sched/idle.c
kernel/sched/sched.h
kernel/signal.c
kernel/smp.c
kernel/task_work.c
kernel/time/timer.c
kernel/trace/blktrace.c
kernel/trace/bpf_trace.c
kernel/trace/ftrace.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_boot.c
kernel/trace/trace_entries.h
kernel/trace/trace_events_trigger.c
kernel/trace/trace_export.c
kernel/trace/trace_functions.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_probe.c
kernel/trace/trace_probe.h
kernel/workqueue.c
lib/Kconfig.debug
lib/Kconfig.kasan
lib/Kconfig.kgdb
lib/packing.c
lib/random32.c
lib/seq_buf.c
lib/test_hmm.c
lib/test_lockup.c
lib/test_objagg.c
mm/cma.c
mm/compaction.c
mm/debug.c
mm/debug_vm_pgtable.c
mm/filemap.c
mm/gup.c
mm/hugetlb.c
mm/khugepaged.c
mm/maccess.c
mm/memcontrol.c
mm/memory.c
mm/memory_hotplug.c
mm/migrate.c
mm/mmap.c
mm/mremap.c
mm/nommu.c
mm/page_alloc.c
mm/rodata_test.c
mm/shmem.c
mm/slab.h
mm/slab_common.c
mm/slub.c
mm/swap.c
mm/swap_state.c
mm/vmalloc.c
mm/vmscan.c
mm/workingset.c
net/8021q/vlan_dev.c
net/9p/mod.c
net/9p/trans_fd.c
net/ax25/af_ax25.c
net/bluetooth/hci_event.c
net/bpf/test_run.c
net/bpfilter/bpfilter_kern.c
net/bridge/br_mrp.c
net/bridge/br_multicast.c
net/bridge/br_private.h
net/bridge/br_private_mrp.h
net/bridge/netfilter/nft_meta_bridge.c
net/bridge/netfilter/nft_reject_bridge.c
net/ceph/ceph_common.c
net/ceph/osd_client.c
net/core/dev.c
net/core/dev_addr_lists.c
net/core/drop_monitor.c
net/core/filter.c
net/core/flow_dissector.c
net/core/flow_offload.c
net/core/net-sysfs.c
net/core/rtnetlink.c
net/core/skmsg.c
net/core/sock.c
net/core/sock_map.c
net/core/sock_reuseport.c
net/core/sysctl_net_core.c
net/core/xdp.c
net/dsa/tag_edsa.c
net/ethtool/cabletest.c
net/ethtool/common.c
net/ethtool/ioctl.c
net/ethtool/linkstate.c
net/ethtool/netlink.c
net/hsr/hsr_device.c
net/hsr/hsr_device.h
net/hsr/hsr_forward.c
net/hsr/hsr_framereg.c
net/hsr/hsr_main.c
net/hsr/hsr_netlink.c
net/ipv4/Kconfig
net/ipv4/esp4_offload.c
net/ipv4/fib_semantics.c
net/ipv4/fou.c
net/ipv4/icmp.c
net/ipv4/ip_output.c
net/ipv4/ip_tunnel.c
net/ipv4/ip_tunnel_core.c
net/ipv4/ip_vti.c
net/ipv4/ipip.c
net/ipv4/netfilter/ip_tables.c
net/ipv4/netfilter/ipt_SYNPROXY.c
net/ipv4/netfilter/iptable_filter.c
net/ipv4/netfilter/iptable_mangle.c
net/ipv4/netfilter/iptable_nat.c
net/ipv4/netfilter/iptable_raw.c
net/ipv4/netfilter/iptable_security.c
net/ipv4/netfilter/nf_flow_table_ipv4.c
net/ipv4/netfilter/nft_dup_ipv4.c
net/ipv4/netfilter/nft_fib_ipv4.c
net/ipv4/netfilter/nft_reject_ipv4.c
net/ipv4/ping.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_cong.c
net/ipv4/tcp_cubic.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv4/udp.c
net/ipv6/Kconfig
net/ipv6/esp6_offload.c
net/ipv6/fou6.c
net/ipv6/icmp.c
net/ipv6/ila/ila_main.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_vti.c
net/ipv6/mcast.c
net/ipv6/netfilter/ip6_tables.c
net/ipv6/netfilter/ip6t_SYNPROXY.c
net/ipv6/netfilter/ip6table_filter.c
net/ipv6/netfilter/ip6table_mangle.c
net/ipv6/netfilter/ip6table_nat.c
net/ipv6/netfilter/ip6table_raw.c
net/ipv6/netfilter/ip6table_security.c
net/ipv6/netfilter/nf_flow_table_ipv6.c
net/ipv6/netfilter/nft_dup_ipv6.c
net/ipv6/netfilter/nft_fib_ipv6.c
net/ipv6/netfilter/nft_reject_ipv6.c
net/ipv6/route.c
net/ipv6/sit.c
net/ipv6/udp.c
net/l2tp/l2tp_core.c
net/llc/af_llc.c
net/mac80211/mesh_hwmp.c
net/mac80211/rx.c
net/mac80211/status.c
net/mac80211/tx.c
net/mptcp/options.c
net/mptcp/protocol.h
net/mptcp/subflow.c
net/netfilter/ipset/ip_set_bitmap_ip.c
net/netfilter/ipset/ip_set_bitmap_ipmac.c
net/netfilter/ipset/ip_set_bitmap_port.c
net/netfilter/ipset/ip_set_core.c
net/netfilter/ipset/ip_set_hash_gen.h
net/netfilter/ipvs/ip_vs_sync.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_dup_netdev.c
net/netfilter/nf_flow_table_core.c
net/netfilter/nf_flow_table_inet.c
net/netfilter/nf_flow_table_offload.c
net/netfilter/nf_synproxy_core.c
net/netfilter/nf_tables_api.c
net/netfilter/nf_tables_offload.c
net/netfilter/nfnetlink.c
net/netfilter/nft_compat.c
net/netfilter/nft_connlimit.c
net/netfilter/nft_counter.c
net/netfilter/nft_ct.c
net/netfilter/nft_dup_netdev.c
net/netfilter/nft_fib_inet.c
net/netfilter/nft_fib_netdev.c
net/netfilter/nft_flow_offload.c
net/netfilter/nft_hash.c
net/netfilter/nft_limit.c
net/netfilter/nft_log.c
net/netfilter/nft_masq.c
net/netfilter/nft_nat.c
net/netfilter/nft_numgen.c
net/netfilter/nft_objref.c
net/netfilter/nft_osf.c
net/netfilter/nft_queue.c
net/netfilter/nft_quota.c
net/netfilter/nft_redir.c
net/netfilter/nft_reject.c
net/netfilter/nft_reject_inet.c
net/netfilter/nft_set_pipapo.c
net/netfilter/nft_set_rbtree.c
net/netfilter/nft_synproxy.c
net/netfilter/nft_tunnel.c
net/netfilter/xt_nat.c
net/netlink/genetlink.c
net/nfc/nci/core.c
net/openvswitch/actions.c
net/qrtr/qrtr.c
net/rds/connection.c
net/rds/ib.h
net/rds/rds.h
net/rds/send.c
net/rds/transport.c
net/rxrpc/call_accept.c
net/rxrpc/call_event.c
net/rxrpc/input.c
net/rxrpc/recvmsg.c
net/rxrpc/sendmsg.c
net/sched/act_connmark.c
net/sched/act_csum.c
net/sched/act_ct.c
net/sched/act_ctinfo.c
net/sched/act_gate.c
net/sched/act_mpls.c
net/sched/act_skbedit.c
net/sched/cls_api.c
net/sched/cls_flow.c
net/sched/cls_flower.c
net/sched/em_ipset.c
net/sched/em_ipt.c
net/sched/em_meta.c
net/sched/sch_atm.c
net/sched/sch_cake.c
net/sched/sch_dsmark.c
net/sched/sch_fq.c
net/sched/sch_fq_codel.c
net/sched/sch_hhf.c
net/sched/sch_teql.c
net/sctp/associola.c
net/sctp/bind_addr.c
net/sctp/protocol.c
net/sctp/stream.c
net/smc/af_smc.c
net/smc/smc_cdc.c
net/smc/smc_clc.c
net/smc/smc_clc.h
net/smc/smc_core.c
net/smc/smc_core.h
net/smc/smc_ib.c
net/smc/smc_ib.h
net/smc/smc_ism.c
net/smc/smc_ism.h
net/smc/smc_llc.c
net/smc/smc_llc.h
net/smc/smc_pnet.c
net/smc/smc_wr.c
net/sunrpc/rpc_pipe.c
net/sunrpc/svcsock.c
net/sunrpc/xdr.c
net/sunrpc/xprtrdma/frwr_ops.c
net/sunrpc/xprtrdma/rpc_rdma.c
net/sunrpc/xprtrdma/transport.c
net/sunrpc/xprtrdma/verbs.c
net/sunrpc/xprtrdma/xprt_rdma.h
net/tipc/link.c
net/vmw_vsock/virtio_transport.c
net/wireless/nl80211.c
net/xdp/xsk_buff_pool.c
net/xfrm/Kconfig
net/xfrm/xfrm_device.c
net/xfrm/xfrm_interface.c
net/xfrm/xfrm_output.c
samples/Kconfig
samples/bpf/xdp_monitor_user.c
samples/bpf/xdp_redirect_cpu_user.c
samples/bpf/xdp_rxq_info_user.c
samples/ftrace/sample-trace-array.c
samples/mei/mei-amt-version.c
samples/vfs/test-statx.c
samples/watch_queue/Makefile
scripts/Kbuild.include
scripts/Kconfig.include
scripts/Makefile.extrawarn
scripts/Makefile.lib
scripts/atomic/gen-atomic-fallback.sh
scripts/decode_stacktrace.sh
scripts/dtc/checks.c
scripts/dtc/dtc.h
scripts/dtc/flattree.c
scripts/dtc/libfdt/fdt_rw.c
scripts/dtc/libfdt/fdt_sw.c
scripts/dtc/libfdt/libfdt.h
scripts/dtc/treesource.c
scripts/dtc/version_gen.h
scripts/dtc/yamltree.c
scripts/gcc-plugins/Kconfig
scripts/gdb/linux/symbols.py
scripts/headers_install.sh
scripts/kconfig/qconf.cc
scripts/kconfig/qconf.h
scripts/mod/modpost.c
scripts/recordmcount.h
security/integrity/iint.c
security/integrity/ima/ima.h
security/integrity/ima/ima_crypto.c
security/integrity/integrity.h
security/security.c
security/selinux/ss/conditional.c
security/selinux/ss/services.c
sound/core/compress_offload.c
sound/core/info.c
sound/drivers/opl3/opl3_synth.c
sound/hda/intel-dsp-config.c
sound/pci/hda/hda_auto_parser.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_controller.h
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/soc/amd/raven/acp3x-pcm-dma.c
sound/soc/amd/raven/pci-acp3x.c
sound/soc/amd/renoir/Makefile
sound/soc/codecs/hdac_hda.c
sound/soc/codecs/max98373.c
sound/soc/codecs/max98390.c
sound/soc/codecs/rt1015.c
sound/soc/codecs/rt1015.h
sound/soc/codecs/rt286.c
sound/soc/codecs/rt5670.c
sound/soc/codecs/rt5670.h
sound/soc/codecs/rt5682.c
sound/soc/codecs/wm8974.c
sound/soc/fsl/fsl_asrc_common.h
sound/soc/fsl/fsl_asrc_dma.c
sound/soc/fsl/fsl_mqs.c
sound/soc/fsl/fsl_ssi.c
sound/soc/generic/audio-graph-card.c
sound/soc/generic/simple-card.c
sound/soc/intel/boards/Kconfig
sound/soc/intel/boards/bdw-rt5677.c
sound/soc/intel/boards/bytcht_es8316.c
sound/soc/intel/boards/cht_bsw_rt5672.c
sound/soc/qcom/Kconfig
sound/soc/qcom/common.c
sound/soc/qcom/qdsp6/q6afe.c
sound/soc/qcom/qdsp6/q6afe.h
sound/soc/qcom/qdsp6/q6asm.c
sound/soc/rockchip/rk3399_gru_sound.c
sound/soc/rockchip/rockchip_pdm.c
sound/soc/soc-core.c
sound/soc/soc-dai.c
sound/soc/soc-devres.c
sound/soc/soc-generic-dmaengine-pcm.c
sound/soc/soc-pcm.c
sound/soc/soc-topology.c
sound/soc/sof/core.c
sound/soc/sof/imx/imx8.c
sound/soc/sof/imx/imx8m.c
sound/soc/sof/intel/Kconfig
sound/soc/sof/intel/hda-stream.c
sound/soc/sof/probe.h
sound/soc/sof/sof-pci-dev.c
sound/usb/card.h
sound/usb/endpoint.c
sound/usb/format.c
sound/usb/line6/capture.c
sound/usb/line6/driver.c
sound/usb/line6/playback.c
sound/usb/midi.c
sound/usb/mixer.c
sound/usb/mixer.h
sound/usb/mixer_quirks.c
sound/usb/pcm.c
sound/usb/quirks-table.h
sound/usb/quirks.c
tools/arch/x86/include/asm/cpufeatures.h
tools/arch/x86/include/asm/msr-index.h
tools/arch/x86/include/uapi/asm/kvm.h
tools/arch/x86/include/uapi/asm/unistd.h
tools/arch/x86/include/uapi/asm/vmx.h
tools/arch/x86/lib/memcpy_64.S
tools/bootconfig/main.c
tools/bootconfig/test-bootconfig.sh
tools/bpf/bpftool/Documentation/bpftool-map.rst
tools/bpf/bpftool/map.c
tools/include/linux/bits.h
tools/include/uapi/asm-generic/unistd.h
tools/include/uapi/drm/i915_drm.h
tools/include/uapi/linux/bpf.h
tools/include/uapi/linux/fcntl.h
tools/include/uapi/linux/fs.h
tools/include/uapi/linux/fscrypt.h
tools/include/uapi/linux/kvm.h
tools/include/uapi/linux/stat.h
tools/include/uapi/linux/vhost.h
tools/lib/bpf/bpf.h
tools/lib/bpf/hashmap.h
tools/lib/bpf/libbpf.c
tools/lib/subcmd/parse-options.c
tools/lib/traceevent/event-parse.c
tools/lib/traceevent/kbuffer-parse.c
tools/lib/traceevent/kbuffer.h
tools/objtool/arch.h
tools/objtool/arch/x86/decode.c
tools/objtool/arch/x86/include/arch_elf.h [new file with mode: 0644]
tools/objtool/check.c
tools/objtool/elf.c
tools/objtool/elf.h
tools/objtool/orc_gen.c
tools/perf/Makefile.config
tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
tools/perf/arch/x86/util/intel-pt.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-script.c
tools/perf/pmu-events/arch/s390/cf_z15/extended.json
tools/perf/scripts/python/export-to-postgresql.py
tools/perf/scripts/python/exported-sql-viewer.py
tools/perf/scripts/python/flamegraph.py
tools/perf/trace/beauty/statx.c
tools/perf/ui/browsers/hists.c
tools/perf/util/bpf-prologue.c
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/hashmap.h
tools/perf/util/intel-pt.c
tools/perf/util/parse-events.y
tools/perf/util/pmu.h
tools/perf/util/probe-event.c
tools/perf/util/probe-file.c
tools/perf/util/stat-display.c
tools/spi/spidev_test.c
tools/testing/kunit/kunit.py
tools/testing/kunit/kunit_config.py
tools/testing/kunit/kunit_parser.py
tools/testing/kunit/kunit_tool_test.py
tools/testing/kunit/test_data/test_insufficient_memory.log [new file with mode: 0644]
tools/testing/nvdimm/test/nfit_test.h
tools/testing/selftests/arm64/signal/Makefile
tools/testing/selftests/bpf/prog_tests/fentry_fexit.c
tools/testing/selftests/bpf/prog_tests/flow_dissector.c
tools/testing/selftests/bpf/prog_tests/flow_dissector_reattach.c
tools/testing/selftests/bpf/prog_tests/sockopt_sk.c
tools/testing/selftests/bpf/progs/bpf_cubic.c
tools/testing/selftests/bpf/progs/bpf_iter_netlink.c
tools/testing/selftests/bpf/progs/fentry_test.c
tools/testing/selftests/bpf/progs/fexit_test.c
tools/testing/selftests/bpf/progs/sockopt_sk.c
tools/testing/selftests/bpf/progs/test_sockmap_kern.h
tools/testing/selftests/bpf/progs/test_xdp_with_devmap_helpers.c
tools/testing/selftests/bpf/test_maps.c
tools/testing/selftests/bpf/test_sockmap.c
tools/testing/selftests/ftrace/ftracetest
tools/testing/selftests/ftrace/test.d/00basic/snapshot.tc
tools/testing/selftests/ftrace/test.d/00basic/trace_pipe.tc
tools/testing/selftests/ftrace/test.d/direct/kprobe-direct.tc
tools/testing/selftests/ftrace/test.d/dynevent/add_remove_kprobe.tc
tools/testing/selftests/ftrace/test.d/dynevent/add_remove_synth.tc
tools/testing/selftests/ftrace/test.d/dynevent/clear_select_events.tc
tools/testing/selftests/ftrace/test.d/dynevent/generic_clear_event.tc
tools/testing/selftests/ftrace/test.d/event/event-enable.tc
tools/testing/selftests/ftrace/test.d/event/event-no-pid.tc
tools/testing/selftests/ftrace/test.d/event/event-pid.tc
tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc
tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc
tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc
tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc
tools/testing/selftests/ftrace/test.d/ftrace/func-filter-glob.tc
tools/testing/selftests/ftrace/test.d/ftrace/func-filter-notrace-pid.tc
tools/testing/selftests/ftrace/test.d/ftrace/func-filter-pid.tc
tools/testing/selftests/ftrace/test.d/ftrace/func-filter-stacktrace.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_cpumask.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_mod_trace.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_profile_stat.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_set_ftrace_file.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_stack_tracer.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc
tools/testing/selftests/ftrace/test.d/ftrace/tracing-error-log.tc
tools/testing/selftests/ftrace/test.d/functions
tools/testing/selftests/ftrace/test.d/instances/instance-event.tc
tools/testing/selftests/ftrace/test.d/instances/instance.tc
tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc
tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_comm.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_symbol.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_syntax.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_type.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_user.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_eventname.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_ftrace.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_module.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_multiprobe.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc
tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc
tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_maxactive.tc
tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc
tools/testing/selftests/ftrace/test.d/kprobe/probepoint.tc
tools/testing/selftests/ftrace/test.d/kprobe/profile.tc
tools/testing/selftests/ftrace/test.d/kprobe/uprobe_syntax_errors.tc
tools/testing/selftests/ftrace/test.d/preemptirq/irqsoff_tracer.tc
tools/testing/selftests/ftrace/test.d/template
tools/testing/selftests/ftrace/test.d/tracer/wakeup.tc
tools/testing/selftests/ftrace/test.d/tracer/wakeup_rt.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-action-hist-xfail.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-field-variable-support.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-multi-actions-accept.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onchange-action-hist.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmax-action-hist.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-snapshot-action-hist.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-createremove.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-syntax.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-trace-action-hist.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-syntax-errors.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-trace-marker-hist.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-trace-marker-snapshot.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-trace-marker-synthetic-kernel.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-trace-marker-synthetic.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc
tools/testing/selftests/kmod/kmod.sh
tools/testing/selftests/kselftest.h
tools/testing/selftests/net/fib_nexthop_multiprefix.sh
tools/testing/selftests/net/fib_nexthops.sh
tools/testing/selftests/net/ip_defrag.sh
tools/testing/selftests/net/so_txtime.c
tools/testing/selftests/net/txtimestamp.sh
tools/testing/selftests/netfilter/Makefile
tools/testing/selftests/netfilter/nft_conntrack_helper.sh [new file with mode: 0755]
tools/testing/selftests/pidfd/pidfd.h
tools/testing/selftests/pidfd/pidfd_getfd_test.c
tools/testing/selftests/pidfd/pidfd_setns_test.c
tools/testing/selftests/powerpc/nx-gzip/gunz_test.c
tools/testing/selftests/powerpc/nx-gzip/gzfht_test.c
tools/testing/selftests/powerpc/pmu/ebb/Makefile
tools/testing/selftests/seccomp/seccomp_bpf.c
tools/testing/selftests/tc-testing/tc-tests/actions/bpf.json
tools/testing/selftests/tc-testing/tc-tests/actions/csum.json
tools/testing/selftests/tc-testing/tc-tests/actions/tunnel_key.json
tools/testing/selftests/tpm2/test_smoke.sh
tools/testing/selftests/tpm2/test_space.sh
tools/testing/selftests/tpm2/tpm2.py
tools/testing/selftests/tpm2/tpm2_tests.py
tools/testing/selftests/wireguard/netns.sh
tools/testing/selftests/x86/Makefile
tools/testing/selftests/x86/helpers.h [new file with mode: 0644]
tools/testing/selftests/x86/single_step_syscall.c
tools/testing/selftests/x86/syscall_arg_fault.c
tools/testing/selftests/x86/syscall_nt.c
tools/testing/selftests/x86/test_vsyscall.c
tools/testing/selftests/x86/unwind_vdso.c
tools/virtio/linux/kernel.h
tools/virtio/linux/virtio.h
tools/virtio/virtio_test.c
tools/virtio/vringh_test.c
virt/kvm/kvm_main.c

index 87b9dd8..d5f4804 100644 (file)
@@ -143,6 +143,9 @@ x509.genkey
 /allrandom.config
 /allyes.config
 
+# Kconfig savedefconfig output
+/defconfig
+
 # Kdevelop4
 *.kdev4
 
index c69d9c7..db4f229 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -90,11 +90,16 @@ Frank Rowand <frowand.list@gmail.com> <frank.rowand@sonymobile.com>
 Frank Zago <fzago@systemfabricworks.com>
 Gao Xiang <xiang@kernel.org> <gaoxiang25@huawei.com>
 Gao Xiang <xiang@kernel.org> <hsiangkao@aol.com>
+Gerald Schaefer <gerald.schaefer@linux.ibm.com> <gerald.schaefer@de.ibm.com>
+Gerald Schaefer <gerald.schaefer@linux.ibm.com> <geraldsc@de.ibm.com>
+Gerald Schaefer <gerald.schaefer@linux.ibm.com> <geraldsc@linux.vnet.ibm.com>
 Greg Kroah-Hartman <greg@echidna.(none)>
 Greg Kroah-Hartman <gregkh@suse.de>
 Greg Kroah-Hartman <greg@kroah.com>
 Gregory CLEMENT <gregory.clement@bootlin.com> <gregory.clement@free-electrons.com>
 Hanjun Guo <guohanjun@huawei.com> <hanjun.guo@linaro.org>
+Heiko Carstens <hca@linux.ibm.com> <h.carstens@de.ibm.com>
+Heiko Carstens <hca@linux.ibm.com> <heiko.carstens@de.ibm.com>
 Henk Vergonet <Henk.Vergonet@gmail.com>
 Henrik Kretzschmar <henne@nachtwindheim.de>
 Henrik Rydberg <rydberg@bitmath.org>
@@ -193,6 +198,9 @@ Maxime Ripard <mripard@kernel.org> <maxime.ripard@free-electrons.com>
 Mayuresh Janorkar <mayur@ti.com>
 Michael Buesch <m@bues.ch>
 Michel Dänzer <michel@tungstengraphics.com>
+Mike Rapoport <rppt@kernel.org> <mike@compulab.co.il>
+Mike Rapoport <rppt@kernel.org> <mike.rapoport@gmail.com>
+Mike Rapoport <rppt@kernel.org> <rppt@linux.ibm.com>
 Miodrag Dinic <miodrag.dinic@mips.com> <miodrag.dinic@imgtec.com>
 Miquel Raynal <miquel.raynal@bootlin.com> <miquel.raynal@free-electrons.com>
 Mitesh shah <mshah@teja.com>
index f6d9c2a..2e9ae31 100644 (file)
@@ -16,7 +16,16 @@ Description:    Allow the root user to disable/enable in runtime the clock
                 gating mechanism in Gaudi. Due to how Gaudi is built, the
                 clock gating needs to be disabled in order to access the
                 registers of the TPC and MME engines. This is sometimes needed
-                during debug by the user and hence the user needs this option
+                during debug by the user and hence the user needs this option.
+                The user can supply a bitmask value, each bit represents
+                a different engine to disable/enable its clock gating feature.
+                The bitmask is composed of 20 bits:
+                0  -  7 : DMA channels
+                8  - 11 : MME engines
+                12 - 19 : TPC engines
+                The bit's location of a specific engine can be determined
+                using (1 << GAUDI_ENGINE_ID_*). GAUDI_ENGINE_ID_* values
+                are defined in uapi habanalabs.h file in enum gaudi_engine_id
 
 What:           /sys/kernel/debug/habanalabs/hl<n>/command_buffers
 Date:           Jan 2019
index 1e6c28b..f307506 100644 (file)
@@ -56,11 +56,6 @@ Description: The /dev/kmsg character device node provides userspace access
                  seek after the last record available at the time
                  the last SYSLOG_ACTION_CLEAR was issued.
 
-               Due to the record nature of this interface with a "read all"
-               behavior and the specific positions each seek operation sets,
-               SEEK_CUR is not supported, returning -ESPIPE (invalid seek) to
-               errno whenever requested.
-
                The output format consists of a prefix carrying the syslog
                prefix including priority and facility, the 64 bit message
                sequence number and the monotonic timestamp in microseconds,
diff --git a/Documentation/ABI/testing/sysfs-bus-papr-pmem b/Documentation/ABI/testing/sysfs-bus-papr-pmem
new file mode 100644 (file)
index 0000000..5b10d03
--- /dev/null
@@ -0,0 +1,27 @@
+What:          /sys/bus/nd/devices/nmemX/papr/flags
+Date:          Apr, 2020
+KernelVersion: v5.8
+Contact:       linuxppc-dev <linuxppc-dev@lists.ozlabs.org>, linux-nvdimm@lists.01.org,
+Description:
+               (RO) Report flags indicating various states of a
+               papr-pmem NVDIMM device. Each flag maps to a one or
+               more bits set in the dimm-health-bitmap retrieved in
+               response to H_SCM_HEALTH hcall. The details of the bit
+               flags returned in response to this hcall is available
+               at 'Documentation/powerpc/papr_hcalls.rst' . Below are
+               the flags reported in this sysfs file:
+
+               * "not_armed"   : Indicates that NVDIMM contents will not
+                                 survive a power cycle.
+               * "flush_fail"  : Indicates that NVDIMM contents
+                                 couldn't be flushed during last
+                                 shut-down event.
+               * "restore_fail": Indicates that NVDIMM contents
+                                 couldn't be restored during NVDIMM
+                                 initialization.
+               * "encrypted"   : NVDIMM contents are encrypted.
+               * "smart_notify": There is health event for the NVDIMM.
+               * "scrubbed"    : Indicating that contents of the
+                                 NVDIMM have been scrubbed.
+               * "locked"      : Indicating that NVDIMM contents cant
+                                 be modified until next power cycle.
index 151c595..f58cfb0 100644 (file)
@@ -1,6 +1,6 @@
 What:          /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_req
 Date:          Feb 2014
-Contact:       Li Jun <b47624@freescale.com>
+Contact:       Li Jun <jun.li@nxp.com>
 Description:
                Can be set and read.
                Set a_bus_req(A-device bus request) input to be 1 if
@@ -17,7 +17,7 @@ Description:
 
 What:          /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_drop
 Date:          Feb 2014
-Contact:       Li Jun <b47624@freescale.com>
+Contact:       Li Jun <jun.li@nxp.com>
 Description:
                Can be set and read
                The a_bus_drop(A-device bus drop) input is 1 when the
@@ -32,7 +32,7 @@ Description:
 
 What:          /sys/bus/platform/devices/ci_hdrc.0/inputs/b_bus_req
 Date:          Feb 2014
-Contact:       Li Jun <b47624@freescale.com>
+Contact:       Li Jun <jun.li@nxp.com>
 Description:
                Can be set and read.
                The b_bus_req(B-device bus request) input is 1 during the time
@@ -47,7 +47,7 @@ Description:
 
 What:          /sys/bus/platform/devices/ci_hdrc.0/inputs/a_clr_err
 Date:          Feb 2014
-Contact:       Li Jun <b47624@freescale.com>
+Contact:       Li Jun <jun.li@nxp.com>
 Description:
                Only can be set.
                The a_clr_err(A-device Vbus error clear) input is used to clear
index 5fb5269..5aad534 100644 (file)
@@ -258,7 +258,7 @@ Configuring the kernel
 Compiling the kernel
 --------------------
 
- - Make sure you have at least gcc 4.6 available.
+ - Make sure you have at least gcc 4.9 available.
    For more information, refer to :ref:`Documentation/process/changes.rst <changes>`.
 
    Please note that you can still run a.out user programs with this kernel.
index ce3e05e..d09471a 100644 (file)
@@ -1356,8 +1356,8 @@ PAGE_SIZE multiple when read back.
 
          thp_fault_alloc
                Number of transparent hugepages which were allocated to satisfy
-               a page fault, including COW faults. This counter is not present
-               when CONFIG_TRANSPARENT_HUGEPAGE is not set.
+               a page fault. This counter is not present when CONFIG_TRANSPARENT_HUGEPAGE
+                is not set.
 
          thp_collapse_alloc
                Number of transparent hugepages which were allocated to allow
index ec62fcc..6cf8adc 100644 (file)
@@ -11,6 +11,7 @@ Device Mapper
     dm-clone
     dm-crypt
     dm-dust
+    dm-ebs
     dm-flakey
     dm-init
     dm-integrity
index 6a233e4..b2acd0d 100644 (file)
@@ -305,8 +305,7 @@ monitor how successfully the system is providing huge pages for use.
 
 thp_fault_alloc
        is incremented every time a huge page is successfully
-       allocated to handle a page fault. This applies to both the
-       first time a page is faulted and for COW faults.
+       allocated to handle a page fault.
 
 thp_collapse_alloc
        is incremented by khugepaged when it has found
index 314fa5b..f28853f 100644 (file)
@@ -171,6 +171,7 @@ infrastructure:
 
 
   3) ID_AA64PFR1_EL1 - Processor Feature Register 1
+
      +------------------------------+---------+---------+
      | Name                         |  bits   | visible |
      +------------------------------+---------+---------+
@@ -181,6 +182,7 @@ infrastructure:
 
 
   4) MIDR_EL1 - Main ID Register
+
      +------------------------------+---------+---------+
      | Name                         |  bits   | visible |
      +------------------------------+---------+---------+
index 936cf2a..3f7c3a7 100644 (file)
@@ -147,6 +147,14 @@ stable kernels.
 +----------------+-----------------+-----------------+-----------------------------+
 | Qualcomm Tech. | Falkor v{1,2}   | E1041           | QCOM_FALKOR_ERRATUM_1041    |
 +----------------+-----------------+-----------------+-----------------------------+
+| Qualcomm Tech. | Kryo4xx Gold    | N/A             | ARM64_ERRATUM_1463225       |
++----------------+-----------------+-----------------+-----------------------------+
+| Qualcomm Tech. | Kryo4xx Gold    | N/A             | ARM64_ERRATUM_1418040       |
++----------------+-----------------+-----------------+-----------------------------+
+| Qualcomm Tech. | Kryo4xx Silver  | N/A             | ARM64_ERRATUM_1530923       |
++----------------+-----------------+-----------------+-----------------------------+
+| Qualcomm Tech. | Kryo4xx Silver  | N/A             | ARM64_ERRATUM_1024718       |
++----------------+-----------------+-----------------+-----------------------------+
 +----------------+-----------------+-----------------+-----------------------------+
 | Fujitsu        | A64FX           | E#010001        | FUJITSU_ERRATUM_010001      |
 +----------------+-----------------+-----------------+-----------------------------+
index 5689c74..bfd55f4 100644 (file)
@@ -186,7 +186,7 @@ prctl(PR_SVE_SET_VL, unsigned long arg)
 
     flags:
 
-       PR_SVE_SET_VL_INHERIT
+       PR_SVE_VL_INHERIT
 
            Inherit the current vector length across execve().  Otherwise, the
            vector length is reset to the system default at execve().  (See
@@ -247,7 +247,7 @@ prctl(PR_SVE_GET_VL)
 
     The following flag may be OR-ed into the result:
 
-       PR_SVE_SET_VL_INHERIT
+       PR_SVE_VL_INHERIT
 
            Vector length will be inherited across execve().
 
@@ -393,7 +393,7 @@ The regset data starts with struct user_sve_header, containing:
 * At every execve() call, the new vector length of the new process is set to
   the system default vector length, unless
 
-    * PR_SVE_SET_VL_INHERIT (or equivalently SVE_PT_VL_INHERIT) is set for the
+    * PR_SVE_VL_INHERIT (or equivalently SVE_PT_VL_INHERIT) is set for the
       calling thread, or
 
     * a deferred vector length change is pending, established via the
index 0d237d4..19d4d15 100644 (file)
@@ -492,13 +492,6 @@ set max_budget to higher values than those to which BFQ would have set
 it with auto-tuning. An alternative way to achieve this goal is to
 just increase the value of timeout_sync, leaving max_budget equal to 0.
 
-weights
--------
-
-Read-only parameter, used to show the weights of the currently active
-BFQ queues.
-
-
 4. Group scheduling with BFQ
 ============================
 
@@ -566,7 +559,7 @@ Parameters to set
 For each group, there is only the following parameter to set.
 
 weight (namely blkio.bfq.weight or io.bfq-weight): the weight of the
-group inside its parent. Available values: 1..10000 (default 100). The
+group inside its parent. Available values: 1..1000 (default 100). The
 linear mapping between ioprio and weights, described at the beginning
 of the tunable section, is still valid, but all weights higher than
 IOPRIO_BE_NR*10 are mapped to ioprio 0.
index c47d974..172f957 100644 (file)
@@ -86,6 +86,20 @@ then the next program in the chain (A) will see those changes,
 *not* the original input ``setsockopt`` arguments. The potentially
 modified values will be then passed down to the kernel.
 
+Large optval
+============
+When the ``optval`` is greater than the ``PAGE_SIZE``, the BPF program
+can access only the first ``PAGE_SIZE`` of that data. So it has to options:
+
+* Set ``optlen`` to zero, which indicates that the kernel should
+  use the original buffer from the userspace. Any modifications
+  done by the BPF program to the ``optval`` are ignored.
+* Set ``optlen`` to the value less than ``PAGE_SIZE``, which
+  indicates that the kernel should use BPF's trimmed ``optval``.
+
+When the BPF program returns with the ``optlen`` greater than
+``PAGE_SIZE``, the userspace will receive ``EFAULT`` errno.
+
 Example
 =======
 
index 2d8d2fe..f416204 100644 (file)
@@ -204,6 +204,14 @@ Returns the maximum size of a mapping for the device. The size parameter
 of the mapping functions like dma_map_single(), dma_map_page() and
 others should not be larger than the returned value.
 
+::
+
+       bool
+       dma_need_sync(struct device *dev, dma_addr_t dma_addr);
+
+Returns %true if dma_sync_single_for_{device,cpu} calls are required to
+transfer memory ownership.  Returns %false if those calls can be skipped.
+
 ::
 
        unsigned long
index 6068266..7ca8c7b 100644 (file)
@@ -33,7 +33,7 @@ all combinations of get*(), pin*(), FOLL_LONGTERM, and more. Also, the
 pin_user_pages*() APIs are clearly distinct from the get_user_pages*() APIs, so
 that's a natural dividing line, and a good point to make separate wrapper calls.
 In other words, use pin_user_pages*() for DMA-pinned pages, and
-get_user_pages*() for other cases. There are four cases described later on in
+get_user_pages*() for other cases. There are five cases described later on in
 this document, to further clarify that concept.
 
 FOLL_PIN and FOLL_GET are mutually exclusive for a given gup call. However,
index ce4bbd9..b38379f 100644 (file)
@@ -114,12 +114,6 @@ the below options are available:
   To dynamically limit for which functions to generate reports, see the
   `DebugFS interface`_ blacklist/whitelist feature.
 
-  For ``__always_inline`` functions, replace ``__always_inline`` with
-  ``__no_kcsan_or_inline`` (which implies ``__always_inline``)::
-
-    static __no_kcsan_or_inline void foo(void) {
-        ...
-
 * To disable data race detection for a particular compilation unit, add to the
   ``Makefile``::
 
index ea55b24..1628862 100644 (file)
@@ -61,3 +61,43 @@ test, or an end-to-end test.
   kernel by installing a production configuration of the kernel on production
   hardware with a production userspace and then trying to exercise some behavior
   that depends on interactions between the hardware, the kernel, and userspace.
+
+KUnit isn't working, what should I do?
+======================================
+
+Unfortunately, there are a number of things which can break, but here are some
+things to try.
+
+1. Try running ``./tools/testing/kunit/kunit.py run`` with the ``--raw_output``
+   parameter. This might show details or error messages hidden by the kunit_tool
+   parser.
+2. Instead of running ``kunit.py run``, try running ``kunit.py config``,
+   ``kunit.py build``, and ``kunit.py exec`` independently. This can help track
+   down where an issue is occurring. (If you think the parser is at fault, you
+   can run it manually against stdin or a file with ``kunit.py parse``.)
+3. Running the UML kernel directly can often reveal issues or error messages
+   kunit_tool ignores. This should be as simple as running ``./vmlinux`` after
+   building the UML kernel (e.g., by using ``kunit.py build``). Note that UML
+   has some unusual requirements (such as the host having a tmpfs filesystem
+   mounted), and has had issues in the past when built statically and the host
+   has KASLR enabled. (On older host kernels, you may need to run ``setarch
+   `uname -m` -R ./vmlinux`` to disable KASLR.)
+4. Make sure the kernel .config has ``CONFIG_KUNIT=y`` and at least one test
+   (e.g. ``CONFIG_KUNIT_EXAMPLE_TEST=y``). kunit_tool will keep its .config
+   around, so you can see what config was used after running ``kunit.py run``.
+   It also preserves any config changes you might make, so you can
+   enable/disable things with ``make ARCH=um menuconfig`` or similar, and then
+   re-run kunit_tool.
+5. Try to run ``make ARCH=um defconfig`` before running ``kunit.py run``. This
+   may help clean up any residual config items which could be causing problems.
+6. Finally, try running KUnit outside UML. KUnit and KUnit tests can run be
+   built into any kernel, or can be built as a module and loaded at runtime.
+   Doing so should allow you to determine if UML is causing the issue you're
+   seeing. When tests are built-in, they will execute when the kernel boots, and
+   modules will automatically execute associated tests when loaded. Test results
+   can be collected from ``/sys/kernel/debug/kunit/<test suite>/results``, and
+   can be parsed with ``kunit.py parse``. For more details, see "KUnit on
+   non-UML architectures" in :doc:`usage`.
+
+If none of the above tricks help, you are always welcome to email any issues to
+kunit-dev@googlegroups.com.
index a638989..91c4d00 100644 (file)
@@ -2,7 +2,6 @@
 DT_DOC_CHECKER ?= dt-doc-validate
 DT_EXTRACT_EX ?= dt-extract-example
 DT_MK_SCHEMA ?= dt-mk-schema
-DT_MK_SCHEMA_USERONLY_FLAG := $(if $(DT_SCHEMA_FILES), -u)
 
 DT_SCHEMA_MIN_VERSION = 2020.5
 
@@ -35,21 +34,40 @@ quiet_cmd_mk_schema = SCHEMA  $@
 
 DT_DOCS = $(shell $(find_cmd) | sed -e 's|^$(srctree)/||')
 
-DT_SCHEMA_FILES ?= $(DT_DOCS)
-
-extra-$(CHECK_DT_BINDING) += $(patsubst $(src)/%.yaml,%.example.dts, $(DT_SCHEMA_FILES))
-extra-$(CHECK_DT_BINDING) += $(patsubst $(src)/%.yaml,%.example.dt.yaml, $(DT_SCHEMA_FILES))
-extra-$(CHECK_DT_BINDING) += processed-schema-examples.yaml
-
 override DTC_FLAGS := \
        -Wno-avoid_unnecessary_addr_size \
-       -Wno-graph_child_address
+       -Wno-graph_child_address \
+       -Wno-interrupt_provider
 
 $(obj)/processed-schema-examples.yaml: $(DT_DOCS) check_dtschema_version FORCE
        $(call if_changed,mk_schema)
 
-$(obj)/processed-schema.yaml: DT_MK_SCHEMA_FLAGS := $(DT_MK_SCHEMA_USERONLY_FLAG)
+ifeq ($(DT_SCHEMA_FILES),)
+
+# Unless DT_SCHEMA_FILES is specified, use the full schema for dtbs_check too.
+# Just copy processed-schema-examples.yaml
+
+$(obj)/processed-schema.yaml: $(obj)/processed-schema-examples.yaml FORCE
+       $(call if_changed,copy)
+
+DT_SCHEMA_FILES = $(DT_DOCS)
+
+else
+
+# If DT_SCHEMA_FILES is specified, use it for processed-schema.yaml
+
+$(obj)/processed-schema.yaml: DT_MK_SCHEMA_FLAGS := -u
 $(obj)/processed-schema.yaml: $(DT_SCHEMA_FILES) check_dtschema_version FORCE
        $(call if_changed,mk_schema)
 
-extra-y += processed-schema.yaml
+endif
+
+extra-$(CHECK_DT_BINDING) += $(patsubst $(src)/%.yaml,%.example.dts, $(DT_SCHEMA_FILES))
+extra-$(CHECK_DT_BINDING) += $(patsubst $(src)/%.yaml,%.example.dt.yaml, $(DT_SCHEMA_FILES))
+extra-$(CHECK_DT_BINDING) += processed-schema-examples.yaml
+extra-$(CHECK_DTBS) += processed-schema.yaml
+
+# Hack: avoid 'Argument list too long' error for 'make clean'. Remove most of
+# build artifacts here before they are processed by scripts/Makefile.clean
+clean-files = $(shell find $(obj) \( -name '*.example.dts' -o \
+                       -name '*.example.dt.yaml' \) -delete 2>/dev/null)
index 7150474..10b8459 100644 (file)
@@ -47,7 +47,7 @@ Required properties:
                          &lsio_mu1 1 2
                          &lsio_mu1 1 3
                          &lsio_mu1 3 3>;
-               See Documentation/devicetree/bindings/mailbox/fsl,mu.txt
+               See Documentation/devicetree/bindings/mailbox/fsl,mu.yaml
                for detailed mailbox binding.
 
 Note: Each mu which supports general interrupt should have an alias correctly
index c4c9119..a0c6c5d 100644 (file)
@@ -80,14 +80,14 @@ examples:
         ranges = <1 0x00000000 0x42000000 0x02000000>,
                  <5 0x00000000 0x46000000 0x01000000>;
 
-        ethernet@1,01f00000 {
+        ethernet@1,1f00000 {
             compatible = "smsc,lan9115";
             reg = <1 0x01f00000 0x1000>;
             interrupts = <0 48 4>;
             phy-mode = "mii";
         };
 
-        uart@5,00200000 {
+        serial@5,200000 {
             compatible = "ns16550a";
             reg = <5 0x00200000 0x20>;
             interrupts = <0 49 4>;
index b5f3ed0..a753654 100644 (file)
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Clock bindings for Freescale i.MX27
 
 maintainers:
-  - Fabio Estevam <fabio.estevam@freescale.com>
+  - Fabio Estevam <fabio.estevam@nxp.com>
 
 description: |
   The clock consumer should specify the desired clock by having the clock
index 1b6f75d..a25a374 100644 (file)
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Clock bindings for Freescale i.MX31
 
 maintainers:
-  - Fabio Estevam <fabio.estevam@freescale.com>
+  - Fabio Estevam <fabio.estevam@nxp.com>
 
 description: |
   The clock consumer should specify the desired clock by having the clock
index f5c2b3d..4d9e7c7 100644 (file)
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Clock bindings for Freescale i.MX5
 
 maintainers:
-  - Fabio Estevam <fabio.estevam@freescale.com>
+  - Fabio Estevam <fabio.estevam@nxp.com>
 
 description: |
   The clock consumer should specify the desired clock by having the clock
index 6e14e08..0d1db3f 100644 (file)
@@ -37,7 +37,7 @@ Optional properties:
        simple-card or audio-graph-card binding. See their binding
        documents on how to describe the way the sii902x device is
        connected to the rest of the audio system:
-       Documentation/devicetree/bindings/sound/simple-card.txt
+       Documentation/devicetree/bindings/sound/simple-card.yaml
        Documentation/devicetree/bindings/sound/audio-graph-card.txt
        Note: In case of the audio-graph-card binding the used port
        index should be 3.
index 5bf77f6..5a99490 100644 (file)
@@ -68,7 +68,7 @@ Required properties:
   datasheet
 - clocks : phandle to the PRE axi clock input, as described
   in Documentation/devicetree/bindings/clock/clock-bindings.txt and
-  Documentation/devicetree/bindings/clock/imx6q-clock.txt.
+  Documentation/devicetree/bindings/clock/imx6q-clock.yaml.
 - clock-names: should be "axi"
 - interrupts: should contain the PRE interrupt
 - fsl,iram: phandle pointing to the mmio-sram device node, that should be
@@ -94,7 +94,7 @@ Required properties:
   datasheet
 - clocks : phandles to the PRG ipg and axi clock inputs, as described
   in Documentation/devicetree/bindings/clock/clock-bindings.txt and
-  Documentation/devicetree/bindings/clock/imx6q-clock.txt.
+  Documentation/devicetree/bindings/clock/imx6q-clock.yaml.
 - clock-names: should be "ipg" and "axi"
 - fsl,pres: phandles to the PRE units attached to this PRG, with the fixed
   PRE as the first entry and the muxable PREs following.
index 38c637f..8e6e7d7 100644 (file)
@@ -30,8 +30,8 @@ Required properties:
                 "di2_sel" - IPU2 DI0 mux
                 "di3_sel" - IPU2 DI1 mux
         The needed clock numbers for each are documented in
-        Documentation/devicetree/bindings/clock/imx5-clock.txt, and in
-        Documentation/devicetree/bindings/clock/imx6q-clock.txt.
+        Documentation/devicetree/bindings/clock/imx5-clock.yaml, and in
+        Documentation/devicetree/bindings/clock/imx6q-clock.yaml.
 
 Optional properties:
  - pinctrl-names : should be "default" on i.MX53, not used on i.MX6q
index 41fd571..be69e0c 100644 (file)
@@ -33,7 +33,7 @@ additionalProperties: false
 
 examples:
   - |
-    sysreg {
+    sysreg@0 {
         compatible = "arm,versatile-sysreg", "syscon", "simple-mfd";
         reg = <0x00000 0x1000>;
 
index ec8ae74..7204da5 100644 (file)
@@ -24,7 +24,7 @@ properties:
     description: |
       Should contain a list of phandles pointing to display interface port
       of vop devices. vop definitions as defined in
-      Documentation/devicetree/bindings/display/rockchip/rockchip-vop.txt
+      Documentation/devicetree/bindings/display/rockchip/rockchip-vop.yaml
 
 required:
   - compatible
index ba45558..e1c49b6 100644 (file)
@@ -12,7 +12,7 @@ Required properties for the top level node:
    Only the GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported.
 - #interrupt-cells : Specifies the number of cells needed to encode an
    interrupt. Should be 2. The first cell defines the interrupt number,
-   the second encodes the triger flags encoded as described in
+   the second encodes the trigger flags encoded as described in
    Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
 - compatible:
   - "mediatek,mt7621-gpio" for Mediatek controllers
index e134053..e6bbcae 100644 (file)
@@ -10,7 +10,7 @@ Interrupt number definition:
  16-31  : private  irq, and we use 16 as the co-processor timer.
  31-1024: common irq for soc ip.
 
-Interrupt triger mode: (Defined in dt-bindings/interrupt-controller/irq.h)
+Interrupt trigger mode: (Defined in dt-bindings/interrupt-controller/irq.h)
  IRQ_TYPE_LEVEL_HIGH (default)
  IRQ_TYPE_LEVEL_LOW
  IRQ_TYPE_EDGE_RISING
index 4438432..ad76edc 100644 (file)
@@ -87,7 +87,7 @@ Example:
                ranges;
 
                /* APU<->RPU0 IPI mailbox controller */
-               ipi_mailbox_rpu0: mailbox@ff90400 {
+               ipi_mailbox_rpu0: mailbox@ff990400 {
                        reg = <0xff990400 0x20>,
                              <0xff990420 0x20>,
                              <0xff990080 0x20>,
index 526593c..4cc1a67 100644 (file)
@@ -47,6 +47,9 @@ properties:
     $ref: /schemas/types.yaml#/definitions/phandle-array
     description: Phandle to the device SRAM
 
+  iommus:
+    maxItems: 1
+
   memory-region:
     description:
       CMA pool to use for buffers allocation instead of the default
index 8c4d649..2d7cdf1 100644 (file)
@@ -8,7 +8,7 @@ The embedded controller requires the SPI controller driver to signal readiness
 to receive a transfer (that is, when TX FIFO contains the response data) by
 strobing the ACK pin with the ready signal. See the "ready-gpios" property of the
 SSP binding as documented in:
-<Documentation/devicetree/bindings/spi/spi-pxa2xx.txt>.
+<Documentation/devicetree/bindings/spi/marvell,mmp2-ssp.yaml>.
 
 Example:
        &ssp3 {
index 219bcbd..9ef5bac 100644 (file)
@@ -3,7 +3,7 @@ MediaTek SoC built-in Bluetooth Devices
 
 This device is a serial attached device to BTIF device and thus it must be a
 child node of the serial node with BTIF. The dt-bindings details for BTIF
-device can be known via Documentation/devicetree/bindings/serial/8250.txt.
+device can be known via Documentation/devicetree/bindings/serial/8250.yaml.
 
 Required properties:
 
index b686131..1b8e8b4 100644 (file)
@@ -114,7 +114,7 @@ with values derived from the SoC user manual.
    [flags]>
 
 On other mach-shmobile platforms GPIO is handled by the gpio-rcar driver.
-Please refer to Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt
+Please refer to Documentation/devicetree/bindings/gpio/renesas,rcar-gpio.yaml
 for documentation of the GPIO device tree bindings on those platforms.
 
 
index 2696826..d5f6919 100644 (file)
@@ -5,7 +5,7 @@ It is based on common bindings for device graphs.
 see ${LINUX}/Documentation/devicetree/bindings/graph.txt
 
 Basically, Audio Graph Card property is same as Simple Card.
-see ${LINUX}/Documentation/devicetree/bindings/sound/simple-card.txt
+see ${LINUX}/Documentation/devicetree/bindings/sound/simple-card.yaml
 
 Below are same as Simple-Card.
 
index 8132d0c..35e6690 100644 (file)
@@ -378,6 +378,8 @@ examples:
   - |
     sound {
         compatible = "simple-audio-card";
+        #address-cells = <1>;
+        #size-cells = <0>;
 
         simple-audio-card,name = "rsnd-ak4643";
         simple-audio-card,format = "left_j";
@@ -391,10 +393,12 @@ examples:
                                     "ak4642 Playback", "DAI1 Playback";
 
         dpcmcpu: simple-audio-card,cpu@0 {
+            reg = <0>;
             sound-dai = <&rcar_sound 0>;
         };
 
         simple-audio-card,cpu@1 {
+            reg = <1>;
             sound-dai = <&rcar_sound 1>;
         };
 
@@ -418,6 +422,8 @@ examples:
   - |
     sound {
         compatible = "simple-audio-card";
+        #address-cells = <1>;
+        #size-cells = <0>;
 
         simple-audio-card,routing =
             "pcm3168a Playback", "DAI1 Playback",
@@ -426,6 +432,7 @@ examples:
             "pcm3168a Playback", "DAI4 Playback";
 
         simple-audio-card,dai-link@0 {
+            reg = <0>;
             format = "left_j";
             bitclock-master = <&sndcpu0>;
             frame-master = <&sndcpu0>;
@@ -439,22 +446,23 @@ examples:
         };
 
         simple-audio-card,dai-link@1 {
+            reg = <1>;
             format = "i2s";
             bitclock-master = <&sndcpu1>;
             frame-master = <&sndcpu1>;
 
             convert-channels = <8>; /* TDM Split */
 
-            sndcpu1: cpu@0 {
+            sndcpu1: cpu0 {
                 sound-dai = <&rcar_sound 1>;
             };
-            cpu@1 {
+            cpu1 {
                 sound-dai = <&rcar_sound 2>;
             };
-            cpu@2 {
+            cpu2 {
                 sound-dai = <&rcar_sound 3>;
             };
-            cpu@3 {
+            cpu3 {
                 sound-dai = <&rcar_sound 4>;
             };
             codec {
@@ -466,6 +474,7 @@ examples:
         };
 
         simple-audio-card,dai-link@2 {
+            reg = <2>;
             format = "i2s";
             bitclock-master = <&sndcpu2>;
             frame-master = <&sndcpu2>;
index 4d51f3f..a6ffcde 100644 (file)
@@ -5,7 +5,7 @@ codec or external codecs.
 
 sti sound drivers allows to expose sti SoC audio interface through the
 generic ASoC simple card. For details about sound card declaration please refer to
-Documentation/devicetree/bindings/sound/simple-card.txt.
+Documentation/devicetree/bindings/sound/simple-card.yaml.
 
 1) sti-uniperiph-dai: audio dai device.
 ---------------------------------------
index 9147df2..38efb50 100644 (file)
@@ -34,12 +34,15 @@ properties:
     maxItems: 1
 
   clocks:
-    maxItems: 1
+    minItems: 1
+    maxItems: 2
+    items:
+      - description: controller register bus clock
+      - description: baud rate generator and delay control clock
 
   clock-names:
-    description: input clock for the baud rate generator
-    items:
-      - const: core
+    minItems: 1
+    maxItems: 2
 
 if:
   properties:
@@ -51,17 +54,22 @@ if:
 then:
   properties:
     clocks:
-      contains:
-        items:
-          - description: controller register bus clock
-          - description: baud rate generator and delay control clock
+      minItems: 2
 
     clock-names:
-      minItems: 2
       items:
         - const: core
         - const: pclk
 
+else:
+  properties:
+    clocks:
+      maxItems: 1
+
+    clock-names:
+      items:
+        - const: core
+
 required:
   - compatible
   - reg
index 790311a..c8c1e91 100644 (file)
@@ -19,7 +19,7 @@ Required properties:
 
 SPI Controller nodes must be child of GENI based Qualcomm Universal
 Peripharal. Please refer GENI based QUP wrapper controller node bindings
-described in Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.txt.
+described in Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml.
 
 SPI slave nodes must be children of the SPI master node and conform to SPI bus
 binding as described in Documentation/devicetree/bindings/spi/spi-bus.txt.
index fcd25a0..727d045 100644 (file)
@@ -41,7 +41,7 @@ examples:
     #include <dt-bindings/interrupt-controller/arm-gic.h>
 
     // Example 1: SDM845 TSENS
-    soc: soc@0 {
+    soc: soc {
             #address-cells = <2>;
             #size-cells = <2>;
 
index b8515d3..3ec9cc8 100644 (file)
@@ -224,7 +224,7 @@ examples:
     #include <dt-bindings/thermal/thermal.h>
 
     // Example 1: SDM845 TSENS
-    soc: soc@0 {
+    soc {
             #address-cells = <2>;
             #size-cells = <2>;
 
index 25b9209..ea14de8 100644 (file)
@@ -35,7 +35,7 @@ examples:
     #include <dt-bindings/soc/ti,sci_pm_domain.h>
     vtm: thermal@42050000 {
         compatible = "ti,am654-vtm";
-        reg = <0x0 0x42050000 0x0 0x25c>;
+        reg = <0x42050000 0x25c>;
         power-domains = <&k3_pds 80 TI_SCI_PD_EXCLUSIVE>;
         #thermal-sensor-cells = <1>;
     };
index 15cfec0..f5c7e99 100644 (file)
@@ -8,7 +8,7 @@ regs is accessed by cpu co-processor 4 registers with mtcr/mfcr.
  - PTIM_CTLR "cr<0, 14>" Control reg to start reset timer.
  - PTIM_TSR  "cr<1, 14>" Interrupt cleanup status reg.
  - PTIM_CCVR "cr<3, 14>" Current counter value reg.
- - PTIM_LVR  "cr<6, 14>" Window value reg to triger next event.
+ - PTIM_LVR  "cr<6, 14>" Window value reg to trigger next event.
 
 ==============================
 timer node bindings definition
index e4e83d3..8b019ac 100644 (file)
@@ -127,8 +127,8 @@ examples:
                 #address-cells = <1>;
                 #size-cells = <0>;
 
-                string@0409 {
-                        reg = <0x0409>;
+                string@409 {
+                        reg = <0x409>;
                         manufacturer = "ASPEED";
                         product = "USB Virtual Hub";
                         serial-number = "0000";
index 220cf46..8c74a99 100644 (file)
@@ -1,4 +1,4 @@
-:orphan:
+.. SPDX-License-Identifier: GPL-2.0
 
 Writing DeviceTree Bindings in json-schema
 ==========================================
@@ -124,9 +124,12 @@ dtc must also be built with YAML output support enabled. This requires that
 libyaml and its headers be installed on the host system. For some distributions
 that involves installing the development package, such as:
 
-Debian:
+Debian::
+
   apt-get install libyaml-dev
-Fedora:
+
+Fedora::
+
   dnf -y install libyaml-devel
 
 Running checks
index 6e71f67..bc7e1fc 100644 (file)
@@ -451,7 +451,7 @@ The bridge driver also has some helper functions it can use:
                                        "module_foo", "chipid", 0x36, NULL);
 
 This loads the given module (can be ``NULL`` if no module needs to be loaded)
-and calls :c:func:`i2c_new_device` with the given ``i2c_adapter`` and
+and calls :c:func:`i2c_new_client_device` with the given ``i2c_adapter`` and
 chip/address arguments. If all goes well, then it registers the subdev with
 the v4l2_device.
 
index a15192e..664838a 100644 (file)
@@ -23,6 +23,7 @@ PTP hardware clock infrastructure for Linux
   + Ancillary clock features
     - Time stamp external events
     - Period output signals configurable from user space
+    - Low Pass Filter (LPF) access from user space
     - Synchronization of the Linux system time via the PPS subsystem
 
 PTP hardware clock kernel API
@@ -94,3 +95,14 @@ Supported hardware
 
      - Auxiliary Slave/Master Mode Snapshot (optional interrupt)
      - Target Time (optional interrupt)
+
+   * Renesas (IDT) ClockMatrixâ„¢
+
+     - Up to 4 independent PHC channels
+     - Integrated low pass filter (LPF), access via .adjPhase (compliant to ITU-T G.8273.2)
+     - Programmable output periodic signals
+     - Programmable inputs can time stamp external triggers
+     - Driver and/or hardware configuration through firmware (idtcm.bin)
+          - LPF settings (bandwidth, phase limiting, automatic holdover, physical layer assist (per ITU-T G.8273.2))
+          - Programmable output PTP clocks, any frequency up to 1GHz (to other PHY/MAC time stampers, refclk to ASSPs/SoCs/FPGAs)
+          - Lock to GNSS input, automatic switching between GNSS and user-space PHC control (optional)
index 8e26707..8fdb78f 100644 (file)
@@ -25,7 +25,7 @@ size when creating the filesystem.
 Currently 3 filesystems support DAX: ext2, ext4 and xfs.  Enabling DAX on them
 is different.
 
-Enabling DAX on ext4 and ext2
+Enabling DAX on ext2
 -----------------------------
 
 When mounting the filesystem, use the "-o dax" option on the command line or
@@ -33,8 +33,8 @@ add 'dax' to the options in /etc/fstab.  This works to enable DAX on all files
 within the filesystem.  It is equivalent to the '-o dax=always' behavior below.
 
 
-Enabling DAX on xfs
--------------------
+Enabling DAX on xfs and ext4
+----------------------------
 
 Summary
 -------
index 3e4c0ee..e99ff3f 100644 (file)
@@ -39,3 +39,6 @@ is encrypted as well as the data itself.
 
 Verity files cannot have blocks allocated past the end of the verity
 metadata.
+
+Verity and DAX are not compatible and attempts to set both of these flags
+on a file will fail.
index 660dbaf..fcda5d6 100644 (file)
@@ -560,8 +560,8 @@ When the NFS export feature is enabled, all directory index entries are
 verified on mount time to check that upper file handles are not stale.
 This verification may cause significant overhead in some cases.
 
-Note: the mount options index=off,nfs_export=on are conflicting and will
-result in an error.
+Note: the mount options index=off,nfs_export=on are conflicting for a
+read-write mount and will result in an error.
 
 
 Testsuite
index 4cc7432..1711235 100644 (file)
@@ -197,11 +197,14 @@ pp_power_profile_mode
 .. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
    :doc: pp_power_profile_mode
 
-busy_percent
-~~~~~~~~~~~~
+*_busy_percent
+~~~~~~~~~~~~~~
 
 .. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
-   :doc: busy_percent
+   :doc: gpu_busy_percent
+
+.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+   :doc: mem_busy_percent
 
 GPU Product Information
 =======================
index 0b8cd83..38d951f 100644 (file)
@@ -1,14 +1,26 @@
 ==============================
-Linux I2C slave eeprom backend
+Linux I2C slave EEPROM backend
 ==============================
 
-by Wolfram Sang <wsa@sang-engineering.com> in 2014-15
+by Wolfram Sang <wsa@sang-engineering.com> in 2014-20
 
-This is a proof-of-concept backend which acts like an EEPROM on the connected
-I2C bus. The memory contents can be modified from userspace via this file
-located in sysfs::
+This backend simulates an EEPROM on the connected I2C bus. Its memory contents
+can be accessed from userspace via this file located in sysfs::
 
        /sys/bus/i2c/devices/<device-directory>/slave-eeprom
 
+The following types are available: 24c02, 24c32, 24c64, and 24c512. Read-only
+variants are also supported. The name needed for instantiating has the form
+'slave-<type>[ro]'. Examples follow:
+
+24c02, read/write, address 0x64:
+  # echo slave-24c02 0x1064 > /sys/bus/i2c/devices/i2c-1/new_device
+
+24c512, read-only, address 0x42:
+  # echo slave-24c512ro 0x1042 > /sys/bus/i2c/devices/i2c-1/new_device
+
+You can also preload data during boot if a device-property named
+'firmware-name' contains a valid filename (DT or ACPI only).
+
 As of 2015, Linux doesn't support poll on binary sysfs files, so there is no
 notification when another master changed the content.
index c2e2963..64689d1 100644 (file)
@@ -57,7 +57,7 @@ SMBus Quick Command
 
 This sends a single bit to the device, at the place of the Rd/Wr bit::
 
-  A Addr Rd/Wr [A] P
+  S Addr Rd/Wr [A] P
 
 Functionality flag: I2C_FUNC_SMBUS_QUICK
 
index a45cccf..85ccc87 100644 (file)
@@ -182,7 +182,8 @@ module 8123.ko, which is built from the following files::
        8123_pci.c
        8123_bin.o_shipped      <= Binary blob
 
---- 3.1 Shared Makefile
+3.1 Shared Makefile
+-------------------
 
        An external module always includes a wrapper makefile that
        supports building the module using "make" with no arguments.
@@ -470,9 +471,9 @@ build.
 
        The syntax of the Module.symvers file is::
 
-       <CRC>       <Symbol>         <Module>                         <Export Type>     <Namespace>
+               <CRC>       <Symbol>         <Module>                         <Export Type>     <Namespace>
 
-       0xe1cc2a05  usb_stor_suspend drivers/usb/storage/usb-storage  EXPORT_SYMBOL_GPL USB_STORAGE
+               0xe1cc2a05  usb_stor_suspend drivers/usb/storage/usb-storage  EXPORT_SYMBOL_GPL USB_STORAGE
 
        The fields are separated by tabs and values may be empty (e.g.
        if no namespace is defined for an exported symbol).
index 5033938..3b25655 100644 (file)
@@ -101,7 +101,7 @@ Structure randomisation
 
 If you enable ``CONFIG_GCC_PLUGIN_RANDSTRUCT``, you will need to
 pre-generate the random seed in
-``scripts/gcc-plgins/randomize_layout_seed.h`` so the same value
+``scripts/gcc-plugins/randomize_layout_seed.h`` so the same value
 is used in rebuilds.
 
 Debug info conflicts
index c5a646b..2b75760 100644 (file)
@@ -68,4 +68,4 @@ and frameworks can be controlled from the same registers, all of these
 drivers access their registers through the same regmap.
 
 For more information regarding the devicetree bindings of the TCU drivers,
-have a look at Documentation/devicetree/bindings/timer/ingenic,tcu.txt.
+have a look at Documentation/devicetree/bindings/timer/ingenic,tcu.yaml.
index e93d982..82fce60 100644 (file)
@@ -434,7 +434,7 @@ can set up your network then:
        ifconfig arc0 insight
        route add insight arc0
        route add freedom arc0  /* I would use the subnet here (like I said
-                                       to to in "single protocol" above),
+                                       to in "single protocol" above),
                                        but the rest of the subnet
                                        unfortunately lies across the PPP
                                        link on freedom, which confuses
index 824afd7..f060cfb 100644 (file)
@@ -6,7 +6,7 @@ AX.25
 
 To use the amateur radio protocols within Linux you will need to get a
 suitable copy of the AX.25 Utilities. More detailed information about
-AX.25, NET/ROM and ROSE, associated programs and and utilities can be
+AX.25, NET/ROM and ROSE, associated programs and utilities can be
 found on http://www.linux-ax25.org.
 
 There is an active mailing list for discussing Linux amateur radio matters
index 465a8b2..ff40656 100644 (file)
@@ -26,7 +26,7 @@ Usage
 
 1) Device creation & deletion
 
-    a) ip link add dev bareudp0 type bareudp dstport 6635 ethertype 0x8847.
+    a) ip link add dev bareudp0 type bareudp dstport 6635 ethertype mpls_uc
 
        This creates a bareudp tunnel device which tunnels L3 traffic with ethertype
        0x8847 (MPLS traffic). The destination port of the UDP header will be set to
@@ -34,14 +34,21 @@ Usage
 
     b) ip link delete bareudp0
 
-2) Device creation with multiple proto mode enabled
+2) Device creation with multiproto mode enabled
 
-There are two ways to create a bareudp device for MPLS & IP with multiproto mode
-enabled.
+The multiproto mode allows bareudp tunnels to handle several protocols of the
+same family. It is currently only available for IP and MPLS. This mode has to
+be enabled explicitly with the "multiproto" flag.
 
-    a) ip link add dev  bareudp0 type bareudp dstport 6635 ethertype 0x8847 multiproto
+    a) ip link add dev bareudp0 type bareudp dstport 6635 ethertype ipv4 multiproto
 
-    b) ip link add dev  bareudp0 type bareudp dstport 6635 ethertype mpls
+       For an IPv4 tunnel the multiproto mode allows the tunnel to also handle
+       IPv6.
+
+    b) ip link add dev bareudp0 type bareudp dstport 6635 ethertype mpls_uc multiproto
+
+       For MPLS, the multiproto mode allows the tunnel to handle both unicast
+       and multicast MPLS packets.
 
 3) Device Usage
 
index 4cef88d..638ac1e 100644 (file)
@@ -144,7 +144,7 @@ UCAN_COMMAND_SET_BITTIMING
 
 *Host2Dev; mandatory*
 
-Setup bittiming by sending the the structure
+Setup bittiming by sending the structure
 ``ucan_ctl_payload_t.cmd_set_bittiming`` (see ``struct bittiming`` for
 details)
 
@@ -232,7 +232,7 @@ UCAN_IN_TX_COMPLETE
   zero
 
 The CAN device has sent a message to the CAN bus. It answers with a
-list of of tuples <echo-ids, flags>.
+list of tuples <echo-ids, flags>.
 
 The echo-id identifies the frame from (echos the id from a previous
 UCAN_OUT_TX message). The flag indicates the result of the
index 563d56c..a8d15dd 100644 (file)
@@ -95,7 +95,7 @@ Ethernet switch.
 Networking stack hooks
 ----------------------
 
-When a master netdev is used with DSA, a small hook is placed in in the
+When a master netdev is used with DSA, a small hook is placed in the
 networking stack is in order to have the DSA subsystem process the Ethernet
 switch specific tagging protocol. DSA accomplishes this by registering a
 specific (and fake) Ethernet type (later becoming ``skb->protocol``) with the
index 36ca823..6f4bf84 100644 (file)
@@ -30,8 +30,8 @@ Socket API
 
 The address family, socket addresses etc. are defined in the
 include/net/af_ieee802154.h header or in the special header
-in the userspace package (see either http://wpan.cakelab.org/ or the
-git tree at https://github.com/linux-wpan/wpan-tools).
+in the userspace package (see either https://linux-wpan.org/wpan-tools.html
+or the git tree at https://github.com/linux-wpan/wpan-tools).
 
 6LoWPAN Linux implementation
 ============================
index b72f89d..837d51f 100644 (file)
@@ -741,7 +741,7 @@ tcp_fastopen - INTEGER
 
        Default: 0x1
 
-       Note that that additional client or server features are only
+       Note that additional client or server features are only
        effective if the basic support (0x1 and 0x2) are enabled respectively.
 
 tcp_fastopen_blackhole_timeout_sec - INTEGER
index be36c46..2afccc6 100644 (file)
@@ -114,7 +114,7 @@ drop_entry - INTEGER
        modes (when there is no enough available memory, the strategy
        is enabled and the variable is automatically set to 2,
        otherwise the strategy is disabled and the variable is set to
-       1), and 3 means that that the strategy is always enabled.
+       1), and 3 means that the strategy is always enabled.
 
 drop_packet - INTEGER
        - 0  - disabled (default)
index 68552b9..39c2249 100644 (file)
@@ -186,7 +186,7 @@ About the AF_RXRPC driver:
      time [tunable] after the last connection using it discarded, in case a new
      connection is made that could use it.
 
- (#) A client-side connection is only shared between calls if they have have
+ (#) A client-side connection is only shared between calls if they have
      the same key struct describing their security (and assuming the calls
      would otherwise share the connection).  Non-secured calls would also be
      able to share connections with each other.
index 3493631..48fcf12 100644 (file)
@@ -220,13 +220,51 @@ from the LPAR memory.
 **H_SCM_HEALTH**
 
 | Input: drcIndex
-| Out: *health-bitmap, health-bit-valid-bitmap*
+| Out: *health-bitmap (r4), health-bit-valid-bitmap (r5)*
 | Return Value: *H_Success, H_Parameter, H_Hardware*
 
 Given a DRC Index return the info on predictive failure and overall health of
-the NVDIMM. The asserted bits in the health-bitmap indicate a single predictive
-failure and health-bit-valid-bitmap indicate which bits in health-bitmap are
-valid.
+the PMEM device. The asserted bits in the health-bitmap indicate one or more states
+(described in table below) of the PMEM device and health-bit-valid-bitmap indicate
+which bits in health-bitmap are valid. The bits are reported in
+reverse bit ordering for example a value of 0xC400000000000000
+indicates bits 0, 1, and 5 are valid.
+
+Health Bitmap Flags:
+
++------+-----------------------------------------------------------------------+
+|  Bit |               Definition                                              |
++======+=======================================================================+
+|  00  | PMEM device is unable to persist memory contents.                     |
+|      | If the system is powered down, nothing will be saved.                 |
++------+-----------------------------------------------------------------------+
+|  01  | PMEM device failed to persist memory contents. Either contents were   |
+|      | not saved successfully on power down or were not restored properly on |
+|      | power up.                                                             |
++------+-----------------------------------------------------------------------+
+|  02  | PMEM device contents are persisted from previous IPL. The data from   |
+|      | the last boot were successfully restored.                             |
++------+-----------------------------------------------------------------------+
+|  03  | PMEM device contents are not persisted from previous IPL. There was no|
+|      | data to restore from the last boot.                                   |
++------+-----------------------------------------------------------------------+
+|  04  | PMEM device memory life remaining is critically low                   |
++------+-----------------------------------------------------------------------+
+|  05  | PMEM device will be garded off next IPL due to failure                |
++------+-----------------------------------------------------------------------+
+|  06  | PMEM device contents cannot persist due to current platform health    |
+|      | status. A hardware failure may prevent data from being saved or       |
+|      | restored.                                                             |
++------+-----------------------------------------------------------------------+
+|  07  | PMEM device is unable to persist memory contents in certain conditions|
++------+-----------------------------------------------------------------------+
+|  08  | PMEM device is encrypted                                              |
++------+-----------------------------------------------------------------------+
+|  09  | PMEM device has successfully completed a requested erase or secure    |
+|      | erase procedure.                                                      |
++------+-----------------------------------------------------------------------+
+|10:63 | Reserved / Unused                                                     |
++------+-----------------------------------------------------------------------+
 
 **H_SCM_PERFORMANCE_STATS**
 
index 1217c2f..788dc83 100644 (file)
@@ -213,7 +213,7 @@ request buffers are not in memory. The operating system handles the fault by
 updating CSB with the following data:
 
        csb.flags = CSB_V;
-       csb.cc = CSB_CC_TRANSLATION;
+       csb.cc = CSB_CC_FAULT_ADDRESS;
        csb.ce = CSB_CE_TERMINATION;
        csb.address = fault_address;
 
index 5cfb54c..8f68e72 100644 (file)
@@ -29,7 +29,7 @@ you probably needn't concern yourself with pcmciautils.
 ====================== ===============  ========================================
         Program        Minimal version       Command to check the version
 ====================== ===============  ========================================
-GNU C                  4.8              gcc --version
+GNU C                  4.9              gcc --version
 GNU make               3.81             make --version
 binutils               2.23             ld -v
 flex                   2.5.35           flex --version
index 2657a55..1bee6f8 100644 (file)
@@ -319,6 +319,26 @@ If you are afraid to mix up your local variable names, you have another
 problem, which is called the function-growth-hormone-imbalance syndrome.
 See chapter 6 (Functions).
 
+For symbol names and documentation, avoid introducing new usage of
+'master / slave' (or 'slave' independent of 'master') and 'blacklist /
+whitelist'.
+
+Recommended replacements for 'master / slave' are:
+    '{primary,main} / {secondary,replica,subordinate}'
+    '{initiator,requester} / {target,responder}'
+    '{controller,host} / {device,worker,proxy}'
+    'leader / follower'
+    'director / performer'
+
+Recommended replacements for 'blacklist/whitelist' are:
+    'denylist / allowlist'
+    'blocklist / passlist'
+
+Exceptions for introducing new usage is to maintain a userspace ABI/API,
+or when updating code for an existing (as of 2020) hardware or protocol
+specification that mandates those terms. For new specifications
+translate specification usage of the terminology to the kernel coding
+standard where possible.
 
 5) Typedefs
 -----------
index bc8db7b..0bd405a 100644 (file)
@@ -16,18 +16,6 @@ Store Queue API
 .. kernel-doc:: arch/sh/kernel/cpu/sh4/sq.c
    :export:
 
-SH-5
-----
-
-TLB Interfaces
-~~~~~~~~~~~~~~
-
-.. kernel-doc:: arch/sh/mm/tlb-sh5.c
-   :internal:
-
-.. kernel-doc:: arch/sh/include/asm/tlb_64.h
-   :internal:
-
 Machine Specific Interfaces
 ===========================
 
index d0c50d7..0a8e236 100644 (file)
@@ -27,7 +27,7 @@ nitpick_ignore = [
     ("c:func", "copy_to_user"),
     ("c:func", "determine_valid_ioctls"),
     ("c:func", "ERR_PTR"),
-    ("c:func", "i2c_new_device"),
+    ("c:func", "i2c_new_client_device"),
     ("c:func", "ioctl"),
     ("c:func", "IS_ERR"),
     ("c:func", "KERNEL_VERSION"),
index 426f945..320788f 100644 (file)
@@ -4339,14 +4339,15 @@ Errors:
 #define KVM_STATE_VMX_PREEMPTION_TIMER_DEADLINE 0x00000001
 
   struct kvm_vmx_nested_state_hdr {
-       __u32 flags;
        __u64 vmxon_pa;
        __u64 vmcs12_pa;
-       __u64 preemption_timer_deadline;
 
        struct {
                __u16 flags;
        } smm;
+
+       __u32 flags;
+       __u64 preemption_timer_deadline;
   };
 
   struct kvm_vmx_nested_state_data {
index 68f21d4..e02479a 100644 (file)
@@ -1425,7 +1425,7 @@ F:        arch/arm*/include/asm/perf_event.h
 F:     arch/arm*/kernel/hw_breakpoint.c
 F:     arch/arm*/kernel/perf_*
 F:     arch/arm/oprofile/common.c
-F:     drivers/perf/*
+F:     drivers/perf/
 F:     include/linux/perf/arm_pmu.h
 
 ARM PORT
@@ -2929,6 +2929,7 @@ F:        include/uapi/linux/atm*
 
 ATMEL MACB ETHERNET DRIVER
 M:     Nicolas Ferre <nicolas.ferre@microchip.com>
+M:     Claudiu Beznea <claudiu.beznea@microchip.com>
 S:     Supported
 F:     drivers/net/ethernet/cadence/
 
@@ -3306,7 +3307,7 @@ X:        arch/riscv/net/bpf_jit_comp32.c
 
 BPF JIT for S390
 M:     Ilya Leoshkevich <iii@linux.ibm.com>
-M:     Heiko Carstens <heiko.carstens@de.ibm.com>
+M:     Heiko Carstens <hca@linux.ibm.com>
 M:     Vasily Gorbik <gor@linux.ibm.com>
 L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
@@ -3946,7 +3947,7 @@ L:        linux-crypto@vger.kernel.org
 S:     Supported
 F:     drivers/char/hw_random/cctrng.c
 F:     drivers/char/hw_random/cctrng.h
-F:     Documentation/devicetree/bindings/rng/arm-cctrng.txt
+F:     Documentation/devicetree/bindings/rng/arm-cctrng.yaml
 W:     https://developer.arm.com/products/system-ip/trustzone-cryptocell/cryptocell-700-family
 
 CEC FRAMEWORK
@@ -5021,7 +5022,6 @@ F:        drivers/mfd/da91??-*.c
 F:     drivers/pinctrl/pinctrl-da90??.c
 F:     drivers/power/supply/da9052-battery.c
 F:     drivers/power/supply/da91??-*.c
-F:     drivers/regulator/da903x.c
 F:     drivers/regulator/da9???-regulator.[ch]
 F:     drivers/regulator/slg51000-regulator.[ch]
 F:     drivers/rtc/rtc-da90??.c
@@ -5111,7 +5111,7 @@ M:        Vinod Koul <vkoul@kernel.org>
 L:     dmaengine@vger.kernel.org
 S:     Maintained
 Q:     https://patchwork.kernel.org/project/linux-dmaengine/list/
-T:     git git://git.infradead.org/users/vkoul/slave-dma.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine.git
 F:     Documentation/devicetree/bindings/dma/
 F:     Documentation/driver-api/dmaengine/
 F:     drivers/dma/
@@ -5490,7 +5490,7 @@ F:        include/uapi/drm/r128_drm.h
 DRM DRIVER FOR RAYDIUM RM67191 PANELS
 M:     Robert Chiras <robert.chiras@nxp.com>
 S:     Maintained
-F:     Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
+F:     Documentation/devicetree/bindings/display/panel/raydium,rm67191.yaml
 F:     drivers/gpu/drm/panel/panel-raydium-rm67191.c
 
 DRM DRIVER FOR ROCKTECH JH057N00900 PANELS
@@ -6956,6 +6956,7 @@ M:        Timur Tabi <timur@kernel.org>
 M:     Nicolin Chen <nicoleotsuka@gmail.com>
 M:     Xiubo Li <Xiubo.Lee@gmail.com>
 R:     Fabio Estevam <festevam@gmail.com>
+R:     Shengjiu Wang <shengjiu.wang@gmail.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 L:     linuxppc-dev@lists.ozlabs.org
 S:     Maintained
@@ -8333,7 +8334,7 @@ M:        Alexander Aring <alex.aring@gmail.com>
 M:     Stefan Schmidt <stefan@datenfreihafen.org>
 L:     linux-wpan@vger.kernel.org
 S:     Maintained
-W:     http://wpan.cakelab.org/
+W:     https://linux-wpan.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sschmidt/wpan.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sschmidt/wpan-next.git
 F:     Documentation/networking/ieee802154.rst
@@ -9305,6 +9306,17 @@ F:       Documentation/kbuild/kconfig*
 F:     scripts/Kconfig.include
 F:     scripts/kconfig/
 
+KCOV
+R:     Dmitry Vyukov <dvyukov@google.com>
+R:     Andrey Konovalov <andreyknvl@google.com>
+L:     kasan-dev@googlegroups.com
+S:     Maintained
+F:     Documentation/dev-tools/kcov.rst
+F:     include/linux/kcov.h
+F:     include/uapi/linux/kcov.h
+F:     kernel/kcov.c
+F:     scripts/Makefile.kcov
+
 KCSAN
 M:     Marco Elver <elver@google.com>
 R:     Dmitry Vyukov <dvyukov@google.com>
@@ -10808,7 +10820,7 @@ F:      Documentation/devicetree/bindings/dma/mtk-*
 F:     drivers/dma/mediatek/
 
 MEDIATEK ETHERNET DRIVER
-M:     Felix Fietkau <nbd@openwrt.org>
+M:     Felix Fietkau <nbd@nbd.name>
 M:     John Crispin <john@phrozen.org>
 M:     Sean Wang <sean.wang@mediatek.com>
 M:     Mark Lee <Mark-MC.Lee@mediatek.com>
@@ -11240,7 +11252,7 @@ S:      Maintained
 F:     drivers/crypto/atmel-ecc.*
 
 MICROCHIP I2C DRIVER
-M:     Ludovic Desroches <ludovic.desroches@microchip.com>
+M:     Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
 L:     linux-i2c@vger.kernel.org
 S:     Supported
 F:     drivers/i2c/busses/i2c-at91-*.c
@@ -11333,17 +11345,17 @@ F:    drivers/iio/adc/at91-sama5d2_adc.c
 F:     include/dt-bindings/iio/adc/at91-sama5d2_adc.h
 
 MICROCHIP SAMA5D2-COMPATIBLE SHUTDOWN CONTROLLER
-M:     Nicolas Ferre <nicolas.ferre@microchip.com>
+M:     Claudiu Beznea <claudiu.beznea@microchip.com>
 S:     Supported
 F:     drivers/power/reset/at91-sama5d2_shdwc.c
 
 MICROCHIP SPI DRIVER
-M:     Nicolas Ferre <nicolas.ferre@microchip.com>
+M:     Tudor Ambarus <tudor.ambarus@microchip.com>
 S:     Supported
 F:     drivers/spi/spi-atmel.*
 
 MICROCHIP SSC DRIVER
-M:     Nicolas Ferre <nicolas.ferre@microchip.com>
+M:     Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
 F:     drivers/misc/atmel-ssc.c
@@ -11369,14 +11381,6 @@ L:     dmaengine@vger.kernel.org
 S:     Supported
 F:     drivers/dma/at_xdmac.c
 
-MICROSEMI ETHERNET SWITCH DRIVER
-M:     Alexandre Belloni <alexandre.belloni@bootlin.com>
-M:     Microchip Linux Driver Support <UNGLinuxDriver@microchip.com>
-L:     netdev@vger.kernel.org
-S:     Supported
-F:     drivers/net/ethernet/mscc/
-F:     include/soc/mscc/ocelot*
-
 MICROSEMI MIPS SOCS
 M:     Alexandre Belloni <alexandre.belloni@bootlin.com>
 M:     Microchip Linux Driver Support <UNGLinuxDriver@microchip.com>
@@ -12335,6 +12339,18 @@ M:     Peter Zijlstra <peterz@infradead.org>
 S:     Supported
 F:     tools/objtool/
 
+OCELOT ETHERNET SWITCH DRIVER
+M:     Microchip Linux Driver Support <UNGLinuxDriver@microchip.com>
+M:     Vladimir Oltean <vladimir.oltean@nxp.com>
+M:     Claudiu Manoil <claudiu.manoil@nxp.com>
+M:     Alexandre Belloni <alexandre.belloni@bootlin.com>
+L:     netdev@vger.kernel.org
+S:     Supported
+F:     drivers/net/dsa/ocelot/*
+F:     drivers/net/ethernet/mscc/
+F:     include/soc/mscc/ocelot*
+F:     net/dsa/tag_ocelot.c
+
 OCXL (Open Coherent Accelerator Processor Interface OpenCAPI) DRIVER
 M:     Frederic Barrat <fbarrat@linux.ibm.com>
 M:     Andrew Donnellan <ajd@linux.ibm.com>
@@ -12691,13 +12707,13 @@ F:    arch/mips/boot/dts/ralink/omega2p.dts
 
 OP-TEE DRIVER
 M:     Jens Wiklander <jens.wiklander@linaro.org>
-L:     tee-dev@lists.linaro.org
+L:     op-tee@lists.trustedfirmware.org
 S:     Maintained
 F:     drivers/tee/optee/
 
 OP-TEE RANDOM NUMBER GENERATOR (RNG) DRIVER
 M:     Sumit Garg <sumit.garg@linaro.org>
-L:     tee-dev@lists.linaro.org
+L:     op-tee@lists.trustedfirmware.org
 S:     Maintained
 F:     drivers/char/hw_random/optee-rng.c
 
@@ -14172,7 +14188,8 @@ F:      Documentation/devicetree/bindings/net/qcom,ethqos.txt
 F:     drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
 
 QUALCOMM GENERIC INTERFACE I2C DRIVER
-M:     Alok Chauhan <alokc@codeaurora.org>
+M:     Akash Asthana <akashast@codeaurora.org>
+M:     Mukesh Savaliya <msavaliy@codeaurora.org>
 L:     linux-i2c@vger.kernel.org
 L:     linux-arm-msm@vger.kernel.org
 S:     Supported
@@ -14192,6 +14209,15 @@ L:     dmaengine@vger.kernel.org
 S:     Supported
 F:     drivers/dma/qcom/hidma*
 
+QUALCOMM I2C CCI DRIVER
+M:     Loic Poulain <loic.poulain@linaro.org>
+M:     Robert Foss <robert.foss@linaro.org>
+L:     linux-i2c@vger.kernel.org
+L:     linux-arm-msm@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/i2c/i2c-qcom-cci.txt
+F:     drivers/i2c/busses/i2c-qcom-cci.c
+
 QUALCOMM IOMMU
 M:     Rob Clark <robdclark@gmail.com>
 L:     iommu@lists.linux-foundation.org
@@ -14534,7 +14560,7 @@ F:      Documentation/devicetree/bindings/i2c/renesas,iic-emev2.txt
 F:     drivers/i2c/busses/i2c-emev2.c
 
 RENESAS ETHERNET DRIVERS
-R:     Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+R:     Sergei Shtylyov <sergei.shtylyov@gmail.com>
 L:     netdev@vger.kernel.org
 L:     linux-renesas-soc@vger.kernel.org
 F:     Documentation/devicetree/bindings/net/renesas,*.txt
@@ -14561,8 +14587,8 @@ RENESAS R-CAR THERMAL DRIVERS
 M:     Niklas Söderlund <niklas.soderlund@ragnatech.se>
 L:     linux-renesas-soc@vger.kernel.org
 S:     Supported
-F:     Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt
-F:     Documentation/devicetree/bindings/thermal/rcar-thermal.txt
+F:     Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.yaml
+F:     Documentation/devicetree/bindings/thermal/rcar-thermal.yaml
 F:     drivers/thermal/rcar_gen3_thermal.c
 F:     drivers/thermal/rcar_thermal.c
 
@@ -14818,7 +14844,7 @@ S:      Maintained
 F:     drivers/video/fbdev/savage/
 
 S390
-M:     Heiko Carstens <heiko.carstens@de.ibm.com>
+M:     Heiko Carstens <hca@linux.ibm.com>
 M:     Vasily Gorbik <gor@linux.ibm.com>
 M:     Christian Borntraeger <borntraeger@de.ibm.com>
 L:     linux-s390@vger.kernel.org
@@ -14849,7 +14875,8 @@ F:      drivers/s390/block/dasd*
 F:     include/linux/dasd_mod.h
 
 S390 IOMMU (PCI)
-M:     Gerald Schaefer <gerald.schaefer@de.ibm.com>
+M:     Matthew Rosato <mjrosato@linux.ibm.com>
+M:     Gerald Schaefer <gerald.schaefer@linux.ibm.com>
 L:     linux-s390@vger.kernel.org
 S:     Supported
 W:     http://www.ibm.com/developerworks/linux/linux390/
@@ -14877,7 +14904,7 @@ F:      drivers/s390/net/
 
 S390 PCI SUBSYSTEM
 M:     Niklas Schnelle <schnelle@linux.ibm.com>
-M:     Gerald Schaefer <gerald.schaefer@de.ibm.com>
+M:     Gerald Schaefer <gerald.schaefer@linux.ibm.com>
 L:     linux-s390@vger.kernel.org
 S:     Supported
 W:     http://www.ibm.com/developerworks/linux/linux390/
@@ -16045,8 +16072,10 @@ SPARSE CHECKER
 M:     "Luc Van Oostenryck" <luc.vanoostenryck@gmail.com>
 L:     linux-sparse@vger.kernel.org
 S:     Maintained
-W:     https://sparse.wiki.kernel.org/
+W:     https://sparse.docs.kernel.org/
 T:     git git://git.kernel.org/pub/scm/devel/sparse/sparse.git
+Q:     https://patchwork.kernel.org/project/linux-sparse/list/
+B:     https://bugzilla.kernel.org/enter_bug.cgi?component=Sparse&product=Tools
 F:     include/linux/compiler.h
 
 SPEAR CLOCK FRAMEWORK SUPPORT
@@ -16759,7 +16788,7 @@ F:      include/media/i2c/tw9910.h
 
 TEE SUBSYSTEM
 M:     Jens Wiklander <jens.wiklander@linaro.org>
-L:     tee-dev@lists.linaro.org
+L:     op-tee@lists.trustedfirmware.org
 S:     Maintained
 F:     Documentation/tee.txt
 F:     drivers/tee/
@@ -17498,7 +17527,7 @@ F:      Documentation/admin-guide/ufs.rst
 F:     fs/ufs/
 
 UHID USERSPACE HID IO DRIVER
-M:     David Herrmann <dh.herrmann@googlemail.com>
+M:     David Rheinsberg <david.rheinsberg@gmail.com>
 L:     linux-input@vger.kernel.org
 S:     Maintained
 F:     drivers/hid/uhid.c
@@ -18254,14 +18283,6 @@ S:     Maintained
 F:     drivers/input/serio/userio.c
 F:     include/uapi/linux/userio.h
 
-VITESSE FELIX ETHERNET SWITCH DRIVER
-M:     Vladimir Oltean <vladimir.oltean@nxp.com>
-M:     Claudiu Manoil <claudiu.manoil@nxp.com>
-L:     netdev@vger.kernel.org
-S:     Maintained
-F:     drivers/net/dsa/ocelot/*
-F:     net/dsa/tag_ocelot.c
-
 VIVID VIRTUAL VIDEO DRIVER
 M:     Hans Verkuil <hverkuil@xs4all.nl>
 L:     linux-media@vger.kernel.org
@@ -18465,7 +18486,7 @@ S:      Maintained
 F:     drivers/rtc/rtc-sd3078.c
 
 WIIMOTE HID DRIVER
-M:     David Herrmann <dh.herrmann@googlemail.com>
+M:     David Rheinsberg <david.rheinsberg@gmail.com>
 L:     linux-input@vger.kernel.org
 S:     Maintained
 F:     drivers/hid/hid-wiimote*
index ae5d822..229e67f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 8
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc7
 NAME = Kleptomaniac Octopus
 
 # *DOCUMENTATION*
@@ -567,7 +567,7 @@ ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
 ifneq ($(CROSS_COMPILE),)
 CLANG_FLAGS    += --target=$(notdir $(CROSS_COMPILE:%-=%))
 GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)elfedit))
-CLANG_FLAGS    += --prefix=$(GCC_TOOLCHAIN_DIR)
+CLANG_FLAGS    += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
 GCC_TOOLCHAIN  := $(realpath $(GCC_TOOLCHAIN_DIR)/..)
 endif
 ifneq ($(GCC_TOOLCHAIN),)
@@ -828,7 +828,7 @@ endif
 
 ifdef CONFIG_DEBUG_INFO_COMPRESSED
 DEBUG_CFLAGS   += -gz=zlib
-KBUILD_AFLAGS  += -Wa,--compress-debug-sections=zlib
+KBUILD_AFLAGS  += -gz=zlib
 KBUILD_LDFLAGS += --compress-debug-sections=zlib
 endif
 
@@ -970,8 +970,8 @@ LDFLAGS_vmlinux     += --pack-dyn-relocs=relr
 endif
 
 # Align the bit size of userspace programs with the kernel
-KBUILD_USERCFLAGS  += $(filter -m32 -m64, $(KBUILD_CFLAGS))
-KBUILD_USERLDFLAGS += $(filter -m32 -m64, $(KBUILD_CFLAGS))
+KBUILD_USERCFLAGS  += $(filter -m32 -m64 --target=%, $(KBUILD_CFLAGS))
+KBUILD_USERLDFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CFLAGS))
 
 # make the checker run with the right architecture
 CHECKFLAGS += --arch=$(ARCH)
@@ -1336,16 +1336,6 @@ dt_binding_check: scripts_dtc
 # ---------------------------------------------------------------------------
 # Modules
 
-# install modules.builtin regardless of CONFIG_MODULES
-PHONY += _builtin_inst_
-_builtin_inst_:
-       @mkdir -p $(MODLIB)/
-       @cp -f modules.builtin $(MODLIB)/
-       @cp -f $(objtree)/modules.builtin.modinfo $(MODLIB)/
-
-PHONY += install
-install: _builtin_inst_
-
 ifdef CONFIG_MODULES
 
 # By default, build modules as well
@@ -1389,7 +1379,7 @@ PHONY += modules_install
 modules_install: _modinst_ _modinst_post
 
 PHONY += _modinst_
-_modinst_: _builtin_inst_
+_modinst_:
        @rm -rf $(MODLIB)/kernel
        @rm -f $(MODLIB)/source
        @mkdir -p $(MODLIB)/kernel
@@ -1399,6 +1389,8 @@ _modinst_: _builtin_inst_
                ln -s $(CURDIR) $(MODLIB)/build ; \
        fi
        @sed 's:^:kernel/:' modules.order > $(MODLIB)/modules.order
+       @cp -f modules.builtin $(MODLIB)/
+       @cp -f $(objtree)/modules.builtin.modinfo $(MODLIB)/
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
 
 # This depmod is only for convenience to give the initial
@@ -1762,7 +1754,7 @@ PHONY += descend $(build-dirs)
 descend: $(build-dirs)
 $(build-dirs): prepare
        $(Q)$(MAKE) $(build)=$@ \
-       single-build=$(if $(filter-out $@/, $(filter $@/%, $(single-no-ko))),1) \
+       single-build=$(if $(filter-out $@/, $(filter $@/%, $(KBUILD_SINGLE_TARGETS))),1) \
        need-builtin=1 need-modorder=1
 
 clean-dirs := $(addprefix _clean_, $(clean-dirs))
index fddc700..197896c 100644 (file)
@@ -170,6 +170,15 @@ config ARC_CPU_HS
 
 endchoice
 
+config ARC_TUNE_MCPU
+       string "Override default -mcpu compiler flag"
+       default ""
+       help
+         Override default -mcpu=xxx compiler flag (which is set depending on
+         the ISA version) with the specified value.
+         NOTE: If specified flag isn't supported by current compiler the
+         ISA default value will be used as a fallback.
+
 config CPU_BIG_ENDIAN
        bool "Enable Big Endian Mode"
        help
@@ -465,6 +474,12 @@ config ARC_IRQ_NO_AUTOSAVE
          This is programmable and can be optionally disabled in which case
          software INTERRUPT_PROLOGUE/EPILGUE do the needed work
 
+config ARC_LPB_DISABLE
+       bool "Disable loop buffer (LPB)"
+       help
+         On HS cores, loop buffer (LPB) is programmable in runtime and can
+         be optionally disabled.
+
 endif # ISA_ARCV2
 
 endmenu   # "ARC CPU Configuration"
index 20e9ab6..d00f8b8 100644 (file)
@@ -10,8 +10,25 @@ CROSS_COMPILE := $(call cc-cross-prefix, arc-linux- arceb-linux-)
 endif
 
 cflags-y       += -fno-common -pipe -fno-builtin -mmedium-calls -D__linux__
-cflags-$(CONFIG_ISA_ARCOMPACT) += -mA7
-cflags-$(CONFIG_ISA_ARCV2)     += -mcpu=hs38
+
+tune-mcpu-def-$(CONFIG_ISA_ARCOMPACT)  := -mcpu=arc700
+tune-mcpu-def-$(CONFIG_ISA_ARCV2)      := -mcpu=hs38
+
+ifeq ($(CONFIG_ARC_TUNE_MCPU),"")
+cflags-y                               += $(tune-mcpu-def-y)
+else
+tune-mcpu                              := $(shell echo $(CONFIG_ARC_TUNE_MCPU))
+tune-mcpu-ok                           := $(call cc-option-yn, $(tune-mcpu))
+ifeq ($(tune-mcpu-ok),y)
+cflags-y                               += $(tune-mcpu)
+else
+# The flag provided by 'CONFIG_ARC_TUNE_MCPU' option isn't known by this compiler
+# (probably the compiler is too old). Use ISA default mcpu flag instead as a safe option.
+$(warning ** WARNING ** CONFIG_ARC_TUNE_MCPU flag '$(tune-mcpu)' is unknown, fallback to '$(tune-mcpu-def-y)')
+cflags-y                               += $(tune-mcpu-def-y)
+endif
+endif
+
 
 ifdef CONFIG_ARC_CURR_IN_REG
 # For a global register defintion, make sure it gets passed to every file
index c77a0e3..0284ace 100644 (file)
@@ -19,7 +19,7 @@
 #define  R_ARC_32_PCREL                0x31
 
 /*to set parameters in the core dumps */
-#define ELF_ARCH               EM_ARCOMPACT
+#define ELF_ARCH               EM_ARC_INUSE
 #define ELF_CLASS              ELFCLASS32
 
 #ifdef CONFIG_CPU_BIG_ENDIAN
index 7fc73fe..863d63a 100644 (file)
@@ -90,6 +90,9 @@ static inline void arch_local_irq_restore(unsigned long flags)
 /*
  * Unconditionally Enable IRQs
  */
+#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
+extern void arch_local_irq_enable(void);
+#else
 static inline void arch_local_irq_enable(void)
 {
        unsigned long temp;
@@ -102,7 +105,7 @@ static inline void arch_local_irq_enable(void)
        : "n"((STATUS_E1_MASK | STATUS_E2_MASK))
        : "cc", "memory");
 }
-
+#endif
 
 /*
  * Unconditionally Disable IRQs
index 60406ec..ea00c8a 100644 (file)
@@ -165,7 +165,6 @@ END(EV_Extension)
 tracesys:
        ; save EFA in case tracer wants the PC of traced task
        ; using ERET won't work since next-PC has already committed
-       lr  r12, [efa]
        GET_CURR_TASK_FIELD_PTR   TASK_THREAD, r11
        st  r12, [r11, THREAD_FAULT_ADDR]       ; thread.fault_address
 
@@ -208,15 +207,9 @@ tracesys_exit:
 ; Breakpoint TRAP
 ; ---------------------------------------------
 trap_with_param:
-
-       ; stop_pc info by gdb needs this info
-       lr  r0, [efa]
+       mov r0, r12     ; EFA in case ptracer/gdb wants stop_pc
        mov r1, sp
 
-       ; Now that we have read EFA, it is safe to do "fake" rtie
-       ;   and get out of CPU exception mode
-       FAKE_RET_FROM_EXCPN
-
        ; Save callee regs in case gdb wants to have a look
        ; SP will grow up by size of CALLEE Reg-File
        ; NOTE: clobbers r12
@@ -243,6 +236,10 @@ ENTRY(EV_Trap)
 
        EXCEPTION_PROLOGUE
 
+       lr  r12, [efa]
+
+       FAKE_RET_FROM_EXCPN
+
        ;============ TRAP 1   :breakpoints
        ; Check ECR for trap with arg (PROLOGUE ensures r10 has ECR)
        bmsk.f 0, r10, 7
@@ -250,9 +247,6 @@ ENTRY(EV_Trap)
 
        ;============ TRAP  (no param): syscall top level
 
-       ; First return from Exception to pure K mode (Exception/IRQs renabled)
-       FAKE_RET_FROM_EXCPN
-
        ; If syscall tracing ongoing, invoke pre-post-hooks
        GET_CURR_THR_INFO_FLAGS   r10
        btst r10, TIF_SYSCALL_TRACE
index 6eb23f1..17fd1ed 100644 (file)
        bclr    r5, r5, STATUS_AD_BIT
 #endif
        kflag   r5
+
+#ifdef CONFIG_ARC_LPB_DISABLE
+       lr      r5, [ARC_REG_LPB_BUILD]
+       breq    r5, 0, 1f               ; LPB doesn't exist
+       mov     r5, 1
+       sr      r5, [ARC_REG_LPB_CTRL]
+1:
+#endif /* CONFIG_ARC_LPB_DISABLE */
 #endif
        ; Config DSP_CTRL properly, so kernel may use integer multiply,
        ; multiply-accumulate, and divide operations
index dad8a65..41f07b3 100644 (file)
@@ -58,10 +58,12 @@ static const struct id_to_str arc_legacy_rel[] = {
        { 0x00,         NULL   }
 };
 
-static const struct id_to_str arc_cpu_rel[] = {
+static const struct id_to_str arc_hs_ver54_rel[] = {
        /* UARCH.MAJOR, Release */
        {  0,           "R3.10a"},
        {  1,           "R3.50a"},
+       {  2,           "R3.60a"},
+       {  3,           "R4.00a"},
        {  0xFF,        NULL   }
 };
 
@@ -117,12 +119,6 @@ static void decode_arc_core(struct cpuinfo_arc *cpu)
        struct bcr_uarch_build_arcv2 uarch;
        const struct id_to_str *tbl;
 
-       /*
-        * Up until (including) the first core4 release (0x54) things were
-        * simple: AUX IDENTITY.ARCVER was sufficient to identify arc family
-        * and release: 0x50 to 0x53 was HS38, 0x54 was HS48 (dual issue)
-        */
-
        if (cpu->core.family < 0x54) { /* includes arc700 */
 
                for (tbl = &arc_legacy_rel[0]; tbl->id != 0; tbl++) {
@@ -143,11 +139,10 @@ static void decode_arc_core(struct cpuinfo_arc *cpu)
        }
 
        /*
-        * However the subsequent HS release (same 0x54) allow HS38 or HS48
-        * configurations and encode this info in a different BCR.
-        * The BCR was introduced in 0x54 so can't be read unconditionally.
+        * Initial HS cores bumped AUX IDENTITY.ARCVER for each release until
+        * ARCVER 0x54 which introduced AUX MICRO_ARCH_BUILD and subsequent
+        * releases only update it.
         */
-
        READ_BCR(ARC_REG_MICRO_ARCH_BCR, uarch);
 
        if (uarch.prod == 4) {
@@ -158,7 +153,7 @@ static void decode_arc_core(struct cpuinfo_arc *cpu)
                cpu->name = "HS38";
        }
 
-       for (tbl = &arc_cpu_rel[0]; tbl->id != 0xFF; tbl++) {
+       for (tbl = &arc_hs_ver54_rel[0]; tbl->id != 0xFF; tbl++) {
                if (uarch.maj == tbl->id) {
                        cpu->release = tbl->str;
                        break;
index 05e7b5d..04f0b12 100644 (file)
 &mmc2 {
        status = "okay";
        vmmc-supply = <&wl12xx_vmmc>;
-       ti,non-removable;
+       non-removable;
        bus-width = <4>;
        cap-power-off-card;
        pinctrl-names = "default";
index 91f93bc..dd93222 100644 (file)
@@ -22,6 +22,7 @@
        pinctrl-0 = <&emmc_pins>;
        bus-width = <8>;
        status = "okay";
+       non-removable;
 };
 
 &am33xx_pinmux {
index 3124d94..e07dd79 100644 (file)
@@ -75,7 +75,6 @@
        bus-width = <4>;
        non-removable;
        cap-power-off-card;
-       ti,needs-special-hs-handling;
        keep-power-in-suspend;
        pinctrl-names = "default";
        pinctrl-0 = <&mmc3_pins &wl18xx_pins>;
index 5811fb8..83f9452 100644 (file)
        bus-width = <4>;
        non-removable;
        cap-power-off-card;
-       ti,needs-special-hs-handling;
        keep-power-in-suspend;
        pinctrl-names = "default";
        pinctrl-0 = <&mmc3_pins &wl18xx_pins>;
index 4092cd1..609c8db 100644 (file)
@@ -75,7 +75,6 @@
        bus-width = <4>;
        non-removable;
        cap-power-off-card;
-       ti,needs-special-hs-handling;
        keep-power-in-suspend;
        pinctrl-names = "default";
        pinctrl-0 = <&mmc3_pins &wl18xx_pins>;
index 68252da..a4fc6b1 100644 (file)
        bus-width = <4>;
        pinctrl-names = "default";
        pinctrl-0 = <&mmc3_pins &wlan_pins>;
-       ti,non-removable;
-       ti,needs-special-hs-handling;
+       non-removable;
        cap-power-off-card;
        keep-power-in-suspend;
 
index 32f515a..78b6e1f 100644 (file)
 &mmc2 {
        status = "okay";
        vmmc-supply = <&wl12xx_vmmc>;
-       ti,non-removable;
+       non-removable;
        bus-width = <4>;
        cap-power-off-card;
        keep-power-in-suspend;
index fef5828..dbedf72 100644 (file)
        pinctrl-0 = <&emmc_pins>;
        vmmc-supply = <&vmmcsd_fixed>;
        bus-width = <8>;
-       ti,non-removable;
+       non-removable;
        status = "okay";
 };
 
index 6495a12..4e90f9c 100644 (file)
        vmmc-supply = <&vmmcsd_fixed>;
        bus-width = <8>;
        pinctrl-0 = <&mmc1_pins_default>;
-       ti,non-removable;
+       non-removable;
        status = "okay";
 };
 
index 244df9c..f03e72c 100644 (file)
        vmmc-supply = <&vmmcsd_fixed>;
        bus-width = <8>;
        pinctrl-0 = <&mmc2_pins_default>;
-       ti,non-removable;
+       non-removable;
        status = "okay";
 };
 
index 6d7608d..f9a027b 100644 (file)
        pinctrl-0 = <&emmc_pins>;
        vmmc-supply = <&ldo3_reg>;
        bus-width = <8>;
-       ti,non-removable;
+       non-removable;
 };
 
 &mmc3 {
        pinctrl-0 = <&wireless_pins>;
        vmmmc-supply = <&v3v3c_reg>;
        bus-width = <4>;
-       ti,non-removable;
+       non-removable;
        dmas = <&edma_xbar 12 0 1
                &edma_xbar 13 0 2>;
        dma-names = "tx", "rx";
index 3d0672b..7e46b4c 100644 (file)
@@ -69,7 +69,7 @@
        pinctrl-0 = <&emmc_pins>;
        vmmc-supply = <&vmmc_reg>;
        bus-width = <8>;
-       ti,non-removable;
+       non-removable;
        status = "disabled";
 };
 
index 4da7190..f0b2222 100644 (file)
@@ -88,7 +88,6 @@
                        AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0)
                        AM33XX_PADCONF(AM335X_PIN_MMC0_CMD, PIN_INPUT_PULLUP, MUX_MODE0)
                        AM33XX_PADCONF(AM335X_PIN_MMC0_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
-                       AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKR, PIN_INPUT, MUX_MODE4)           /* (B12) mcasp0_aclkr.mmc0_sdwp */
                >;
        };
 
index 7ff11d6..a9cbefc 100644 (file)
                        ranges = <0x0 0x60000 0x1000>;
 
                        mmc1: mmc@0 {
-                               compatible = "ti,omap4-hsmmc";
-                               ti,dual-volt;
+                               compatible = "ti,am335-sdhci";
                                ti,needs-special-reset;
-                               ti,needs-special-hs-handling;
                                dmas = <&edma_xbar 24 0 0
                                        &edma_xbar 25 0 0>;
                                dma-names = "tx", "rx";
                        ranges = <0x0 0xd8000 0x1000>;
 
                        mmc2: mmc@0 {
-                               compatible = "ti,omap4-hsmmc";
+                               compatible = "ti,am335-sdhci";
                                ti,needs-special-reset;
                                dmas = <&edma 2 0
                                        &edma 3 0>;
index 3b177c9..5fdce10 100644 (file)
                        ranges = <0x0 0x47810000 0x1000>;
 
                        mmc3: mmc@0 {
-                               compatible = "ti,omap4-hsmmc";
+                               compatible = "ti,am335-sdhci";
                                ti,needs-special-reset;
                                interrupts = <29>;
                                reg = <0x0 0x1000>;
+                               status = "disabled";
                        };
                };
 
                              <0x47400010 0x4>;
                        reg-names = "rev", "sysc";
                        ti,sysc-mask = <(SYSC_OMAP4_FREEEMU |
-                                        SYSC_OMAP2_SOFTRESET)>;
+                                        SYSC_OMAP4_SOFTRESET)>;
                        ti,sysc-midle = <SYSC_IDLE_FORCE>,
                                        <SYSC_IDLE_NO>,
                                        <SYSC_IDLE_SMART>;
                        clock-names = "fck";
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       ranges = <0x0 0x47400000 0x5000>;
+                       ranges = <0x0 0x47400000 0x8000>;
 
                        usb0_phy: usb-phy@1300 {
                                compatible = "ti,am335x-usb-phy";
index b4861f7..51ad9e8 100644 (file)
                        ranges = <0x0 0x47810000 0x1000>;
 
                        mmc3: mmc@0 {
-                               compatible = "ti,omap4-hsmmc";
+                               compatible = "ti,am437-sdhci";
                                ti,needs-special-reset;
                                interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
                                reg = <0x0 0x1000>;
+                               status = "disabled";
                        };
                };
 
index 063113a..a6b4fca 100644 (file)
        pinctrl-0 = <&emmc_pins>;
        vmmc-supply = <&vmmc_3v3>;
        bus-width = <8>;
-       ti,non-removable;
+       non-removable;
 };
 
 &spi0 {
index d692e3b..7737863 100644 (file)
 
                backlight = <&lcd_bl>;
 
-               panel-timing {
-                       clock-frequency = <33000000>;
-                       hactive = <800>;
-                       vactive = <480>;
-                       hfront-porch = <210>;
-                       hback-porch = <16>;
-                       hsync-len = <30>;
-                       vback-porch = <10>;
-                       vfront-porch = <22>;
-                       vsync-len = <13>;
-                       hsync-active = <0>;
-                       vsync-active = <0>;
-                       de-active = <1>;
-                       pixelclk-active = <1>;
-               };
-
                port {
                        lcd_in: endpoint {
                                remote-endpoint = <&dpi_out>;
        pinctrl-names = "default", "sleep";
        pinctrl-0 = <&emmc_pins_default>;
        pinctrl-1 = <&emmc_pins_sleep>;
-       ti,non-removable;
+       non-removable;
 };
 
 &mmc3 {
        pinctrl-1 = <&mmc3_pins_sleep>;
        cap-power-off-card;
        keep-power-in-suspend;
-       ti,non-removable;
+       non-removable;
 
        #address-cells = <1>;
        #size-cells = <0>;
index 0d0f9fe..906ac29 100644 (file)
                        ranges = <0x0 0x60000 0x1000>;
 
                        mmc1: mmc@0 {
-                               compatible = "ti,omap4-hsmmc";
+                               compatible = "ti,am437-sdhci";
                                reg = <0x0 0x1000>;
-                               ti,dual-volt;
                                ti,needs-special-reset;
                                dmas = <&edma 24 0>,
                                        <&edma 25 0>;
                        reg = <0xcc020 0x4>;
                        reg-names = "rev";
                        /* Domains (P, C): per_pwrdm, l4ls_clkdm */
-                       clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN0_CLKCTRL 0>;
-                       clock-names = "fck";
+                       clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN0_CLKCTRL 0>,
+                       <&dcan0_fck>;
+                       clock-names = "fck", "osc";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges = <0x0 0xcc000 0x2000>;
                        dcan0: can@0 {
                                compatible = "ti,am4372-d_can", "ti,am3352-d_can";
                                reg = <0x0 0x2000>;
+                               clocks = <&dcan0_fck>;
+                               clock-names = "fck";
                                syscon-raminit = <&scm_conf 0x644 0>;
                                interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
                                status = "disabled";
                        reg = <0xd0020 0x4>;
                        reg-names = "rev";
                        /* Domains (P, C): per_pwrdm, l4ls_clkdm */
-                       clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN1_CLKCTRL 0>;
-                       clock-names = "fck";
+                       clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN1_CLKCTRL 0>,
+                       <&dcan1_fck>;
+                       clock-names = "fck", "osc";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges = <0x0 0xd0000 0x2000>;
                        dcan1: can@0 {
                                compatible = "ti,am4372-d_can", "ti,am3352-d_can";
                                reg = <0x0 0x2000>;
+                               clocks = <&dcan1_fck>;
+                               clock-name = "fck";
                                syscon-raminit = <&scm_conf 0x644 1>;
                                interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
                                status = "disabled";
                        ranges = <0x0 0xd8000 0x1000>;
 
                        mmc2: mmc@0 {
-                               compatible = "ti,omap4-hsmmc";
+                               compatible = "ti,am437-sdhci";
                                reg = <0x0 0x1000>;
                                ti,needs-special-reset;
                                dmas = <&edma 2 0>,
index 4d5a7ca..08eabf0 100644 (file)
 
                enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
 
-               panel-timing {
-                       clock-frequency = <9000000>;
-                       hactive = <480>;
-                       vactive = <272>;
-                       hfront-porch = <2>;
-                       hback-porch = <2>;
-                       hsync-len = <41>;
-                       vfront-porch = <2>;
-                       vback-porch = <2>;
-                       vsync-len = <10>;
-                       hsync-active = <0>;
-                       vsync-active = <0>;
-                       de-active = <1>;
-                       pixelclk-active = <1>;
-               };
-
                port {
                        lcd_in: endpoint {
                                remote-endpoint = <&dpi_out>;
        pinctrl-1 = <&mmc3_pins_sleep>;
        cap-power-off-card;
        keep-power-in-suspend;
-       ti,non-removable;
+       non-removable;
 
        #address-cells = <1>;
        #size-cells = <0>;
index 27259fd..7d4e0df 100644 (file)
 
                backlight = <&lcd_bl>;
 
-               panel-timing {
-                       clock-frequency = <33000000>;
-                       hactive = <800>;
-                       vactive = <480>;
-                       hfront-porch = <210>;
-                       hback-porch = <16>;
-                       hsync-len = <30>;
-                       vback-porch = <10>;
-                       vfront-porch = <22>;
-                       vsync-len = <13>;
-                       hsync-active = <0>;
-                       vsync-active = <0>;
-                       de-active = <1>;
-                       pixelclk-active = <1>;
-               };
-
                port {
                        lcd_in: endpoint {
                                remote-endpoint = <&dpi_out>;
index 9877d77..4c51c6b 100644 (file)
 
 &cpsw_emac0 {
        phy-handle = <&phy0>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-rxid";
 };
 
 &ocp {
index 3481165..9b1a24c 100644 (file)
 
                        comphy: phy@18300 {
                                compatible = "marvell,armada-380-comphy";
-                               reg = <0x18300 0x100>;
+                               reg-names = "comphy", "conf";
+                               reg = <0x18300 0x100>, <0x18460 4>;
                                #address-cells = <1>;
                                #size-cells = <0>;
 
index da6d70f..3175266 100644 (file)
                        status = "disabled";
                };
 
-               dma@20000 {
+               dma: dma@20000 {
                        compatible = "arm,pl330", "arm,primecell";
                        reg = <0x20000 0x1000>;
                        interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>,
                        clocks = <&iprocslow>;
                        clock-names = "apb_pclk";
                        #dma-cells = <1>;
+                       dma-coherent;
+                       status = "disabled";
                };
 
                sdio: sdhci@21000 {
                        status = "disabled";
                };
 
-               mailbox: mailbox@25000 {
+               mailbox: mailbox@25c00 {
                        compatible = "brcm,iproc-fa2-mbox";
-                       reg = <0x25000 0x445>;
-                       interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
+                       reg = <0x25c00 0x400>;
+                       interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
                        #mbox-cells = <1>;
                        brcm,rx-status-len = <32>;
                        brcm,use-bcm-hdr;
index 3343253..29bbecd 100644 (file)
@@ -17,6 +17,7 @@
        };
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000
                       0x88000000 0x18000000>;
        };
index 8c388eb..7be4c4e 100644 (file)
 
 /* USB 3 support needed to be complete */
 
+&dma {
+       status = "okay";
+};
+
 &amac0 {
        status = "okay";
 };
index c339771..e58ed7e 100644 (file)
 
 /* USB 3 support needed to be complete */
 
+&dma {
+       status = "okay";
+};
+
 &amac0 {
        status = "okay";
 };
index 1c72ec8..716da62 100644 (file)
 
 /* XHCI support needed to be complete */
 
+&dma {
+       status = "okay";
+};
+
 &amac0 {
        status = "okay";
 };
index 96a021c..a49c2fd 100644 (file)
 
 /* USB 3 and SLIC support needed to be complete */
 
+&dma {
+       status = "okay";
+};
+
 &amac0 {
        status = "okay";
 };
index b2c7f21..dd6dff6 100644 (file)
 
 /* USB 3 and SLIC support needed to be complete */
 
+&dma {
+       status = "okay";
+};
+
 &amac0 {
        status = "okay";
 };
index 536fb24..a71371b 100644 (file)
        status = "okay";
 };
 
+&dma {
+       status = "okay";
+};
+
 &amac0 {
        status = "okay";
 };
index 3fcca12..7b84b54 100644 (file)
        };
 };
 
+&dma {
+       status = "okay";
+};
+
 &amac0 {
        status = "okay";
 };
index f89a64c..2cf6a52 100644 (file)
        rx-num-evt = <32>;
 };
 
-&mailbox5 {
-       status = "okay";
-       mbox_ipu1_ipc3x: mbox_ipu1_ipc3x {
-               status = "okay";
-       };
-       mbox_dsp1_ipc3x: mbox_dsp1_ipc3x {
-               status = "okay";
-       };
-};
-
-&mailbox6 {
-       status = "okay";
-       mbox_ipu2_ipc3x: mbox_ipu2_ipc3x {
-               status = "okay";
-       };
-       mbox_dsp2_ipc3x: mbox_dsp2_ipc3x {
-               status = "okay";
-       };
-};
-
 &pcie1_rc {
        status = "okay";
 };
index 62ca895..0c6f266 100644 (file)
                                        <SYSC_IDLE_SMART>,
                                        <SYSC_IDLE_SMART_WKUP>;
                        /* Domains (P, C): l4per_pwrdm, l4per_clkdm */
-                       clocks = <&l4per_clkctrl DRA7_L4PER_TIMER4_CLKCTRL 0>,
-                                <&timer_sys_clk_div>;
-                       clock-names = "fck", "timer_sys_ck";
+                       clocks = <&l4per_clkctrl DRA7_L4PER_TIMER4_CLKCTRL 0>;
+                       clock-names = "fck";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges = <0x0 0x36000 0x1000>;
                                        <SYSC_IDLE_SMART>,
                                        <SYSC_IDLE_SMART_WKUP>;
                        /* Domains (P, C): ipu_pwrdm, ipu_clkdm */
-                       clocks = <&ipu_clkctrl DRA7_IPU_TIMER5_CLKCTRL 0>, <&timer_sys_clk_div>;
-                       clock-names = "fck", "timer_sys_ck";
+                       clocks = <&ipu_clkctrl DRA7_IPU_TIMER5_CLKCTRL 0>;
+                       clock-names = "fck";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges = <0x0 0x20000 0x1000>;
                        timer5: timer@0 {
                                compatible = "ti,omap5430-timer";
                                reg = <0x0 0x80>;
-                               clocks = <&ipu_clkctrl DRA7_IPU_TIMER5_CLKCTRL 24>;
-                               clock-names = "fck";
+                               clocks = <&ipu_clkctrl DRA7_IPU_TIMER5_CLKCTRL 24>, <&timer_sys_clk_div>;
+                               clock-names = "fck", "timer_sys_ck";
                                interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
                        };
                };
                                        <SYSC_IDLE_SMART>,
                                        <SYSC_IDLE_SMART_WKUP>;
                        /* Domains (P, C): ipu_pwrdm, ipu_clkdm */
-                       clocks = <&ipu_clkctrl DRA7_IPU_TIMER6_CLKCTRL 0>,
-                                <&timer_sys_clk_div>;
-                       clock-names = "fck", "timer_sys_ck";
+                       clocks = <&ipu_clkctrl DRA7_IPU_TIMER6_CLKCTRL 0>;
+                       clock-names = "fck";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges = <0x0 0x22000 0x1000>;
                        timer6: timer@0 {
                                compatible = "ti,omap5430-timer";
                                reg = <0x0 0x80>;
-                               clocks = <&ipu_clkctrl DRA7_IPU_TIMER6_CLKCTRL 24>;
-                               clock-names = "fck";
+                               clocks = <&ipu_clkctrl DRA7_IPU_TIMER6_CLKCTRL 24>, <&timer_sys_clk_div>;
+                               clock-names = "fck", "timer_sys_ck";
                                interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
                        };
                };
                        timer14: timer@0 {
                                compatible = "ti,omap5430-timer";
                                reg = <0x0 0x80>;
-                               clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER14_CLKCTRL 24>;
-                               clock-names = "fck";
+                               clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER14_CLKCTRL 24>, <&timer_sys_clk_div>;
+                               clock-names = "fck", "timer_sys_ck";
                                interrupts = <GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH>;
                                ti,timer-pwm;
                        };
                        timer15: timer@0 {
                                compatible = "ti,omap5430-timer";
                                reg = <0x0 0x80>;
-                               clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER15_CLKCTRL 24>;
-                               clock-names = "fck";
+                               clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER15_CLKCTRL 24>, <&timer_sys_clk_div>;
+                               clock-names = "fck", "timer_sys_ck";
                                interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>;
                                ti,timer-pwm;
                        };
                        timer16: timer@0 {
                                compatible = "ti,omap5430-timer";
                                reg = <0x0 0x80>;
-                               clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER16_CLKCTRL 24>;
-                               clock-names = "fck";
+                               clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER16_CLKCTRL 24>, <&timer_sys_clk_div>;
+                               clock-names = "fck", "timer_sys_ck";
                                interrupts = <GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH>;
                                ti,timer-pwm;
                        };
index c38e86e..8c33510 100644 (file)
                simple-audio-card,frame-master = <&sound_codec>;
 
                sound_cpu: simple-audio-card,cpu {
-                       sound-dai = <&ssi2>;
+                       sound-dai = <&ssi1>;
                };
 
                sound_codec: simple-audio-card,codec {
index 756f3a9..12997da 100644 (file)
 
        pinctrl_usbotg: usbotggrp {
                fsl,pins = <
-                       MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+                       MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
                >;
        };
 
                        MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17070
                        MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17070
                        MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17070
+                       MX6QDL_PAD_GPIO_1__GPIO1_IO01  0x1b0b0
                >;
        };
 
index 8259244..14fd1de 100644 (file)
@@ -99,7 +99,7 @@
 &fec2 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet2>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-handle = <&ethphy0>;
        fsl,magic-packet;
        status = "okay";
index 3e5fb72..c99aa27 100644 (file)
 &fec2 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet2>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-handle = <&ethphy2>;
        status = "okay";
 };
index f05e918..53a25fb 100644 (file)
        status = "okay";
 };
 
-&wdog1 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_wdog>;
-       fsl,ext-reset-output;
-       status = "okay";
-};
-
 &iomuxc {
        pinctrl-0 = <&pinctrl_reset_out &pinctrl_gpio>;
 
                        MX6UL_PAD_NAND_DATA03__USDHC2_DATA3     0x170f9
                >;
        };
-
-       pinctrl_wdog: wdoggrp {
-               fsl,pins = <
-                       MX6UL_PAD_GPIO1_IO09__WDOG1_WDOG_ANY    0x30b0
-               >;
-       };
 };
index a17af4d..61ba21a 100644 (file)
        status = "okay";
 };
 
+&wdog1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_wdog>;
+       fsl,ext-reset-output;
+       status = "okay";
+};
+
 &iomuxc {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_reset_out>;
                        MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09      0x1b0b0
                >;
        };
+
+       pinctrl_wdog: wdoggrp {
+               fsl,pins = <
+                       MX6UL_PAD_GPIO1_IO09__WDOG1_WDOG_ANY    0x18b0
+               >;
+       };
 };
index db640ba..8b3d64c 100644 (file)
 
 &gbe0 {
        phy-handle = <&ethphy0>;
-       phy-mode = "rgmii-id";
+       phy-mode = "rgmii-rxid";
        status = "okay";
 };
 
index ae89dea..91129dc 100644 (file)
@@ -11,7 +11,7 @@
        #size-cells = <1>;
        interrupt-parent = <&gic>;
 
-       L2: l2-cache-controller@c4200000 {
+       L2: cache-controller@c4200000 {
                compatible = "arm,pl310-cache";
                reg = <0xc4200000 0x1000>;
                cache-unified;
index e39eee6..08a7d3c 100644 (file)
                #interrupt-cells = <2>;
                #address-cells = <1>;
                #size-cells = <0>;
-               spi-max-frequency = <3000000>;
+               spi-max-frequency = <9600000>;
                spi-cs-high;
+               spi-cpol;
+               spi-cpha;
 
                cpcap_adc: adc {
                        compatible = "motorola,mapphone-cpcap-adc";
index 4089d97..3dbcae3 100644 (file)
                        linux,code = <SW_FRONT_PROXIMITY>;
                        linux,can-disable;
                };
+
+               machine_cover {
+                       label = "Machine Cover";
+                       gpios = <&gpio6 0 GPIO_ACTIVE_LOW>; /* 160 */
+                       linux,input-type = <EV_SW>;
+                       linux,code = <SW_MACHINE_COVER>;
+                       linux,can-disable;
+               };
        };
 
        isp1707: isp1707 {
        pinctrl-0 = <&mmc1_pins>;
        vmmc-supply = <&vmmc1>;
        bus-width = <4>;
-       /* 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_LOW>; /* 160 */
 };
 
 /* most boards use vaux3, only some old versions use vmmc2 instead */
index 8047e8c..4548d87 100644 (file)
        ethernet@gpmc {
                reg = <5 0 0xff>;
                interrupt-parent = <&gpio2>;
-               interrupts = <12 IRQ_TYPE_EDGE_FALLING>;        /* gpio_44 */
+               interrupts = <12 IRQ_TYPE_LEVEL_LOW>;           /* gpio_44 */
 
                phy-mode = "mii";
 
index 6c2b07f..4400f5f 100644 (file)
        ti,no-idle;
        timer@0 {
                assigned-clocks = <&l4_wkup_clkctrl OMAP4_TIMER1_CLKCTRL 24>;
-               assigned-clock-parents = <&sys_clkin_ck>;
+               assigned-clock-parents = <&sys_32k_ck>;
        };
 };
index c2b54af..78f3267 100644 (file)
                        };
                };
 
-               L2: l2-cache@fffef000 {
+               L2: cache-controller@fffef000 {
                        compatible = "arm,pl310-cache";
                        reg = <0xfffef000 0x1000>;
                        interrupts = <0 38 0x04>;
index 3b8571b..8f614c4 100644 (file)
                        reg = <0xffcfb100 0x80>;
                };
 
-               L2: l2-cache@fffff000 {
+               L2: cache-controller@fffff000 {
                        compatible = "arm,pl310-cache";
                        reg = <0xfffff000 0x1000>;
                        interrupts = <0 18 IRQ_TYPE_LEVEL_HIGH>;
index bf531ef..0f95a6e 100644 (file)
                default-pool {
                        compatible = "shared-dma-pool";
                        size = <0x6000000>;
-                       alloc-ranges = <0x4a000000 0x6000000>;
+                       alloc-ranges = <0x40000000 0x10000000>;
                        reusable;
                        linux,cma-default;
                };
index e6b0367..c2b4fbf 100644 (file)
                default-pool {
                        compatible = "shared-dma-pool";
                        size = <0x6000000>;
-                       alloc-ranges = <0x4a000000 0x6000000>;
+                       alloc-ranges = <0x40000000 0x10000000>;
                        reusable;
                        linux,cma-default;
                };
index ffe1d10..6d6a379 100644 (file)
                default-pool {
                        compatible = "shared-dma-pool";
                        size = <0x6000000>;
-                       alloc-ranges = <0x4a000000 0x6000000>;
+                       alloc-ranges = <0x40000000 0x10000000>;
                        reusable;
                        linux,cma-default;
                };
index e6308fb..a88ee52 100644 (file)
                };
        };
 
-       mcc {
-               compatible = "arm,vexpress,config-bus";
-               arm,vexpress,config-bridge = <&v2m_sysreg>;
-
-               oscclk0 {
-                       /* MCC static memory clock */
-                       compatible = "arm,vexpress-osc";
-                       arm,vexpress-sysreg,func = <1 0>;
-                       freq-range = <25000000 60000000>;
-                       #clock-cells = <0>;
-                       clock-output-names = "v2m:oscclk0";
-               };
-
-               v2m_oscclk1: oscclk1 {
-                       /* CLCD clock */
-                       compatible = "arm,vexpress-osc";
-                       arm,vexpress-sysreg,func = <1 1>;
-                       freq-range = <23750000 65000000>;
-                       #clock-cells = <0>;
-                       clock-output-names = "v2m:oscclk1";
-               };
-
-               v2m_oscclk2: oscclk2 {
-                       /* IO FPGA peripheral clock */
-                       compatible = "arm,vexpress-osc";
-                       arm,vexpress-sysreg,func = <1 2>;
-                       freq-range = <24000000 24000000>;
-                       #clock-cells = <0>;
-                       clock-output-names = "v2m:oscclk2";
-               };
-
-               volt-vio {
-                       /* Logic level voltage */
-                       compatible = "arm,vexpress-volt";
-                       arm,vexpress-sysreg,func = <2 0>;
-                       regulator-name = "VIO";
-                       regulator-always-on;
-                       label = "VIO";
-               };
-
-               temp-mcc {
-                       /* MCC internal operating temperature */
-                       compatible = "arm,vexpress-temp";
-                       arm,vexpress-sysreg,func = <4 0>;
-                       label = "MCC";
-               };
-
-               reset {
-                       compatible = "arm,vexpress-reset";
-                       arm,vexpress-sysreg,func = <5 0>;
-               };
-
-               muxfpga {
-                       compatible = "arm,vexpress-muxfpga";
-                       arm,vexpress-sysreg,func = <7 0>;
-               };
-
-               shutdown {
-                       compatible = "arm,vexpress-shutdown";
-                       arm,vexpress-sysreg,func = <8 0>;
-               };
-
-               reboot {
-                       compatible = "arm,vexpress-reboot";
-                       arm,vexpress-sysreg,func = <9 0>;
-               };
-
-               dvimode {
-                       compatible = "arm,vexpress-dvimode";
-                       arm,vexpress-sysreg,func = <11 0>;
-               };
-       };
-
        bus@8000000 {
                motherboard-bus {
                        model = "V2M-P1";
                                                };
                                        };
                                };
+
+                               mcc {
+                                       compatible = "arm,vexpress,config-bus";
+                                       arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+                                       oscclk0 {
+                                               /* MCC static memory clock */
+                                               compatible = "arm,vexpress-osc";
+                                               arm,vexpress-sysreg,func = <1 0>;
+                                               freq-range = <25000000 60000000>;
+                                               #clock-cells = <0>;
+                                               clock-output-names = "v2m:oscclk0";
+                                       };
+
+                                       v2m_oscclk1: oscclk1 {
+                                               /* CLCD clock */
+                                               compatible = "arm,vexpress-osc";
+                                               arm,vexpress-sysreg,func = <1 1>;
+                                               freq-range = <23750000 65000000>;
+                                               #clock-cells = <0>;
+                                               clock-output-names = "v2m:oscclk1";
+                                       };
+
+                                       v2m_oscclk2: oscclk2 {
+                                               /* IO FPGA peripheral clock */
+                                               compatible = "arm,vexpress-osc";
+                                               arm,vexpress-sysreg,func = <1 2>;
+                                               freq-range = <24000000 24000000>;
+                                               #clock-cells = <0>;
+                                               clock-output-names = "v2m:oscclk2";
+                                       };
+
+                                       volt-vio {
+                                               /* Logic level voltage */
+                                               compatible = "arm,vexpress-volt";
+                                               arm,vexpress-sysreg,func = <2 0>;
+                                               regulator-name = "VIO";
+                                               regulator-always-on;
+                                               label = "VIO";
+                                       };
+
+                                       temp-mcc {
+                                               /* MCC internal operating temperature */
+                                               compatible = "arm,vexpress-temp";
+                                               arm,vexpress-sysreg,func = <4 0>;
+                                               label = "MCC";
+                                       };
+
+                                       reset {
+                                               compatible = "arm,vexpress-reset";
+                                               arm,vexpress-sysreg,func = <5 0>;
+                                       };
+
+                                       muxfpga {
+                                               compatible = "arm,vexpress-muxfpga";
+                                               arm,vexpress-sysreg,func = <7 0>;
+                                       };
+
+                                       shutdown {
+                                               compatible = "arm,vexpress-shutdown";
+                                               arm,vexpress-sysreg,func = <8 0>;
+                                       };
+
+                                       reboot {
+                                               compatible = "arm,vexpress-reboot";
+                                               arm,vexpress-sysreg,func = <9 0>;
+                                       };
+
+                                       dvimode {
+                                               compatible = "arm,vexpress-dvimode";
+                                               arm,vexpress-sysreg,func = <11 0>;
+                                       };
+                               };
                        };
                };
        };
index 84dc0ba..5dcf3c6 100644 (file)
@@ -87,4 +87,11 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
        return dram_base + SZ_512M;
 }
 
+struct efi_arm_entry_state {
+       u32     cpsr_before_ebs;
+       u32     sctlr_before_ebs;
+       u32     cpsr_after_ebs;
+       u32     sctlr_after_ebs;
+};
+
 #endif /* _ASM_ARM_EFI_H */
index f44f448..1a3eedb 100644 (file)
@@ -5,6 +5,8 @@
 #ifndef _ASM_ARM_PERCPU_H_
 #define _ASM_ARM_PERCPU_H_
 
+#include <asm/thread_info.h>
+
 /*
  * Same as asm-generic/percpu.h, except that we store the per cpu offset
  * in the TPIDRPRW. TPIDRPRW only exists on V6K and V7
index c036a4a..a1570c8 100644 (file)
 #if defined(__APCS_26__)
 #error Sorry, your compiler targets APCS-26 but this kernel requires APCS-32
 #endif
-/*
- * GCC 4.8.0-4.8.2: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58854
- *           miscompiles find_get_entry(), and can result in EXT3 and EXT4
- *           filesystem corruption (possibly other FS too).
- */
-#if defined(GCC_VERSION) && GCC_VERSION >= 40800 && GCC_VERSION < 40803
-#error Your compiler is too buggy; it is known to miscompile kernels
-#error and result in filesystem corruption and oopses.
-#endif
 
 int main(void)
 {
index 10499d4..9a79ef6 100644 (file)
@@ -84,7 +84,8 @@ static int ftrace_modify_code(unsigned long pc, unsigned long old,
                old = __opcode_to_mem_arm(old);
 
        if (validate) {
-               if (probe_kernel_read(&replaced, (void *)pc, MCOUNT_INSN_SIZE))
+               if (copy_from_kernel_nofault(&replaced, (void *)pc,
+                               MCOUNT_INSN_SIZE))
                        return -EFAULT;
 
                if (replaced != old)
index 02ca7ad..7fff88e 100644 (file)
@@ -683,6 +683,12 @@ static void disable_single_step(struct perf_event *bp)
        arch_install_hw_breakpoint(bp);
 }
 
+static int watchpoint_fault_on_uaccess(struct pt_regs *regs,
+                                      struct arch_hw_breakpoint *info)
+{
+       return !user_mode(regs) && info->ctrl.privilege == ARM_BREAKPOINT_USER;
+}
+
 static void watchpoint_handler(unsigned long addr, unsigned int fsr,
                               struct pt_regs *regs)
 {
@@ -742,16 +748,27 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr,
                }
 
                pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
+
+               /*
+                * If we triggered a user watchpoint from a uaccess routine,
+                * then handle the stepping ourselves since userspace really
+                * can't help us with this.
+                */
+               if (watchpoint_fault_on_uaccess(regs, info))
+                       goto step;
+
                perf_bp_event(wp, regs);
 
                /*
-                * If no overflow handler is present, insert a temporary
-                * mismatch breakpoint so we can single-step over the
-                * watchpoint trigger.
+                * Defer stepping to the overflow handler if one is installed.
+                * Otherwise, insert a temporary mismatch breakpoint so that
+                * we can single-step over the watchpoint trigger.
                 */
-               if (is_default_overflow_handler(wp))
-                       enable_single_step(wp, instruction_pointer(regs));
+               if (!is_default_overflow_handler(wp))
+                       goto unlock;
 
+step:
+               enable_single_step(wp, instruction_pointer(regs));
 unlock:
                rcu_read_unlock();
        }
index 6a95b92..7bd30c0 100644 (file)
@@ -236,7 +236,7 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
        /* patch_text() only supports int-sized breakpoints */
        BUILD_BUG_ON(sizeof(int) != BREAK_INSTR_SIZE);
 
-       err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
+       err = copy_from_kernel_nofault(bpt->saved_instr, (char *)bpt->bpt_addr,
                                BREAK_INSTR_SIZE);
        if (err)
                return err;
index 65a3b1e..17d5a78 100644 (file)
@@ -396,7 +396,7 @@ int is_valid_bugaddr(unsigned long pc)
        u32 insn = __opcode_to_mem_arm(BUG_INSTR_VALUE);
 #endif
 
-       if (probe_kernel_address((unsigned *)pc, bkpt))
+       if (get_kernel_nofault(bkpt, (void *)pc))
                return 0;
 
        return bkpt == insn;
index 6bfdca4..fddd08a 100644 (file)
@@ -184,6 +184,7 @@ static void __init patch_vdso(void *ehdr)
        if (!cntvct_ok) {
                vdso_nullpatch_one(&einfo, "__vdso_gettimeofday");
                vdso_nullpatch_one(&einfo, "__vdso_clock_gettime");
+               vdso_nullpatch_one(&einfo, "__vdso_clock_gettime64");
        }
 }
 
index 6aa938b..1df0ee0 100644 (file)
@@ -53,6 +53,7 @@ config ARCH_BCM_NSP
        select ARM_ERRATA_754322
        select ARM_ERRATA_775420
        select ARM_ERRATA_764369 if SMP
+       select ARM_TIMER_SP804
        select THERMAL
        select THERMAL_OF
        help
index 2a685ad..ae84c08 100644 (file)
@@ -289,6 +289,6 @@ struct platform_device *__init imx_add_spi_imx(
                const struct spi_imx_master *pdata);
 
 struct platform_device *imx_add_imx_dma(char *name, resource_size_t iobase,
-                                       int irq, int irq_err);
+                                       int irq);
 struct platform_device *imx_add_imx_sdma(char *name,
        resource_size_t iobase, int irq, struct sdma_platform_data *pdata);
index 78628ef..355de84 100644 (file)
@@ -24,7 +24,8 @@ struct platform_device *__init mxc_register_gpio(char *name, int id,
                        .flags = IORESOURCE_IRQ,
                },
        };
+       unsigned int nres;
 
-       return platform_device_register_resndata(&mxc_aips_bus,
-                       name, id, res, ARRAY_SIZE(res), NULL, 0);
+       nres = irq_high ? ARRAY_SIZE(res) : ARRAY_SIZE(res) - 1;
+       return platform_device_register_resndata(&mxc_aips_bus, name, id, res, nres, NULL, 0);
 }
index 26b47b3..12656f2 100644 (file)
@@ -6,7 +6,7 @@
 #include "devices-common.h"
 
 struct platform_device __init __maybe_unused *imx_add_imx_dma(char *name,
-       resource_size_t iobase, int irq, int irq_err)
+       resource_size_t iobase, int irq)
 {
        struct resource res[] = {
                {
@@ -17,10 +17,6 @@ struct platform_device __init __maybe_unused *imx_add_imx_dma(char *name,
                        .start = irq,
                        .end = irq,
                        .flags = IORESOURCE_IRQ,
-               }, {
-                       .start = irq_err,
-                       .end = irq_err,
-                       .flags = IORESOURCE_IRQ,
                },
        };
 
index 50a2eda..b834026 100644 (file)
@@ -78,8 +78,7 @@ void __init imx21_soc_init(void)
        mxc_register_gpio("imx21-gpio", 5, MX21_GPIO6_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
 
        pinctrl_provide_dummies();
-       imx_add_imx_dma("imx21-dma", MX21_DMA_BASE_ADDR,
-                       MX21_INT_DMACH0, 0); /* No ERR irq */
+       imx_add_imx_dma("imx21-dma", MX21_DMA_BASE_ADDR, MX21_INT_DMACH0);
        platform_device_register_simple("imx21-audmux", 0, imx21_audmux_res,
                                        ARRAY_SIZE(imx21_audmux_res));
 }
index 4e41251..2717614 100644 (file)
@@ -79,8 +79,7 @@ void __init imx27_soc_init(void)
        mxc_register_gpio("imx21-gpio", 5, MX27_GPIO6_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
 
        pinctrl_provide_dummies();
-       imx_add_imx_dma("imx27-dma", MX27_DMA_BASE_ADDR,
-                       MX27_INT_DMACH0, 0); /* No ERR irq */
+       imx_add_imx_dma("imx27-dma", MX27_DMA_BASE_ADDR, MX27_INT_DMACH0);
        /* imx27 has the imx21 type audmux */
        platform_device_register_simple("imx21-audmux", 0, imx27_audmux_res,
                                        ARRAY_SIZE(imx27_audmux_res));
index f057df8..e9962b4 100644 (file)
@@ -295,14 +295,14 @@ static int __init imx_suspend_alloc_ocram(
        if (!ocram_pool) {
                pr_warn("%s: ocram pool unavailable!\n", __func__);
                ret = -ENODEV;
-               goto put_node;
+               goto put_device;
        }
 
        ocram_base = gen_pool_alloc(ocram_pool, size);
        if (!ocram_base) {
                pr_warn("%s: unable to alloc ocram!\n", __func__);
                ret = -ENOMEM;
-               goto put_node;
+               goto put_device;
        }
 
        phys = gen_pool_virt_to_phys(ocram_pool, ocram_base);
@@ -312,6 +312,8 @@ static int __init imx_suspend_alloc_ocram(
        if (virt_out)
                *virt_out = virt;
 
+put_device:
+       put_device(&pdev->dev);
 put_node:
        of_node_put(node);
 
index dd34dff..40c74b4 100644 (file)
@@ -493,14 +493,14 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
        if (!ocram_pool) {
                pr_warn("%s: ocram pool unavailable!\n", __func__);
                ret = -ENODEV;
-               goto put_node;
+               goto put_device;
        }
 
        ocram_base = gen_pool_alloc(ocram_pool, MX6Q_SUSPEND_OCRAM_SIZE);
        if (!ocram_base) {
                pr_warn("%s: unable to alloc ocram!\n", __func__);
                ret = -ENOMEM;
-               goto put_node;
+               goto put_device;
        }
 
        ocram_pbase = gen_pool_virt_to_phys(ocram_pool, ocram_base);
@@ -523,7 +523,7 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
        ret = imx6_pm_get_base(&pm_info->mmdc_base, socdata->mmdc_compat);
        if (ret) {
                pr_warn("%s: failed to get mmdc base %d!\n", __func__, ret);
-               goto put_node;
+               goto put_device;
        }
 
        ret = imx6_pm_get_base(&pm_info->src_base, socdata->src_compat);
@@ -570,7 +570,7 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
                &imx6_suspend,
                MX6Q_SUSPEND_OCRAM_SIZE - sizeof(*pm_info));
 
-       goto put_node;
+       goto put_device;
 
 pl310_cache_map_failed:
        iounmap(pm_info->gpc_base.vbase);
@@ -580,6 +580,8 @@ iomuxc_map_failed:
        iounmap(pm_info->src_base.vbase);
 src_map_failed:
        iounmap(pm_info->mmdc_base.vbase);
+put_device:
+       put_device(&pdev->dev);
 put_node:
        of_node_put(node);
 
index 82706af..15b29a1 100644 (file)
@@ -3435,7 +3435,7 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
                regs = ioremap(data->module_pa,
                               data->module_size);
                if (!regs)
-                       return -ENOMEM;
+                       goto out_free_sysc;
        }
 
        /*
@@ -3445,13 +3445,13 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
        if (oh->class->name && strcmp(oh->class->name, data->name)) {
                class = kmemdup(oh->class, sizeof(*oh->class), GFP_KERNEL);
                if (!class)
-                       return -ENOMEM;
+                       goto out_unmap;
        }
 
        if (list_empty(&oh->slave_ports)) {
                oi = kcalloc(1, sizeof(*oi), GFP_KERNEL);
                if (!oi)
-                       return -ENOMEM;
+                       goto out_free_class;
 
                /*
                 * Note that we assume interconnect interface clocks will be
@@ -3478,6 +3478,14 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
        spin_unlock_irqrestore(&oh->_lock, flags);
 
        return 0;
+
+out_free_class:
+       kfree(class);
+out_unmap:
+       iounmap(regs);
+out_free_sysc:
+       kfree(sysc);
+       return -ENOMEM;
 }
 
 static const struct omap_hwmod_reset omap24xx_reset_quirks[] = {
@@ -3489,7 +3497,7 @@ static const struct omap_hwmod_reset dra7_reset_quirks[] = {
 };
 
 static const struct omap_hwmod_reset omap_reset_quirks[] = {
-       { .match = "dss", .len = 3, .reset = omap_dss_reset, },
+       { .match = "dss_core", .len = 8, .reset = omap_dss_reset, },
        { .match = "hdq1w", .len = 5, .reset = omap_hdq1w_reset, },
        { .match = "i2c", .len = 3, .reset = omap_i2c_reset, },
        { .match = "wd_timer", .len = 8, .reset = omap2_wd_timer_reset, },
index dcb9893..ffecbf2 100644 (file)
@@ -20,14 +20,6 @@ static const char *const stih41x_dt_match[] __initconst = {
        NULL
 };
 
-static void sti_l2_write_sec(unsigned long val, unsigned reg)
-{
-       /*
-        * We can't write to secure registers as we are in non-secure
-        * mode, until we have some SMI service available.
-        */
-}
-
 DT_MACHINE_START(STM, "STi SoC with Flattened Device Tree")
        .dt_compat      = stih41x_dt_match,
        .l2c_aux_val    = L2C_AUX_CTRL_SHARED_OVERRIDE |
@@ -36,5 +28,4 @@ DT_MACHINE_START(STM, "STi SoC with Flattened Device Tree")
                          L2C_AUX_CTRL_WAY_SIZE(4),
        .l2c_aux_mask   = 0xc0000fff,
        .smp            = smp_ops(sti_smp_ops),
-       .l2c_write_sec  = sti_l2_write_sec,
 MACHINE_END
index 84718ed..81a627e 100644 (file)
@@ -774,7 +774,7 @@ static int alignment_get_arm(struct pt_regs *regs, u32 *ip, u32 *inst)
        if (user_mode(regs))
                fault = get_user(instr, ip);
        else
-               fault = probe_kernel_address(ip, instr);
+               fault = get_kernel_nofault(instr, ip);
 
        *inst = __mem_to_opcode_arm(instr);
 
@@ -789,7 +789,7 @@ static int alignment_get_thumb(struct pt_regs *regs, u16 *ip, u16 *inst)
        if (user_mode(regs))
                fault = get_user(instr, ip);
        else
-               fault = probe_kernel_address(ip, instr);
+               fault = get_kernel_nofault(instr, ip);
 
        *inst = __mem_to_opcode_thumb16(instr);
 
index 628028b..bcd8261 100644 (file)
@@ -966,7 +966,7 @@ void __init create_mapping_late(struct mm_struct *mm, struct map_desc *md,
        pud_t *pud;
 
        p4d = p4d_alloc(mm, pgd_offset(mm, md->virtual), md->virtual);
-       if (!WARN_ON(!p4d))
+       if (WARN_ON(!p4d))
                return;
        pud = pud_alloc(mm, p4d, md->virtual);
        if (WARN_ON(!pud))
index fd4e1ce..e93145d 100644 (file)
@@ -241,7 +241,6 @@ static int __init fdt_find_hyper_node(unsigned long node, const char *uname,
  * see Documentation/devicetree/bindings/arm/xen.txt for the
  * documentation of the Xen Device Tree format.
  */
-#define GRANT_TABLE_PHYSADDR 0
 void __init xen_early_init(void)
 {
        of_scan_flat_dt(fdt_find_hyper_node, NULL);
index 31380da..66dc41f 100644 (file)
@@ -1518,9 +1518,9 @@ config ARM64_PTR_AUTH
        default y
        depends on !KVM || ARM64_VHE
        depends on (CC_HAS_SIGN_RETURN_ADDRESS || CC_HAS_BRANCH_PROT_PAC_RET) && AS_HAS_PAC
-       # GCC 9.1 and later inserts a .note.gnu.property section note for PAC
+       # Modern compilers insert a .note.gnu.property section note for PAC
        # which is only understood by binutils starting with version 2.33.1.
-       depends on !CC_IS_GCC || GCC_VERSION < 90100 || LD_VERSION >= 233010000
+       depends on LD_IS_LLD || LD_VERSION >= 233010000 || (CC_IS_GCC && GCC_VERSION < 90100)
        depends on !CC_IS_CLANG || AS_HAS_CFI_NEGATE_RA_STATE
        depends on (!FUNCTION_GRAPH_TRACER || DYNAMIC_FTRACE_WITH_REGS)
        help
@@ -1564,7 +1564,7 @@ config CC_HAS_SIGN_RETURN_ADDRESS
        def_bool $(cc-option,-msign-return-address=all)
 
 config AS_HAS_PAC
-       def_bool $(as-option,-Wa$(comma)-march=armv8.3-a)
+       def_bool $(cc-option,-Wa$(comma)-march=armv8.3-a)
 
 config AS_HAS_CFI_NEGATE_RA_STATE
        def_bool $(as-instr,.cfi_startproc\n.cfi_negate_ra_state\n.cfi_endproc\n)
@@ -1630,6 +1630,8 @@ config ARM64_BTI_KERNEL
        depends on CC_HAS_BRANCH_PROT_PAC_RET_BTI
        # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94697
        depends on !CC_IS_GCC || GCC_VERSION >= 100100
+       # https://reviews.llvm.org/rGb8ae3fdfa579dbf366b1bb1cbfdbf8c51db7fa55
+       depends on !CC_IS_CLANG || CLANG_VERSION >= 100001
        depends on !(CC_IS_CLANG && GCOV_KERNEL)
        depends on (!FUNCTION_GRAPH_TRACER || DYNAMIC_FTRACE_WITH_REGS)
        help
index cdf7ec0..265c446 100644 (file)
@@ -8,21 +8,6 @@ config PID_IN_CONTEXTIDR
          instructions during context switch. Say Y here only if you are
          planning to use hardware trace tools with this kernel.
 
-config ARM64_RANDOMIZE_TEXT_OFFSET
-       bool "Randomize TEXT_OFFSET at build time"
-       help
-         Say Y here if you want the image load offset (AKA TEXT_OFFSET)
-         of the kernel to be randomized at build-time. When selected,
-         this option will cause TEXT_OFFSET to be randomized upon any
-         build of the kernel, and the offset will be reflected in the
-         text_offset field of the resulting Image. This can be used to
-         fuzz-test bootloaders which respect text_offset.
-
-         This option is intended for bootloader and/or kernel testing
-         only. Bootloaders must make no assumptions regarding the value
-         of TEXT_OFFSET and platforms must not require a specific
-         value.
-
 config DEBUG_EFI
        depends on EFI && DEBUG_INFO
        bool "UEFI debugging"
index 76359cf..70f5905 100644 (file)
@@ -121,13 +121,7 @@ endif
 head-y         := arch/arm64/kernel/head.o
 
 # The byte offset of the kernel image in RAM from the start of RAM.
-ifeq ($(CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET), y)
-TEXT_OFFSET := $(shell awk "BEGIN {srand(); printf \"0x%06x\n\", \
-                int(2 * 1024 * 1024 / (2 ^ $(CONFIG_ARM64_PAGE_SHIFT)) * \
-                rand()) * (2 ^ $(CONFIG_ARM64_PAGE_SHIFT))}")
-else
 TEXT_OFFSET := 0x0
-endif
 
 ifeq ($(CONFIG_KASAN_SW_TAGS), y)
 KASAN_SHADOW_SCALE_SHIFT := 4
@@ -143,7 +137,7 @@ export      TEXT_OFFSET
 
 core-y         += arch/arm64/
 libs-y         := arch/arm64/lib/ $(libs-y)
-core-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
+libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
 
 # Default target when executing plain make
 boot           := arch/arm64/boot
index 78b1361..9ce78a7 100644 (file)
                        resets = <&ccu RST_BUS_VE>;
                        interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
                        allwinner,sram = <&ve_sram 1>;
+                       iommus = <&iommu 3>;
                };
 
                gpu: gpu@1800000 {
index d1fc9c2..9498d1d 100644 (file)
@@ -77,7 +77,7 @@
                method = "smc";
        };
 
-       intc: intc@fffc1000 {
+       intc: interrupt-controller@fffc1000 {
                compatible = "arm,gic-400", "arm,cortex-a15-gic";
                #interrupt-cells = <3>;
                interrupt-controller;
                        status = "disabled";
                };
 
-               nand: nand@ffb90000 {
+               nand: nand-controller@ffb90000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        compatible = "altr,socfpga-denali-nand";
                        clock-names = "timer";
                };
 
-               uart0: serial0@ffc02000 {
+               uart0: serial@ffc02000 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0xffc02000 0x100>;
                        interrupts = <0 108 4>;
                        status = "disabled";
                };
 
-               uart1: serial1@ffc02100 {
+               uart1: serial@ffc02100 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0xffc02100 0x100>;
                        interrupts = <0 109 4>;
index f6c4a15..feadd21 100644 (file)
 };
 
 &qspi {
+       status = "okay";
        flash@0 {
                #address-cells = <1>;
                #size-cells = <1>;
index 9946515..c079667 100644 (file)
 };
 
 &qspi {
+       status = "okay";
        flash@0 {
                #address-cells = <1>;
                #size-cells = <1>;
 
                        qspi_boot: partition@0 {
                                label = "Boot and fpga data";
-                               reg = <0x0 0x034B0000>;
+                               reg = <0x0 0x03FE0000>;
                        };
 
-                       qspi_rootfs: partition@4000000 {
+                       qspi_rootfs: partition@3FE0000 {
                                label = "Root Filesystem - JFFS2";
-                               reg = <0x034B0000 0x0EB50000>;
+                               reg = <0x03FE0000 0x0C020000>;
                        };
                };
        };
index 6a226fa..9e43f4d 100644 (file)
@@ -10,7 +10,7 @@
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/sound/meson-aiu.h>
 
-#include "meson-gxl-s905x.dtsi"
+#include "meson-gxl-s805x.dtsi"
 
 / {
        compatible = "libretech,aml-s805x-ac", "amlogic,s805x",
index 867e30f..eb7f5a3 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <dt-bindings/input/input.h>
 
-#include "meson-gxl-s905x.dtsi"
+#include "meson-gxl-s805x.dtsi"
 
 / {
        compatible = "amlogic,p241", "amlogic,s805x", "amlogic,meson-gxl";
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s805x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl-s805x.dtsi
new file mode 100644 (file)
index 0000000..f9d7056
--- /dev/null
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 BayLibre SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include "meson-gxl-s905x.dtsi"
+
+/ {
+       compatible = "amlogic,s805x", "amlogic,meson-gxl";
+};
+
+/* The S805X Package doesn't seem to handle the 744MHz OPP correctly */
+&mali {
+       assigned-clocks = <&clkc CLKID_MALI_0_SEL>,
+                         <&clkc CLKID_MALI_0>,
+                         <&clkc CLKID_MALI>; /* Glitch free mux */
+       assigned-clock-parents = <&clkc CLKID_FCLK_DIV3>,
+                                <0>, /* Do Nothing */
+                                <&clkc CLKID_MALI_0>;
+       assigned-clock-rates = <0>, /* Do Nothing */
+                              <666666666>,
+                              <0>; /* Do Nothing */
+};
index fc59c85..6c8b189 100644 (file)
        };
 };
 
+&hwrng {
+       clocks = <&clkc CLKID_RNG0>;
+       clock-names = "core";
+};
+
 &i2c_A {
        clocks = <&clkc CLKID_I2C>;
 };
index fb0137a..94911b1 100644 (file)
 
                        ldo1_reg: LDO1 {
                                regulator-name = "LDO1";
-                               regulator-min-microvolt = <3000000>;
+                               regulator-min-microvolt = <1600000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
                                regulator-always-on;
 
                        ldo2_reg: LDO2 {
                                regulator-name = "LDO2";
-                               regulator-min-microvolt = <900000>;
+                               regulator-min-microvolt = <800000>;
                                regulator-max-microvolt = <900000>;
                                regulator-boot-on;
                                regulator-always-on;
index e5ec832..0f1d7f8 100644 (file)
 
                        ldo1_reg: LDO1 {
                                regulator-name = "LDO1";
-                               regulator-min-microvolt = <3000000>;
+                               regulator-min-microvolt = <1600000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
                                regulator-always-on;
 
                        ldo2_reg: LDO2 {
                                regulator-name = "LDO2";
-                               regulator-min-microvolt = <900000>;
+                               regulator-min-microvolt = <800000>;
                                regulator-max-microvolt = <900000>;
                                regulator-boot-on;
                                regulator-always-on;
index d07e0e6..a1e5483 100644 (file)
 
                        ldo1_reg: LDO1 {
                                regulator-name = "LDO1";
-                               regulator-min-microvolt = <3000000>;
+                               regulator-min-microvolt = <1600000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
                                regulator-always-on;
 
                        ldo2_reg: LDO2 {
                                regulator-name = "LDO2";
-                               regulator-min-microvolt = <900000>;
+                               regulator-min-microvolt = <800000>;
                                regulator-max-microvolt = <900000>;
                                regulator-boot-on;
                                regulator-always-on;
index 51d9483..92f478d 100644 (file)
@@ -98,6 +98,7 @@
 };
 
 &qspi {
+       status = "okay";
        flash@0 {
                #address-cells = <1>;
                #size-cells = <1>;
index c8243da..eb01cc9 100644 (file)
        status = "okay";
        phy-mode = "2500base-x";
        phys = <&cp1_comphy5 2>;
-       fixed-link {
-               speed = <2500>;
-               full-duplex;
-       };
+       managed = "in-band-status";
 };
 
 &cp1_spi1 {
index 883e8ba..2ca7ba6 100644 (file)
@@ -194,7 +194,7 @@ CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_ACPI=y
 CONFIG_PCI_AARDVARK=y
 CONFIG_PCI_TEGRA=y
-CONFIG_PCIE_RCAR=y
+CONFIG_PCIE_RCAR_HOST=y
 CONFIG_PCI_HOST_GENERIC=y
 CONFIG_PCI_XGENE=y
 CONFIG_PCIE_ALTERA=y
index 5e5dc05..619db9b 100644 (file)
@@ -73,13 +73,13 @@ static inline void apply_alternatives_module(void *start, size_t length) { }
        ".pushsection .altinstructions,\"a\"\n"                         \
        ALTINSTR_ENTRY(feature)                                         \
        ".popsection\n"                                                 \
-       ".pushsection .altinstr_replacement, \"a\"\n"                   \
+       ".subsection 1\n"                                               \
        "663:\n\t"                                                      \
        newinstr "\n"                                                   \
        "664:\n\t"                                                      \
-       ".popsection\n\t"                                               \
        ".org   . - (664b-663b) + (662b-661b)\n\t"                      \
-       ".org   . - (662b-661b) + (664b-663b)\n"                        \
+       ".org   . - (662b-661b) + (664b-663b)\n\t"                      \
+       ".previous\n"                                                   \
        ".endif\n"
 
 #define __ALTERNATIVE_CFG_CB(oldinstr, feature, cfg_enabled, cb)       \
@@ -117,9 +117,9 @@ static inline void apply_alternatives_module(void *start, size_t length) { }
 662:   .pushsection .altinstructions, "a"
        altinstruction_entry 661b, 663f, \cap, 662b-661b, 664f-663f
        .popsection
-       .pushsection .altinstr_replacement, "ax"
+       .subsection 1
 663:   \insn2
-664:   .popsection
+664:   .previous
        .org    . - (664b-663b) + (662b-661b)
        .org    . - (662b-661b) + (664b-663b)
        .endif
@@ -160,7 +160,7 @@ static inline void apply_alternatives_module(void *start, size_t length) { }
        .pushsection .altinstructions, "a"
        altinstruction_entry 663f, 661f, \cap, 664f-663f, 662f-661f
        .popsection
-       .pushsection .altinstr_replacement, "ax"
+       .subsection 1
        .align 2        /* So GAS knows label 661 is suitably aligned */
 661:
 .endm
@@ -179,9 +179,9 @@ static inline void apply_alternatives_module(void *start, size_t length) { }
 .macro alternative_else
 662:
        .if .Lasm_alt_mode==0
-       .pushsection .altinstr_replacement, "ax"
+       .subsection 1
        .else
-       .popsection
+       .previous
        .endif
 663:
 .endm
@@ -192,7 +192,7 @@ static inline void apply_alternatives_module(void *start, size_t length) { }
 .macro alternative_endif
 664:
        .if .Lasm_alt_mode==0
-       .popsection
+       .previous
        .endif
        .org    . - (664b-663b) + (662b-661b)
        .org    . - (662b-661b) + (664b-663b)
index a358e97..6647ae4 100644 (file)
@@ -109,7 +109,7 @@ static inline u32 gic_read_pmr(void)
        return read_sysreg_s(SYS_ICC_PMR_EL1);
 }
 
-static inline void gic_write_pmr(u32 val)
+static __always_inline void gic_write_pmr(u32 val)
 {
        write_sysreg_s(val, SYS_ICC_PMR_EL1);
 }
index 7ae54d7..9f0ec21 100644 (file)
@@ -58,6 +58,7 @@ struct arch_timer_erratum_workaround {
        u64 (*read_cntvct_el0)(void);
        int (*set_next_event_phys)(unsigned long, struct clock_event_device *);
        int (*set_next_event_virt)(unsigned long, struct clock_event_device *);
+       bool disable_compat_vdso;
 };
 
 DECLARE_PER_CPU(const struct arch_timer_erratum_workaround *,
index b6f7bc6..93a161b 100644 (file)
@@ -24,16 +24,17 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
 {
        __uint128_t tmp;
        u64 sum;
+       int n = ihl; /* we want it signed */
 
        tmp = *(const __uint128_t *)iph;
        iph += 16;
-       ihl -= 4;
+       n -= 4;
        tmp += ((tmp >> 64) | (tmp << 64));
        sum = tmp >> 64;
        do {
                sum += *(const u32 *)iph;
                iph += 4;
-       } while (--ihl);
+       } while (--n > 0);
 
        sum += ((sum >> 32) | (sum << 32));
        return csum_fold((__force u32)(sum >> 32));
index 5d1f4ae..f7c3d1f 100644 (file)
@@ -675,7 +675,7 @@ static inline bool system_supports_generic_auth(void)
                cpus_have_const_cap(ARM64_HAS_GENERIC_AUTH);
 }
 
-static inline bool system_uses_irq_prio_masking(void)
+static __always_inline bool system_uses_irq_prio_masking(void)
 {
        return IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) &&
               cpus_have_const_cap(ARM64_HAS_IRQ_PRIO_MASKING);
index a87a93f..7219cdd 100644 (file)
@@ -86,6 +86,7 @@
 #define QCOM_CPU_PART_FALKOR           0xC00
 #define QCOM_CPU_PART_KRYO             0x200
 #define QCOM_CPU_PART_KRYO_3XX_SILVER  0x803
+#define QCOM_CPU_PART_KRYO_4XX_GOLD    0x804
 #define QCOM_CPU_PART_KRYO_4XX_SILVER  0x805
 
 #define NVIDIA_CPU_PART_DENVER         0x003
 #define MIDR_QCOM_FALKOR MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR)
 #define MIDR_QCOM_KRYO MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO)
 #define MIDR_QCOM_KRYO_3XX_SILVER MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_3XX_SILVER)
+#define MIDR_QCOM_KRYO_4XX_GOLD MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_4XX_GOLD)
 #define MIDR_QCOM_KRYO_4XX_SILVER MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_4XX_SILVER)
 #define MIDR_NVIDIA_DENVER MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_DENVER)
 #define MIDR_NVIDIA_CARMEL MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_CARMEL)
index e5ceea2..0b298f4 100644 (file)
@@ -109,6 +109,8 @@ void disable_debug_monitors(enum dbg_active_el el);
 
 void user_rewind_single_step(struct task_struct *task);
 void user_fastforward_single_step(struct task_struct *task);
+void user_regs_reset_single_step(struct user_pt_regs *regs,
+                                struct task_struct *task);
 
 void kernel_enable_single_step(struct pt_regs *regs);
 void kernel_disable_single_step(void);
index 81fefd2..ba89a9a 100644 (file)
@@ -12,7 +12,6 @@
  * instead.
  */
 #define BTI_C hint 34 ;
-#define BTI_J hint 36 ;
 
 /*
  * When using in-kernel BTI we need to ensure that PCS-conformant assembly
        SYM_START(name, SYM_L_WEAK, SYM_A_NONE)         \
        BTI_C
 
-#define SYM_INNER_LABEL(name, linkage)                 \
-       .type name SYM_T_NONE ASM_NL                    \
-       SYM_ENTRY(name, linkage, SYM_A_NONE)            \
-       BTI_J
-
 #endif
 
 /*
index 68140fd..8444df0 100644 (file)
@@ -19,6 +19,9 @@
 
 typedef struct {
        atomic64_t      id;
+#ifdef CONFIG_COMPAT
+       void            *sigpage;
+#endif
        void            *vdso;
        unsigned long   flags;
 } mm_context_t;
index 2e7e0f4..4d867c6 100644 (file)
@@ -67,7 +67,7 @@ extern bool arm64_use_ng_mappings;
 #define PAGE_HYP               __pgprot(_HYP_PAGE_DEFAULT | PTE_HYP | PTE_HYP_XN)
 #define PAGE_HYP_EXEC          __pgprot(_HYP_PAGE_DEFAULT | PTE_HYP | PTE_RDONLY)
 #define PAGE_HYP_RO            __pgprot(_HYP_PAGE_DEFAULT | PTE_HYP | PTE_RDONLY | PTE_HYP_XN)
-#define PAGE_HYP_DEVICE                __pgprot(PROT_DEVICE_nGnRE | PTE_HYP)
+#define PAGE_HYP_DEVICE                __pgprot(_PROT_DEFAULT | PTE_ATTRINDX(MT_DEVICE_nGnRE) | PTE_HYP | PTE_HYP_XN)
 
 #define PAGE_S2_MEMATTR(attr)                                          \
        ({                                                              \
index 6dbd267..758e2d1 100644 (file)
@@ -416,7 +416,7 @@ static inline pmd_t pmd_mkdevmap(pmd_t pmd)
        __pgprot((pgprot_val(prot) & ~(mask)) | (bits))
 
 #define pgprot_nx(prot) \
-       __pgprot_modify(prot, 0, PTE_PXN)
+       __pgprot_modify(prot, PTE_MAYBE_GP, PTE_PXN)
 
 /*
  * Mark the prot value as uncacheable and unbufferable.
index ea268d8..a0c8a0b 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/thread_info.h>
-#include <asm/pointer_auth.h>
 
 DECLARE_PER_CPU_READ_MOSTLY(int, cpu_number);
 
index 65299a2..cfc0672 100644 (file)
@@ -34,6 +34,10 @@ static inline long syscall_get_error(struct task_struct *task,
                                     struct pt_regs *regs)
 {
        unsigned long error = regs->regs[0];
+
+       if (is_compat_thread(task_thread_info(task)))
+               error = sign_extend64(error, 31);
+
        return IS_ERR_VALUE(error) ? error : 0;
 }
 
@@ -47,7 +51,13 @@ static inline void syscall_set_return_value(struct task_struct *task,
                                            struct pt_regs *regs,
                                            int error, long val)
 {
-       regs->regs[0] = (long) error ? error : val;
+       if (error)
+               val = error;
+
+       if (is_compat_thread(task_thread_info(task)))
+               val = lower_32_bits(val);
+
+       regs->regs[0] = val;
 }
 
 #define SYSCALL_MAX_ARGS 6
index 6ea8b6a..5e784e1 100644 (file)
@@ -93,6 +93,7 @@ void arch_release_task_struct(struct task_struct *tsk);
 #define _TIF_SYSCALL_EMU       (1 << TIF_SYSCALL_EMU)
 #define _TIF_UPROBE            (1 << TIF_UPROBE)
 #define _TIF_FSCHECK           (1 << TIF_FSCHECK)
+#define _TIF_SINGLESTEP                (1 << TIF_SINGLESTEP)
 #define _TIF_32BIT             (1 << TIF_32BIT)
 #define _TIF_SVE               (1 << TIF_SVE)
 
index df6ea65..b054d9f 100644 (file)
@@ -2,7 +2,10 @@
 #ifndef __ASM_VDSOCLOCKSOURCE_H
 #define __ASM_VDSOCLOCKSOURCE_H
 
-#define VDSO_ARCH_CLOCKMODES   \
-       VDSO_CLOCKMODE_ARCHTIMER
+#define VDSO_ARCH_CLOCKMODES                                   \
+       /* vdso clocksource for both 32 and 64bit tasks */      \
+       VDSO_CLOCKMODE_ARCHTIMER,                               \
+       /* vdso clocksource for 64bit tasks only */             \
+       VDSO_CLOCKMODE_ARCHTIMER_NOCOMPAT
 
 #endif
index b6907ae..9a625e8 100644 (file)
@@ -111,7 +111,7 @@ static __always_inline u64 __arch_get_hw_counter(s32 clock_mode)
         * update. Return something. Core will do another round and then
         * see the mode change and fallback to the syscall.
         */
-       if (clock_mode == VDSO_CLOCKMODE_NONE)
+       if (clock_mode != VDSO_CLOCKMODE_ARCHTIMER)
                return 0;
 
        /*
@@ -152,6 +152,12 @@ static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
        return ret;
 }
 
+static inline bool vdso_clocksource_ok(const struct vdso_data *vd)
+{
+       return vd->clock_mode == VDSO_CLOCKMODE_ARCHTIMER;
+}
+#define vdso_clocksource_ok    vdso_clocksource_ok
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __ASM_VDSO_GETTIMEOFDAY_H */
index 151f285..a561cbb 100644 (file)
@@ -29,9 +29,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
 
 obj-$(CONFIG_COMPAT)                   += sys32.o signal32.o                   \
                                           sys_compat.o
-ifneq ($(CONFIG_COMPAT_VDSO), y)
 obj-$(CONFIG_COMPAT)                   += sigreturn32.o
-endif
 obj-$(CONFIG_KUSER_HELPERS)            += kuser32.o
 obj-$(CONFIG_FUNCTION_TRACER)          += ftrace.o entry-ftrace.o
 obj-$(CONFIG_MODULES)                  += module.o
index d1757ef..7303994 100644 (file)
@@ -43,20 +43,8 @@ bool alternative_is_applied(u16 cpufeature)
  */
 static bool branch_insn_requires_update(struct alt_instr *alt, unsigned long pc)
 {
-       unsigned long replptr;
-
-       if (kernel_text_address(pc))
-               return true;
-
-       replptr = (unsigned long)ALT_REPL_PTR(alt);
-       if (pc >= replptr && pc <= (replptr + alt->alt_len))
-               return false;
-
-       /*
-        * Branching into *another* alternate sequence is doomed, and
-        * we're not even trying to fix it up.
-        */
-       BUG();
+       unsigned long replptr = (unsigned long)ALT_REPL_PTR(alt);
+       return !(pc >= replptr && pc <= (replptr + alt->alt_len));
 }
 
 #define align_down(x, a)       ((unsigned long)(x) & ~(((unsigned long)(a)) - 1))
index ad06d68..79728bf 100644 (file)
@@ -460,6 +460,8 @@ static const struct midr_range arm64_ssb_cpus[] = {
        MIDR_ALL_VERSIONS(MIDR_CORTEX_A53),
        MIDR_ALL_VERSIONS(MIDR_CORTEX_A55),
        MIDR_ALL_VERSIONS(MIDR_BRAHMA_B53),
+       MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_3XX_SILVER),
+       MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_SILVER),
        {},
 };
 
@@ -470,12 +472,7 @@ static bool
 has_cortex_a76_erratum_1463225(const struct arm64_cpu_capabilities *entry,
                               int scope)
 {
-       u32 midr = read_cpuid_id();
-       /* Cortex-A76 r0p0 - r3p1 */
-       struct midr_range range = MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 3, 1);
-
-       WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
-       return is_midr_in_range(midr, &range) && is_kernel_in_hyp_mode();
+       return is_affected_midr_range_list(entry, scope) && is_kernel_in_hyp_mode();
 }
 #endif
 
@@ -726,6 +723,8 @@ static const struct midr_range erratum_1418040_list[] = {
        MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 3, 1),
        /* Neoverse-N1 r0p0 to r3p1 */
        MIDR_RANGE(MIDR_NEOVERSE_N1, 0, 0, 3, 1),
+       /* Kryo4xx Gold (rcpe to rfpf) => (r0p0 to r3p1) */
+       MIDR_RANGE(MIDR_QCOM_KRYO_4XX_GOLD, 0xc, 0xe, 0xf, 0xf),
        {},
 };
 #endif
@@ -770,11 +769,23 @@ static const struct midr_range erratum_speculative_at_list[] = {
 #ifdef CONFIG_ARM64_ERRATUM_1530923
        /* Cortex A55 r0p0 to r2p0 */
        MIDR_RANGE(MIDR_CORTEX_A55, 0, 0, 2, 0),
+       /* Kryo4xx Silver (rdpe => r1p0) */
+       MIDR_REV(MIDR_QCOM_KRYO_4XX_SILVER, 0xd, 0xe),
 #endif
        {},
 };
 #endif
 
+#ifdef CONFIG_ARM64_ERRATUM_1463225
+static const struct midr_range erratum_1463225[] = {
+       /* Cortex-A76 r0p0 - r3p1 */
+       MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 3, 1),
+       /* Kryo4xx Gold (rcpe to rfpf) => (r0p0 to r3p1) */
+       MIDR_RANGE(MIDR_QCOM_KRYO_4XX_GOLD, 0xc, 0xe, 0xf, 0xf),
+       {},
+};
+#endif
+
 const struct arm64_cpu_capabilities arm64_errata[] = {
 #ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE
        {
@@ -914,6 +925,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
                .capability = ARM64_WORKAROUND_1463225,
                .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
                .matches = has_cortex_a76_erratum_1463225,
+               .midr_range_list = erratum_1463225,
        },
 #endif
 #ifdef CONFIG_CAVIUM_TX2_ERRATUM_219
index 4ae4167..9fae0ef 100644 (file)
@@ -1290,6 +1290,8 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
                MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
                MIDR_ALL_VERSIONS(MIDR_HISI_TSV110),
                MIDR_ALL_VERSIONS(MIDR_NVIDIA_CARMEL),
+               MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_3XX_SILVER),
+               MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_SILVER),
                { /* sentinel */ }
        };
        char const *str = "kpti command line option";
@@ -1406,6 +1408,8 @@ static bool cpu_has_broken_dbm(void)
        static const struct midr_range cpus[] = {
 #ifdef CONFIG_ARM64_ERRATUM_1024718
                MIDR_RANGE(MIDR_CORTEX_A55, 0, 0, 1, 0),  // A55 r0p0 -r1p0
+               /* Kryo4xx Silver (rdpe => r1p0) */
+               MIDR_REV(MIDR_QCOM_KRYO_4XX_SILVER, 0xd, 0xe),
 #endif
                {},
        };
index 5df4936..7310a4f 100644 (file)
@@ -141,17 +141,20 @@ postcore_initcall(debug_monitors_init);
 /*
  * Single step API and exception handling.
  */
-static void set_regs_spsr_ss(struct pt_regs *regs)
+static void set_user_regs_spsr_ss(struct user_pt_regs *regs)
 {
        regs->pstate |= DBG_SPSR_SS;
 }
-NOKPROBE_SYMBOL(set_regs_spsr_ss);
+NOKPROBE_SYMBOL(set_user_regs_spsr_ss);
 
-static void clear_regs_spsr_ss(struct pt_regs *regs)
+static void clear_user_regs_spsr_ss(struct user_pt_regs *regs)
 {
        regs->pstate &= ~DBG_SPSR_SS;
 }
-NOKPROBE_SYMBOL(clear_regs_spsr_ss);
+NOKPROBE_SYMBOL(clear_user_regs_spsr_ss);
+
+#define set_regs_spsr_ss(r)    set_user_regs_spsr_ss(&(r)->user_regs)
+#define clear_regs_spsr_ss(r)  clear_user_regs_spsr_ss(&(r)->user_regs)
 
 static DEFINE_SPINLOCK(debug_hook_lock);
 static LIST_HEAD(user_step_hook);
@@ -391,17 +394,26 @@ void user_rewind_single_step(struct task_struct *task)
         * If single step is active for this thread, then set SPSR.SS
         * to 1 to avoid returning to the active-pending state.
         */
-       if (test_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP))
+       if (test_tsk_thread_flag(task, TIF_SINGLESTEP))
                set_regs_spsr_ss(task_pt_regs(task));
 }
 NOKPROBE_SYMBOL(user_rewind_single_step);
 
 void user_fastforward_single_step(struct task_struct *task)
 {
-       if (test_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP))
+       if (test_tsk_thread_flag(task, TIF_SINGLESTEP))
                clear_regs_spsr_ss(task_pt_regs(task));
 }
 
+void user_regs_reset_single_step(struct user_pt_regs *regs,
+                                struct task_struct *task)
+{
+       if (test_tsk_thread_flag(task, TIF_SINGLESTEP))
+               set_user_regs_spsr_ss(regs);
+       else
+               clear_user_regs_spsr_ss(regs);
+}
+
 /* Kernel API */
 void kernel_enable_single_step(struct pt_regs *regs)
 {
index 3dbdf97..d3be9db 100644 (file)
@@ -57,7 +57,7 @@ static void notrace el1_dbg(struct pt_regs *regs, unsigned long esr)
        /*
         * The CPU masked interrupts, and we are leaving them masked during
         * do_debug_exception(). Update PMR as if we had called
-        * local_mask_daif().
+        * local_daif_mask().
         */
        if (system_uses_irq_prio_masking())
                gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
index 5304d19..35de8ba 100644 (file)
@@ -126,8 +126,10 @@ alternative_else_nop_endif
        add     \dst, \dst, #(\sym - .entry.tramp.text)
        .endm
 
-       // This macro corrupts x0-x3. It is the caller's duty
-       // to save/restore them if required.
+       /*
+        * This macro corrupts x0-x3. It is the caller's duty  to save/restore
+        * them if required.
+        */
        .macro  apply_ssbd, state, tmp1, tmp2
 #ifdef CONFIG_ARM64_SSBD
 alternative_cb arm64_enable_wa2_handling
@@ -167,13 +169,28 @@ alternative_cb_end
        stp     x28, x29, [sp, #16 * 14]
 
        .if     \el == 0
+       .if     \regsize == 32
+       /*
+        * If we're returning from a 32-bit task on a system affected by
+        * 1418040 then re-enable userspace access to the virtual counter.
+        */
+#ifdef CONFIG_ARM64_ERRATUM_1418040
+alternative_if ARM64_WORKAROUND_1418040
+       mrs     x0, cntkctl_el1
+       orr     x0, x0, #2      // ARCH_TIMER_USR_VCT_ACCESS_EN
+       msr     cntkctl_el1, x0
+alternative_else_nop_endif
+#endif
+       .endif
        clear_gp_regs
        mrs     x21, sp_el0
        ldr_this_cpu    tsk, __entry_task, x20
        msr     sp_el0, tsk
 
-       // Ensure MDSCR_EL1.SS is clear, since we can unmask debug exceptions
-       // when scheduling.
+       /*
+        * Ensure MDSCR_EL1.SS is clear, since we can unmask debug exceptions
+        * when scheduling.
+        */
        ldr     x19, [tsk, #TSK_TI_FLAGS]
        disable_step_tsk x19, x20
 
@@ -320,6 +337,14 @@ alternative_else_nop_endif
        tst     x22, #PSR_MODE32_BIT            // native task?
        b.eq    3f
 
+#ifdef CONFIG_ARM64_ERRATUM_1418040
+alternative_if ARM64_WORKAROUND_1418040
+       mrs     x0, cntkctl_el1
+       bic     x0, x0, #2                      // ARCH_TIMER_USR_VCT_ACCESS_EN
+       msr     cntkctl_el1, x0
+alternative_else_nop_endif
+#endif
+
 #ifdef CONFIG_ARM64_ERRATUM_845719
 alternative_if ARM64_WORKAROUND_845719
 #ifdef CONFIG_PID_IN_CONTEXTIDR
@@ -331,21 +356,6 @@ alternative_if ARM64_WORKAROUND_845719
 alternative_else_nop_endif
 #endif
 3:
-#ifdef CONFIG_ARM64_ERRATUM_1418040
-alternative_if_not ARM64_WORKAROUND_1418040
-       b       4f
-alternative_else_nop_endif
-       /*
-        * if (x22.mode32 == cntkctl_el1.el0vcten)
-        *     cntkctl_el1.el0vcten = ~cntkctl_el1.el0vcten
-        */
-       mrs     x1, cntkctl_el1
-       eon     x0, x1, x22, lsr #3
-       tbz     x0, #1, 4f
-       eor     x1, x1, #2      // ARCH_TIMER_USR_VCT_ACCESS_EN
-       msr     cntkctl_el1, x1
-4:
-#endif
        scs_save tsk, x0
 
        /* No kernel C function calls after this as user keys are set. */
@@ -377,11 +387,11 @@ alternative_else_nop_endif
        .if     \el == 0
 alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
-       bne     5f
+       bne     4f
        msr     far_el1, x30
        tramp_alias     x30, tramp_exit_native
        br      x30
-5:
+4:
        tramp_alias     x30, tramp_exit_compat
        br      x30
 #endif
index 35cb5e6..55c8f3e 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/bug.h>
 #include <linux/cache.h>
 #include <linux/compat.h>
+#include <linux/compiler.h>
 #include <linux/cpu.h>
 #include <linux/cpu_pm.h>
 #include <linux/kernel.h>
@@ -119,10 +120,20 @@ struct fpsimd_last_state_struct {
 static DEFINE_PER_CPU(struct fpsimd_last_state_struct, fpsimd_last_state);
 
 /* Default VL for tasks that don't set it explicitly: */
-static int sve_default_vl = -1;
+static int __sve_default_vl = -1;
+
+static int get_sve_default_vl(void)
+{
+       return READ_ONCE(__sve_default_vl);
+}
 
 #ifdef CONFIG_ARM64_SVE
 
+static void set_sve_default_vl(int val)
+{
+       WRITE_ONCE(__sve_default_vl, val);
+}
+
 /* Maximum supported vector length across all CPUs (initially poisoned) */
 int __ro_after_init sve_max_vl = SVE_VL_MIN;
 int __ro_after_init sve_max_virtualisable_vl = SVE_VL_MIN;
@@ -338,13 +349,13 @@ static unsigned int find_supported_vector_length(unsigned int vl)
        return sve_vl_from_vq(__bit_to_vq(bit));
 }
 
-#ifdef CONFIG_SYSCTL
+#if defined(CONFIG_ARM64_SVE) && defined(CONFIG_SYSCTL)
 
 static int sve_proc_do_default_vl(struct ctl_table *table, int write,
                                  void *buffer, size_t *lenp, loff_t *ppos)
 {
        int ret;
-       int vl = sve_default_vl;
+       int vl = get_sve_default_vl();
        struct ctl_table tmp_table = {
                .data = &vl,
                .maxlen = sizeof(vl),
@@ -361,7 +372,7 @@ static int sve_proc_do_default_vl(struct ctl_table *table, int write,
        if (!sve_vl_valid(vl))
                return -EINVAL;
 
-       sve_default_vl = find_supported_vector_length(vl);
+       set_sve_default_vl(find_supported_vector_length(vl));
        return 0;
 }
 
@@ -383,9 +394,9 @@ static int __init sve_sysctl_init(void)
        return 0;
 }
 
-#else /* ! CONFIG_SYSCTL */
+#else /* ! (CONFIG_ARM64_SVE && CONFIG_SYSCTL) */
 static int __init sve_sysctl_init(void) { return 0; }
-#endif /* ! CONFIG_SYSCTL */
+#endif /* ! (CONFIG_ARM64_SVE && CONFIG_SYSCTL) */
 
 #define ZREG(sve_state, vq, n) ((char *)(sve_state) +          \
        (SVE_SIG_ZREG_OFFSET(vq, n) - SVE_SIG_REGS_OFFSET))
@@ -868,7 +879,7 @@ void __init sve_setup(void)
         * For the default VL, pick the maximum supported value <= 64.
         * VL == 64 is guaranteed not to grow the signal frame.
         */
-       sve_default_vl = find_supported_vector_length(64);
+       set_sve_default_vl(find_supported_vector_length(64));
 
        bitmap_andnot(tmp_map, sve_vq_partial_map, sve_vq_map,
                      SVE_VQ_MAX);
@@ -889,7 +900,7 @@ void __init sve_setup(void)
        pr_info("SVE: maximum available vector length %u bytes per vector\n",
                sve_max_vl);
        pr_info("SVE: default vector length %u bytes per vector\n",
-               sve_default_vl);
+               get_sve_default_vl());
 
        /* KVM decides whether to support mismatched systems. Just warn here: */
        if (sve_max_virtualisable_vl < sve_max_vl)
@@ -1029,13 +1040,13 @@ void fpsimd_flush_thread(void)
                 * vector length configured: no kernel task can become a user
                 * task without an exec and hence a call to this function.
                 * By the time the first call to this function is made, all
-                * early hardware probing is complete, so sve_default_vl
+                * early hardware probing is complete, so __sve_default_vl
                 * should be valid.
                 * If a bug causes this to go wrong, we make some noise and
                 * try to fudge thread.sve_vl to a safe value here.
                 */
                vl = current->thread.sve_vl_onexec ?
-                       current->thread.sve_vl_onexec : sve_default_vl;
+                       current->thread.sve_vl_onexec : get_sve_default_vl();
 
                if (WARN_ON(!sve_vl_valid(vl)))
                        vl = SVE_VL_MIN;
index 0b727ed..af234a1 100644 (file)
@@ -730,6 +730,27 @@ static u64 get_distance_from_watchpoint(unsigned long addr, u64 val,
                return 0;
 }
 
+static int watchpoint_report(struct perf_event *wp, unsigned long addr,
+                            struct pt_regs *regs)
+{
+       int step = is_default_overflow_handler(wp);
+       struct arch_hw_breakpoint *info = counter_arch_bp(wp);
+
+       info->trigger = addr;
+
+       /*
+        * If we triggered a user watchpoint from a uaccess routine, then
+        * handle the stepping ourselves since userspace really can't help
+        * us with this.
+        */
+       if (!user_mode(regs) && info->ctrl.privilege == AARCH64_BREAKPOINT_EL0)
+               step = 1;
+       else
+               perf_bp_event(wp, regs);
+
+       return step;
+}
+
 static int watchpoint_handler(unsigned long addr, unsigned int esr,
                              struct pt_regs *regs)
 {
@@ -739,7 +760,6 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
        u64 val;
        struct perf_event *wp, **slots;
        struct debug_info *debug_info;
-       struct arch_hw_breakpoint *info;
        struct arch_hw_breakpoint_ctrl ctrl;
 
        slots = this_cpu_ptr(wp_on_reg);
@@ -777,25 +797,13 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
                if (dist != 0)
                        continue;
 
-               info = counter_arch_bp(wp);
-               info->trigger = addr;
-               perf_bp_event(wp, regs);
-
-               /* Do we need to handle the stepping? */
-               if (is_default_overflow_handler(wp))
-                       step = 1;
+               step = watchpoint_report(wp, addr, regs);
        }
-       if (min_dist > 0 && min_dist != -1) {
-               /* No exact match found. */
-               wp = slots[closest_match];
-               info = counter_arch_bp(wp);
-               info->trigger = addr;
-               perf_bp_event(wp, regs);
 
-               /* Do we need to handle the stepping? */
-               if (is_default_overflow_handler(wp))
-                       step = 1;
-       }
+       /* No exact match found? */
+       if (min_dist > 0 && min_dist != -1)
+               step = watchpoint_report(slots[closest_match], addr, regs);
+
        rcu_read_unlock();
 
        if (!step)
index 684d871..a107375 100644 (file)
@@ -135,7 +135,7 @@ int __kprobes aarch64_insn_read(void *addr, u32 *insnp)
        int ret;
        __le32 val;
 
-       ret = probe_kernel_read(&val, addr, AARCH64_INSN_SIZE);
+       ret = copy_from_kernel_nofault(&val, addr, AARCH64_INSN_SIZE);
        if (!ret)
                *insnp = le32_to_cpu(val);
 
@@ -151,7 +151,7 @@ static int __kprobes __aarch64_insn_write(void *addr, __le32 insn)
        raw_spin_lock_irqsave(&patch_lock, flags);
        waddr = patch_map(addr, FIX_TEXT_POKE0);
 
-       ret = probe_kernel_write(waddr, &insn, AARCH64_INSN_SIZE);
+       ret = copy_to_kernel_nofault(waddr, &insn, AARCH64_INSN_SIZE);
 
        patch_unmap(FIX_TEXT_POKE0);
        raw_spin_unlock_irqrestore(&patch_lock, flags);
index 4311992..1a157ca 100644 (file)
@@ -252,7 +252,7 @@ static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr)
        if (!kgdb_single_step)
                return DBG_HOOK_ERROR;
 
-       kgdb_handle_exception(1, SIGTRAP, 0, regs);
+       kgdb_handle_exception(0, SIGTRAP, 0, regs);
        return DBG_HOOK_HANDLED;
 }
 NOKPROBE_SYMBOL(kgdb_step_brk_fn);
index 522e6f5..361a114 100644 (file)
@@ -219,8 +219,7 @@ static int prepare_elf_headers(void **addr, unsigned long *sz)
                                        MEMBLOCK_NONE, &start, &end, NULL)
                nr_ranges++;
 
-       cmem = kmalloc(sizeof(struct crash_mem) +
-                       sizeof(struct crash_mem_range) * nr_ranges, GFP_KERNEL);
+       cmem = kmalloc(struct_size(cmem, ranges, nr_ranges), GFP_KERNEL);
        if (!cmem)
                return -ENOMEM;
 
index 0bbac61..666b225 100644 (file)
@@ -15,15 +15,34 @@ u64 perf_reg_value(struct pt_regs *regs, int idx)
                return 0;
 
        /*
-        * Compat (i.e. 32 bit) mode:
-        * - PC has been set in the pt_regs struct in kernel_entry,
-        * - Handle SP and LR here.
+        * Our handling of compat tasks (PERF_SAMPLE_REGS_ABI_32) is weird, but
+        * we're stuck with it for ABI compatability reasons.
+        *
+        * For a 32-bit consumer inspecting a 32-bit task, then it will look at
+        * the first 16 registers (see arch/arm/include/uapi/asm/perf_regs.h).
+        * These correspond directly to a prefix of the registers saved in our
+        * 'struct pt_regs', with the exception of the PC, so we copy that down
+        * (x15 corresponds to SP_hyp in the architecture).
+        *
+        * So far, so good.
+        *
+        * The oddity arises when a 64-bit consumer looks at a 32-bit task and
+        * asks for registers beyond PERF_REG_ARM_MAX. In this case, we return
+        * SP_usr, LR_usr and PC in the positions where the AArch64 SP, LR and
+        * PC registers would normally live. The initial idea was to allow a
+        * 64-bit unwinder to unwind a 32-bit task and, although it's not clear
+        * how well that works in practice, somebody might be relying on it.
+        *
+        * At the time we make a sample, we don't know whether the consumer is
+        * 32-bit or 64-bit, so we have to cater for both possibilities.
         */
        if (compat_user_mode(regs)) {
                if ((u32)idx == PERF_REG_ARM64_SP)
                        return regs->compat_sp;
                if ((u32)idx == PERF_REG_ARM64_LR)
                        return regs->compat_lr;
+               if (idx == 15)
+                       return regs->pc;
        }
 
        if ((u32)idx == PERF_REG_ARM64_SP)
index d1c95dc..5290f17 100644 (file)
@@ -120,15 +120,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
 
 void *alloc_insn_page(void)
 {
-       void *page;
-
-       page = vmalloc_exec(PAGE_SIZE);
-       if (page) {
-               set_memory_ro((unsigned long)page, 1);
-               set_vm_flush_reset_perms(page);
-       }
-
-       return page;
+       return __vmalloc_node_range(PAGE_SIZE, 1, VMALLOC_START, VMALLOC_END,
+                       GFP_KERNEL, PAGE_KERNEL_ROX, VM_FLUSH_RESET_PERMS,
+                       NUMA_NO_NODE, __builtin_return_address(0));
 }
 
 /* arm kprobe: install breakpoint in text */
index 68b7f34..1e02e98 100644 (file)
@@ -1811,19 +1811,42 @@ static void tracehook_report_syscall(struct pt_regs *regs,
        unsigned long saved_reg;
 
        /*
-        * A scratch register (ip(r12) on AArch32, x7 on AArch64) is
-        * used to denote syscall entry/exit:
+        * We have some ABI weirdness here in the way that we handle syscall
+        * exit stops because we indicate whether or not the stop has been
+        * signalled from syscall entry or syscall exit by clobbering a general
+        * purpose register (ip/r12 for AArch32, x7 for AArch64) in the tracee
+        * and restoring its old value after the stop. This means that:
+        *
+        * - Any writes by the tracer to this register during the stop are
+        *   ignored/discarded.
+        *
+        * - The actual value of the register is not available during the stop,
+        *   so the tracer cannot save it and restore it later.
+        *
+        * - Syscall stops behave differently to seccomp and pseudo-step traps
+        *   (the latter do not nobble any registers).
         */
        regno = (is_compat_task() ? 12 : 7);
        saved_reg = regs->regs[regno];
        regs->regs[regno] = dir;
 
-       if (dir == PTRACE_SYSCALL_EXIT)
+       if (dir == PTRACE_SYSCALL_ENTER) {
+               if (tracehook_report_syscall_entry(regs))
+                       forget_syscall(regs);
+               regs->regs[regno] = saved_reg;
+       } else if (!test_thread_flag(TIF_SINGLESTEP)) {
                tracehook_report_syscall_exit(regs, 0);
-       else if (tracehook_report_syscall_entry(regs))
-               forget_syscall(regs);
+               regs->regs[regno] = saved_reg;
+       } else {
+               regs->regs[regno] = saved_reg;
 
-       regs->regs[regno] = saved_reg;
+               /*
+                * Signal a pseudo-step exception since we are stepping but
+                * tracer modifications to the registers may have rewound the
+                * state machine.
+                */
+               tracehook_report_syscall_exit(regs, 1);
+       }
 }
 
 int syscall_trace_enter(struct pt_regs *regs)
@@ -1833,12 +1856,12 @@ int syscall_trace_enter(struct pt_regs *regs)
        if (flags & (_TIF_SYSCALL_EMU | _TIF_SYSCALL_TRACE)) {
                tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
                if (!in_syscall(regs) || (flags & _TIF_SYSCALL_EMU))
-                       return -1;
+                       return NO_SYSCALL;
        }
 
        /* Do the secure computing after ptrace; failures should be fast. */
        if (secure_computing() == -1)
-               return -1;
+               return NO_SYSCALL;
 
        if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
                trace_sys_enter(regs, regs->syscallno);
@@ -1851,12 +1874,14 @@ int syscall_trace_enter(struct pt_regs *regs)
 
 void syscall_trace_exit(struct pt_regs *regs)
 {
+       unsigned long flags = READ_ONCE(current_thread_info()->flags);
+
        audit_syscall_exit(regs);
 
-       if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
+       if (flags & _TIF_SYSCALL_TRACEPOINT)
                trace_sys_exit(regs, regs_return_value(regs));
 
-       if (test_thread_flag(TIF_SYSCALL_TRACE))
+       if (flags & (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP))
                tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
 
        rseq_syscall(regs);
@@ -1934,8 +1959,8 @@ static int valid_native_regs(struct user_pt_regs *regs)
  */
 int valid_user_regs(struct user_pt_regs *regs, struct task_struct *task)
 {
-       if (!test_tsk_thread_flag(task, TIF_SINGLESTEP))
-               regs->pstate &= ~DBG_SPSR_SS;
+       /* https://lore.kernel.org/lkml/20191118131525.GA4180@willie-the-truck */
+       user_regs_reset_single_step(regs, task);
 
        if (is_compat_thread(task_thread_info(task)))
                return valid_compat_regs(regs);
index 801d56c..3b4f31f 100644 (file)
@@ -800,7 +800,6 @@ static void setup_restart_syscall(struct pt_regs *regs)
  */
 static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 {
-       struct task_struct *tsk = current;
        sigset_t *oldset = sigmask_to_save();
        int usig = ksig->sig;
        int ret;
@@ -824,14 +823,8 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
         */
        ret |= !valid_user_regs(&regs->user_regs, current);
 
-       /*
-        * Fast forward the stepping logic so we step into the signal
-        * handler.
-        */
-       if (!ret)
-               user_fastforward_single_step(tsk);
-
-       signal_setup_done(ret, ksig, 0);
+       /* Step into the signal handler if we are stepping */
+       signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
 }
 
 /*
index 82feca6..2f507f5 100644 (file)
@@ -342,38 +342,13 @@ static void compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka,
                retcode = ptr_to_compat(ka->sa.sa_restorer);
        } else {
                /* Set up sigreturn pointer */
-#ifdef CONFIG_COMPAT_VDSO
-               void *vdso_base = current->mm->context.vdso;
-               void *vdso_trampoline;
-
-               if (ka->sa.sa_flags & SA_SIGINFO) {
-                       if (thumb) {
-                               vdso_trampoline = VDSO_SYMBOL(vdso_base,
-                                                       compat_rt_sigreturn_thumb);
-                       } else {
-                               vdso_trampoline = VDSO_SYMBOL(vdso_base,
-                                                       compat_rt_sigreturn_arm);
-                       }
-               } else {
-                       if (thumb) {
-                               vdso_trampoline = VDSO_SYMBOL(vdso_base,
-                                                       compat_sigreturn_thumb);
-                       } else {
-                               vdso_trampoline = VDSO_SYMBOL(vdso_base,
-                                                       compat_sigreturn_arm);
-                       }
-               }
-
-               retcode = ptr_to_compat(vdso_trampoline) + thumb;
-#else
                unsigned int idx = thumb << 1;
 
                if (ka->sa.sa_flags & SA_SIGINFO)
                        idx += 3;
 
-               retcode = (unsigned long)current->mm->context.vdso +
+               retcode = (unsigned long)current->mm->context.sigpage +
                          (idx << 2) + thumb;
-#endif
        }
 
        regs->regs[0]   = usig;
index 5f5b868..5f0c048 100644 (file)
@@ -50,6 +50,9 @@ static void invoke_syscall(struct pt_regs *regs, unsigned int scno,
                ret = do_ni_syscall(regs, scno);
        }
 
+       if (is_compat_task())
+               ret = lower_32_bits(ret);
+
        regs->regs[0] = ret;
 }
 
@@ -121,7 +124,21 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
        user_exit();
 
        if (has_syscall_work(flags)) {
-               /* set default errno for user-issued syscall(-1) */
+               /*
+                * The de-facto standard way to skip a system call using ptrace
+                * is to set the system call to -1 (NO_SYSCALL) and set x0 to a
+                * suitable error code for consumption by userspace. However,
+                * this cannot be distinguished from a user-issued syscall(-1)
+                * and so we must set x0 to -ENOSYS here in case the tracer doesn't
+                * issue the skip and we fall into trace_exit with x0 preserved.
+                *
+                * This is slightly odd because it also means that if a tracer
+                * sets the system call number to -1 but does not initialise x0,
+                * then x0 will be preserved for all system calls apart from a
+                * user-issued syscall(-1). However, requesting a skip and not
+                * setting the return value is unlikely to do anything sensible
+                * anyway.
+                */
                if (scno == NO_SYSCALL)
                        regs->regs[0] = -ENOSYS;
                scno = syscall_trace_enter(regs);
@@ -139,7 +156,7 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
        if (!has_syscall_work(flags) && !IS_ENABLED(CONFIG_DEBUG_RSEQ)) {
                local_daif_mask();
                flags = current_thread_info()->flags;
-               if (!has_syscall_work(flags)) {
+               if (!has_syscall_work(flags) && !(flags & _TIF_SINGLESTEP)) {
                        /*
                         * We're off to userspace, where interrupts are
                         * always enabled after we restore the flags from
index 50cc30a..47f651d 100644 (file)
@@ -376,7 +376,7 @@ static int call_undef_hook(struct pt_regs *regs)
 
        if (!user_mode(regs)) {
                __le32 instr_le;
-               if (probe_kernel_address((__force __le32 *)pc, instr_le))
+               if (get_kernel_nofault(instr_le, (__force __le32 *)pc))
                        goto exit;
                instr = le32_to_cpu(instr_le);
        } else if (compat_thumb_mode(regs)) {
@@ -813,6 +813,7 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
                handler[reason], smp_processor_id(), esr,
                esr_get_class_string(esr));
 
+       __show_regs(regs);
        local_daif_mask();
        panic("bad mode");
 }
index 4e01657..e546df0 100644 (file)
@@ -191,15 +191,12 @@ enum aarch32_map {
 #ifdef CONFIG_COMPAT_VDSO
        AA32_MAP_VVAR,
        AA32_MAP_VDSO,
-#else
-       AA32_MAP_SIGPAGE
 #endif
+       AA32_MAP_SIGPAGE
 };
 
 static struct page *aarch32_vectors_page __ro_after_init;
-#ifndef CONFIG_COMPAT_VDSO
 static struct page *aarch32_sig_page __ro_after_init;
-#endif
 
 static struct vm_special_mapping aarch32_vdso_maps[] = {
        [AA32_MAP_VECTORS] = {
@@ -214,12 +211,11 @@ static struct vm_special_mapping aarch32_vdso_maps[] = {
                .name = "[vdso]",
                .mremap = aarch32_vdso_mremap,
        },
-#else
+#endif /* CONFIG_COMPAT_VDSO */
        [AA32_MAP_SIGPAGE] = {
                .name   = "[sigpage]", /* ABI */
                .pages  = &aarch32_sig_page,
        },
-#endif /* CONFIG_COMPAT_VDSO */
 };
 
 static int aarch32_alloc_kuser_vdso_page(void)
@@ -242,27 +238,11 @@ static int aarch32_alloc_kuser_vdso_page(void)
        return 0;
 }
 
-#ifdef CONFIG_COMPAT_VDSO
-static int __aarch32_alloc_vdso_pages(void)
-{
-       int ret;
-
-       vdso_info[VDSO_ABI_AA32].dm = &aarch32_vdso_maps[AA32_MAP_VVAR];
-       vdso_info[VDSO_ABI_AA32].cm = &aarch32_vdso_maps[AA32_MAP_VDSO];
-
-       ret = __vdso_init(VDSO_ABI_AA32);
-       if (ret)
-               return ret;
-
-       return aarch32_alloc_kuser_vdso_page();
-}
-#else
-static int __aarch32_alloc_vdso_pages(void)
+static int aarch32_alloc_sigpage(void)
 {
        extern char __aarch32_sigret_code_start[], __aarch32_sigret_code_end[];
        int sigret_sz = __aarch32_sigret_code_end - __aarch32_sigret_code_start;
        unsigned long sigpage;
-       int ret;
 
        sigpage = get_zeroed_page(GFP_ATOMIC);
        if (!sigpage)
@@ -271,18 +251,34 @@ static int __aarch32_alloc_vdso_pages(void)
        memcpy((void *)sigpage, __aarch32_sigret_code_start, sigret_sz);
        aarch32_sig_page = virt_to_page(sigpage);
        flush_dcache_page(aarch32_sig_page);
+       return 0;
+}
 
-       ret = aarch32_alloc_kuser_vdso_page();
-       if (ret)
-               free_page(sigpage);
+#ifdef CONFIG_COMPAT_VDSO
+static int __aarch32_alloc_vdso_pages(void)
+{
+       vdso_info[VDSO_ABI_AA32].dm = &aarch32_vdso_maps[AA32_MAP_VVAR];
+       vdso_info[VDSO_ABI_AA32].cm = &aarch32_vdso_maps[AA32_MAP_VDSO];
 
-       return ret;
+       return __vdso_init(VDSO_ABI_AA32);
 }
 #endif /* CONFIG_COMPAT_VDSO */
 
 static int __init aarch32_alloc_vdso_pages(void)
 {
-       return __aarch32_alloc_vdso_pages();
+       int ret;
+
+#ifdef CONFIG_COMPAT_VDSO
+       ret = __aarch32_alloc_vdso_pages();
+       if (ret)
+               return ret;
+#endif
+
+       ret = aarch32_alloc_sigpage();
+       if (ret)
+               return ret;
+
+       return aarch32_alloc_kuser_vdso_page();
 }
 arch_initcall(aarch32_alloc_vdso_pages);
 
@@ -305,7 +301,6 @@ static int aarch32_kuser_helpers_setup(struct mm_struct *mm)
        return PTR_ERR_OR_ZERO(ret);
 }
 
-#ifndef CONFIG_COMPAT_VDSO
 static int aarch32_sigreturn_setup(struct mm_struct *mm)
 {
        unsigned long addr;
@@ -328,12 +323,11 @@ static int aarch32_sigreturn_setup(struct mm_struct *mm)
        if (IS_ERR(ret))
                goto out;
 
-       mm->context.vdso = (void *)addr;
+       mm->context.sigpage = (void *)addr;
 
 out:
        return PTR_ERR_OR_ZERO(ret);
 }
-#endif /* !CONFIG_COMPAT_VDSO */
 
 int aarch32_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 {
@@ -352,10 +346,11 @@ int aarch32_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
                                       mm,
                                       bprm,
                                       uses_interp);
-#else
-       ret = aarch32_sigreturn_setup(mm);
+       if (ret)
+               goto out;
 #endif /* CONFIG_COMPAT_VDSO */
 
+       ret = aarch32_sigreturn_setup(mm);
 out:
        mmap_write_unlock(mm);
        return ret;
index 556d424..45d5cfe 100644 (file)
@@ -23,13 +23,14 @@ btildflags-$(CONFIG_ARM64_BTI_KERNEL) += -z force-bti
 # potential future proofing if we end up with internal calls to the exported
 # routines, as x86 does (see 6f121e548f83 ("x86, vdso: Reimplement vdso.so
 # preparation in build-time C")).
-ldflags-y := -shared -nostdlib -soname=linux-vdso.so.1 --hash-style=sysv \
-               -Bsymbolic --eh-frame-hdr --build-id -n $(btildflags-y) -T
+ldflags-y := -shared -nostdlib -soname=linux-vdso.so.1 --hash-style=sysv       \
+            -Bsymbolic $(call ld-option, --no-eh-frame-hdr) --build-id -n      \
+            $(btildflags-y) -T
 
 ccflags-y := -fno-common -fno-builtin -fno-stack-protector -ffixed-x18
 ccflags-y += -DDISABLE_BRANCH_PROFILING
 
-CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) -Os $(CC_FLAGS_SCS)
+CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) -Os $(CC_FLAGS_SCS) $(GCC_PLUGINS_CFLAGS)
 KBUILD_CFLAGS                  += $(DISABLE_LTO)
 KASAN_SANITIZE                 := n
 UBSAN_SANITIZE                 := n
index 620a3ef..0e18729 100644 (file)
 
        .text
 
+/*
+ * NOTE!!!  You may notice that all of the .cfi directives in this file have
+ * been commented out. This is because they have been shown to trigger segfaults
+ * in libgcc when unwinding out of a SIGCANCEL handler to invoke pthread
+ * cleanup handlers during the thread cancellation dance. By omitting the
+ * directives, we trigger an arm64-specific fallback path in the unwinder which
+ * recognises the signal frame and restores many of the registers directly from
+ * the sigcontext. Re-enabling the cfi directives here therefore needs to be
+ * much more comprehensive to reduce the risk of further regressions.
+ */
+
 /* Ensure that the mysterious NOP can be associated with a function. */
-       .cfi_startproc
+//     .cfi_startproc
 
 /*
- * .cfi_signal_frame causes the corresponding Frame Description Entry in the
- * .eh_frame section to be annotated as a signal frame. This allows DWARF
- * unwinders (e.g. libstdc++) to implement _Unwind_GetIPInfo(), which permits
- * unwinding out of the signal trampoline without the need for the mysterious
- * NOP.
+ * .cfi_signal_frame causes the corresponding Frame Description Entry (FDE) in
+ * the .eh_frame section to be annotated as a signal frame. This allows DWARF
+ * unwinders (e.g. libstdc++) to implement _Unwind_GetIPInfo() and identify
+ * the next frame using the unmodified return address instead of subtracting 1,
+ * which may yield the wrong FDE.
  */
-       .cfi_signal_frame
+//     .cfi_signal_frame
 
 /*
  * Tell the unwinder where to locate the frame record linking back to the
- * interrupted context. We don't provide unwind info for registers other
- * than the frame pointer and the link register here; in practice, this
- * is sufficient for unwinding in C/C++ based runtimes and the values in
- * the sigcontext may have been modified by this point anyway. Debuggers
+ * interrupted context. We don't provide unwind info for registers other than
+ * the frame pointer and the link register here; in practice, this is likely to
+ * be insufficient for unwinding in C/C++ based runtimes, especially without a
+ * means to restore the stack pointer. Thankfully, unwinders and debuggers
  * already have baked-in strategies for attempting to unwind out of signals.
  */
-       .cfi_def_cfa    x29, 0
-       .cfi_offset     x29, 0 * 8
-       .cfi_offset     x30, 1 * 8
+//     .cfi_def_cfa    x29, 0
+//     .cfi_offset     x29, 0 * 8
+//     .cfi_offset     x30, 1 * 8
 
 /*
  * This mysterious NOP is required for some unwinders (e.g. libc++) that
        nop     // Mysterious NOP
 
 /*
- * GDB relies on being able to identify the sigreturn instruction sequence to
- * unwind from signal handlers. We cannot, therefore, use SYM_FUNC_START()
- * here, as it will emit a BTI C instruction and break the unwinder. Thankfully,
- * this function is only ever called from a RET and so omitting the landing pad
- * is perfectly fine.
+ * GDB, libgcc and libunwind rely on being able to identify the sigreturn
+ * instruction sequence to unwind from signal handlers. We cannot, therefore,
+ * use SYM_FUNC_START() here, as it will emit a BTI C instruction and break the
+ * unwinder. Thankfully, this function is only ever called from a RET and so
+ * omitting the landing pad is perfectly fine.
  */
 SYM_CODE_START(__kernel_rt_sigreturn)
+//     PLEASE DO NOT MODIFY
        mov     x8, #__NR_rt_sigreturn
+//     PLEASE DO NOT MODIFY
        svc     #0
-       .cfi_endproc
+//     PLEASE DO NOT MODIFY
+//     .cfi_endproc
 SYM_CODE_END(__kernel_rt_sigreturn)
 
 emit_aarch64_feature_1_and
index 7ea1e82..5139a5f 100644 (file)
@@ -14,7 +14,7 @@ COMPAT_GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE_COMPAT)elfedit))
 COMPAT_GCC_TOOLCHAIN := $(realpath $(COMPAT_GCC_TOOLCHAIN_DIR)/..)
 
 CC_COMPAT_CLANG_FLAGS := --target=$(notdir $(CROSS_COMPILE_COMPAT:%-=%))
-CC_COMPAT_CLANG_FLAGS += --prefix=$(COMPAT_GCC_TOOLCHAIN_DIR)
+CC_COMPAT_CLANG_FLAGS += --prefix=$(COMPAT_GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE_COMPAT))
 CC_COMPAT_CLANG_FLAGS += -no-integrated-as -Qunused-arguments
 ifneq ($(COMPAT_GCC_TOOLCHAIN),)
 CC_COMPAT_CLANG_FLAGS += --gcc-toolchain=$(COMPAT_GCC_TOOLCHAIN)
@@ -140,7 +140,6 @@ hostprogs := $(munge)
 
 c-obj-vdso := note.o
 c-obj-vdso-gettimeofday := vgettimeofday.o
-asm-obj-vdso := sigreturn.o
 
 ifneq ($(c-gettimeofday-y),)
 VDSO_CFLAGS_gettimeofday_o += -include $(c-gettimeofday-y)
diff --git a/arch/arm64/kernel/vdso32/sigreturn.S b/arch/arm64/kernel/vdso32/sigreturn.S
deleted file mode 100644 (file)
index b009106..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * This file provides both A32 and T32 versions, in accordance with the
- * arm sigreturn code.
- *
- * Please read the comments in arch/arm64/kernel/vdso/sigreturn.S to
- * understand some of the craziness in here.
- *
- * Copyright (C) 2018 ARM Limited
- */
-
-#include <linux/linkage.h>
-#include <asm/asm-offsets.h>
-#include <asm/unistd.h>
-
-       .text
-
-       .arm
-       .fnstart
-       .save {r0-r15}
-       .pad #COMPAT_SIGFRAME_REGS_OFFSET
-       nop
-SYM_CODE_START(__kernel_sigreturn_arm)
-       mov r7, #__NR_compat_sigreturn
-       svc #0
-       .fnend
-SYM_CODE_END(__kernel_sigreturn_arm)
-
-       .fnstart
-       .save {r0-r15}
-       .pad #COMPAT_RT_SIGFRAME_REGS_OFFSET
-       nop
-SYM_CODE_START(__kernel_rt_sigreturn_arm)
-       mov r7, #__NR_compat_rt_sigreturn
-       svc #0
-       .fnend
-SYM_CODE_END(__kernel_rt_sigreturn_arm)
-
-       .thumb
-       .fnstart
-       .save {r0-r15}
-       .pad #COMPAT_SIGFRAME_REGS_OFFSET
-       nop
-SYM_CODE_START(__kernel_sigreturn_thumb)
-       mov r7, #__NR_compat_sigreturn
-       svc #0
-       .fnend
-SYM_CODE_END(__kernel_sigreturn_thumb)
-
-       .fnstart
-       .save {r0-r15}
-       .pad #COMPAT_RT_SIGFRAME_REGS_OFFSET
-       nop
-SYM_CODE_START(__kernel_rt_sigreturn_thumb)
-       mov r7, #__NR_compat_rt_sigreturn
-       svc #0
-       .fnend
-SYM_CODE_END(__kernel_rt_sigreturn_thumb)
index a394492..337d035 100644 (file)
@@ -64,19 +64,7 @@ VERSION
                __vdso_clock_gettime;
                __vdso_gettimeofday;
                __vdso_clock_getres;
-               __kernel_sigreturn_arm;
-               __kernel_sigreturn_thumb;
-               __kernel_rt_sigreturn_arm;
-               __kernel_rt_sigreturn_thumb;
                __vdso_clock_gettime64;
        local: *;
        };
 }
-
-/*
- * Make the sigreturn code visible to the kernel.
- */
-VDSO_compat_sigreturn_arm      = __kernel_sigreturn_arm;
-VDSO_compat_sigreturn_thumb    = __kernel_sigreturn_thumb;
-VDSO_compat_rt_sigreturn_arm   = __kernel_rt_sigreturn_arm;
-VDSO_compat_rt_sigreturn_thumb = __kernel_rt_sigreturn_thumb;
index 6827da7..5423ffe 100644 (file)
@@ -165,9 +165,6 @@ SECTIONS
                *(.altinstructions)
                __alt_instructions_end = .;
        }
-       .altinstr_replacement : {
-               *(.altinstr_replacement)
-       }
 
        . = ALIGN(SEGMENT_ALIGN);
        __inittext_end = .;
index 6e6ed55..e76c0e8 100644 (file)
@@ -136,11 +136,15 @@ SYM_CODE_START(__kvm_handle_stub_hvc)
 
 1:     cmp     x0, #HVC_RESET_VECTORS
        b.ne    1f
-reset:
+
        /*
-        * Reset kvm back to the hyp stub. Do not clobber x0-x4 in
-        * case we coming via HVC_SOFT_RESTART.
+        * Set the HVC_RESET_VECTORS return code before entering the common
+        * path so that we do not clobber x0-x2 in case we are coming via
+        * HVC_SOFT_RESTART.
         */
+       mov     x0, xzr
+reset:
+       /* Reset kvm back to the hyp stub. */
        mrs     x5, sctlr_el2
        mov_q   x6, SCTLR_ELx_FLAGS
        bic     x5, x5, x6              // Clear SCTL_M and etc
@@ -151,7 +155,6 @@ reset:
        /* Install stub vectors */
        adr_l   x5, __hyp_stub_vectors
        msr     vbar_el2, x5
-       mov     x0, xzr
        eret
 
 1:     /* Bad stub call */
index b5ae3a5..3c22416 100644 (file)
@@ -159,7 +159,10 @@ static void kvm_vcpu_pmu_disable_el0(unsigned long events)
 }
 
 /*
- * On VHE ensure that only guest events have EL0 counting enabled
+ * On VHE ensure that only guest events have EL0 counting enabled.
+ * This is called from both vcpu_{load,put} and the sysreg handling.
+ * Since the latter is preemptible, special care must be taken to
+ * disable preemption.
  */
 void kvm_vcpu_pmu_restore_guest(struct kvm_vcpu *vcpu)
 {
@@ -169,12 +172,14 @@ void kvm_vcpu_pmu_restore_guest(struct kvm_vcpu *vcpu)
        if (!has_vhe())
                return;
 
+       preempt_disable();
        host = this_cpu_ptr(&kvm_host_data);
        events_guest = host->pmu_events.events_guest;
        events_host = host->pmu_events.events_host;
 
        kvm_vcpu_pmu_enable_el0(events_guest);
        kvm_vcpu_pmu_disable_el0(events_host);
+       preempt_enable();
 }
 
 /*
index 1e0f4c2..f7b52ce 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/arm-smccc.h>
 #include <linux/kvm_host.h>
+#include <linux/sched/stat.h>
 
 #include <asm/kvm_mmu.h>
 #include <asm/pvclock-abi.h>
@@ -73,6 +74,11 @@ gpa_t kvm_init_stolen_time(struct kvm_vcpu *vcpu)
        return base;
 }
 
+static bool kvm_arm_pvtime_supported(void)
+{
+       return !!sched_info_on();
+}
+
 int kvm_arm_pvtime_set_attr(struct kvm_vcpu *vcpu,
                            struct kvm_device_attr *attr)
 {
@@ -82,7 +88,8 @@ int kvm_arm_pvtime_set_attr(struct kvm_vcpu *vcpu,
        int ret = 0;
        int idx;
 
-       if (attr->attr != KVM_ARM_VCPU_PVTIME_IPA)
+       if (!kvm_arm_pvtime_supported() ||
+           attr->attr != KVM_ARM_VCPU_PVTIME_IPA)
                return -ENXIO;
 
        if (get_user(ipa, user))
@@ -110,7 +117,8 @@ int kvm_arm_pvtime_get_attr(struct kvm_vcpu *vcpu,
        u64 __user *user = (u64 __user *)attr->addr;
        u64 ipa;
 
-       if (attr->attr != KVM_ARM_VCPU_PVTIME_IPA)
+       if (!kvm_arm_pvtime_supported() ||
+           attr->attr != KVM_ARM_VCPU_PVTIME_IPA)
                return -ENXIO;
 
        ipa = vcpu->arch.steal.base;
@@ -125,7 +133,8 @@ int kvm_arm_pvtime_has_attr(struct kvm_vcpu *vcpu,
 {
        switch (attr->attr) {
        case KVM_ARM_VCPU_PVTIME_IPA:
-               return 0;
+               if (kvm_arm_pvtime_supported())
+                       return 0;
        }
        return -ENXIO;
 }
index d3b2090..6ed36be 100644 (file)
@@ -245,7 +245,7 @@ static int kvm_vcpu_enable_ptrauth(struct kvm_vcpu *vcpu)
  */
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
 {
-       int ret = -EINVAL;
+       int ret;
        bool loaded;
        u32 pstate;
 
@@ -269,15 +269,19 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
 
        if (test_bit(KVM_ARM_VCPU_PTRAUTH_ADDRESS, vcpu->arch.features) ||
            test_bit(KVM_ARM_VCPU_PTRAUTH_GENERIC, vcpu->arch.features)) {
-               if (kvm_vcpu_enable_ptrauth(vcpu))
+               if (kvm_vcpu_enable_ptrauth(vcpu)) {
+                       ret = -EINVAL;
                        goto out;
+               }
        }
 
        switch (vcpu->arch.target) {
        default:
                if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) {
-                       if (!cpus_have_const_cap(ARM64_HAS_32BIT_EL1))
+                       if (!cpus_have_const_cap(ARM64_HAS_32BIT_EL1)) {
+                               ret = -EINVAL;
                                goto out;
+                       }
                        pstate = VCPU_RESET_PSTATE_SVC;
                } else {
                        pstate = VCPU_RESET_PSTATE_EL1;
index 27ac833..b5fa73c 100644 (file)
@@ -90,7 +90,15 @@ static irqreturn_t vgic_v4_doorbell_handler(int irq, void *info)
            !irqd_irq_disabled(&irq_to_desc(irq)->irq_data))
                disable_irq_nosync(irq);
 
+       /*
+        * The v4.1 doorbell can fire concurrently with the vPE being
+        * made non-resident. Ensure we only update pending_last
+        * *after* the non-residency sequence has completed.
+        */
+       raw_spin_lock(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe.vpe_lock);
        vcpu->arch.vgic_cpu.vgic_v3.its_vpe.pending_last = true;
+       raw_spin_unlock(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe.vpe_lock);
+
        kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu);
        kvm_vcpu_kick(vcpu);
 
index e631e64..1e93cfc 100644 (file)
@@ -404,11 +404,6 @@ void __init arm64_memblock_init(void)
        high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
 
        dma_contiguous_reserve(arm64_dma32_phys_limit);
-
-#ifdef CONFIG_ARM64_4K_PAGES
-       hugetlb_cma_reserve(PUD_SHIFT - PAGE_SHIFT);
-#endif
-
 }
 
 void __init bootmem_init(void)
@@ -424,6 +419,16 @@ void __init bootmem_init(void)
        min_low_pfn = min;
 
        arm64_numa_init();
+
+       /*
+        * must be done after arm64_numa_init() which calls numa_init() to
+        * initialize node_online_map that gets used in hugetlb_cma_reserve()
+        * while allocating required CMA size across online nodes.
+        */
+#ifdef CONFIG_ARM64_4K_PAGES
+       hugetlb_cma_reserve(PUD_SHIFT - PAGE_SHIFT);
+#endif
+
        /*
         * Sparsemem tries to allocate bootmem in memory_present(), so must be
         * done after the fixed reservations.
index 990929c..1df25f2 100644 (file)
@@ -723,6 +723,7 @@ int kern_addr_valid(unsigned long addr)
        pmd_t *pmdp, pmd;
        pte_t *ptep, pte;
 
+       addr = arch_kasan_reset_tag(addr);
        if ((((long)addr) >> VA_BITS) != -1UL)
                return 0;
 
index 3c425b8..b4a7ec1 100644 (file)
@@ -72,7 +72,8 @@ static int ftrace_check_current_nop(unsigned long hook)
        uint16_t olds[7];
        unsigned long hook_pos = hook - 2;
 
-       if (probe_kernel_read((void *)olds, (void *)hook_pos, sizeof(nops)))
+       if (copy_from_kernel_nofault((void *)olds, (void *)hook_pos,
+                       sizeof(nops)))
                return -EFAULT;
 
        if (memcmp((void *)nops, (void *)olds, sizeof(nops))) {
@@ -97,7 +98,7 @@ static int ftrace_modify_code(unsigned long hook, unsigned long target,
 
        make_jbsr(target, hook, call, nolr);
 
-       ret = probe_kernel_write((void *)hook_pos, enable ? call : nops,
+       ret = copy_to_kernel_nofault((void *)hook_pos, enable ? call : nops,
                                 sizeof(nops));
        if (ret)
                return -EPERM;
index cea15f2..3a033d2 100644 (file)
@@ -35,7 +35,7 @@ static inline void *dereference_function_descriptor(void *ptr)
        struct fdesc *desc = ptr;
        void *p;
 
-       if (!probe_kernel_address(&desc->ip, p))
+       if (!get_kernel_nofault(p, (void *)&desc->ip))
                ptr = p;
        return ptr;
 }
index cee411e..b2ab2d5 100644 (file)
@@ -108,7 +108,7 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code,
                goto skip_check;
 
        /* read the text we want to modify */
-       if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
+       if (copy_from_kernel_nofault(replaced, (void *)ip, MCOUNT_INSN_SIZE))
                return -EFAULT;
 
        /* Make sure it is what we expect it to be */
@@ -117,7 +117,7 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code,
 
 skip_check:
        /* replace the text with the new text */
-       if (probe_kernel_write(((void *)ip), new_code, MCOUNT_INSN_SIZE))
+       if (copy_to_kernel_nofault(((void *)ip), new_code, MCOUNT_INSN_SIZE))
                return -EPERM;
        flush_icache_range(ip, ip + MCOUNT_INSN_SIZE);
 
@@ -129,7 +129,7 @@ static int ftrace_make_nop_check(struct dyn_ftrace *rec, unsigned long addr)
        unsigned char __attribute__((aligned(8))) replaced[MCOUNT_INSN_SIZE];
        unsigned long ip = rec->ip;
 
-       if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
+       if (copy_from_kernel_nofault(replaced, (void *)ip, MCOUNT_INSN_SIZE))
                return -EFAULT;
        if (rec->flags & FTRACE_FL_CONVERTED) {
                struct ftrace_call_insn *call_insn, *tmp_call;
index 67994a7..1dd57ba 100644 (file)
@@ -42,7 +42,7 @@ enum unw_register_index {
 
 struct unw_info_block {
        u64 header;
-       u64 desc[0];            /* unwind descriptors */
+       u64 desc[];             /* unwind descriptors */
        /* personality routine and language-specific data follow behind descriptors */
 };
 
index e779b19..f66f4b1 100644 (file)
@@ -138,7 +138,8 @@ void __init setup_arch(char **cmdline_p)
        pr_debug("MEMORY -> ROMFS=0x%p-0x%06lx MEM=0x%06lx-0x%06lx\n ",
                 __bss_stop, memory_start, memory_start, memory_end);
 
-       memblock_add(memory_start, memory_end - memory_start);
+       memblock_add(_rambase, memory_end - _rambase);
+       memblock_reserve(_rambase, memory_start - _rambase);
 
        /* Keep a copy of command line */
        *cmdline_p = &command_line[0];
index 29f4792..7d04210 100644 (file)
@@ -174,7 +174,7 @@ void __init cf_bootmem_alloc(void)
        m68k_memory[0].addr = _rambase;
        m68k_memory[0].size = _ramend - _rambase;
 
-       memblock_add(m68k_memory[0].addr, m68k_memory[0].size);
+       memblock_add_node(m68k_memory[0].addr, m68k_memory[0].size, 0);
 
        /* compute total pages in system */
        num_pages = PFN_DOWN(_ramend - _rambase);
index 8d22828..bc72304 100644 (file)
@@ -92,7 +92,7 @@
                        "MIC1N", "Built-in Mic";
                simple-audio-card,pin-switches = "Speaker", "Headphones";
 
-               simple-audio-card,hp-det-gpio = <&gpf 21 GPIO_ACTIVE_HIGH>;
+               simple-audio-card,hp-det-gpio = <&gpf 21 GPIO_ACTIVE_LOW>;
                simple-audio-card,aux-devs = <&speaker_amp>, <&headphones_amp>;
 
                simple-audio-card,bitclock-master = <&dai_codec>;
index c628747..7dd4a80 100644 (file)
                                                                \
        /*                                                      \
         * We can't unroll if the number of iterations isn't    \
-        * compile-time constant. Unfortunately GCC versions    \
-        * up until 4.6 tend to miss obvious constants & cause  \
+        * compile-time constant. Unfortunately clang versions  \
+        * up until 8.0 tend to miss obvious constants & cause  \
         * this check to fail, even though they go on to        \
         * generate reasonable code for the switch statement,   \
         * so we skip the sanity check for those compilers.     \
         */                                                     \
-       BUILD_BUG_ON((CONFIG_GCC_VERSION >= 40700 ||            \
-                     CONFIG_CLANG_VERSION >= 80000) &&         \
-                    !__builtin_constant_p(times));             \
+       BUILD_BUG_ON(!__builtin_constant_p(times));             \
                                                                \
        switch (times) {                                        \
        case 32: fn(__VA_ARGS__); /* fall through */            \
index 6cfae24..d043c2f 100644 (file)
@@ -86,9 +86,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
                goto out;
        }
 
-       if ((probe_kernel_read(&prev_insn, p->addr - 1,
-                               sizeof(mips_instruction)) == 0) &&
-                               insn_has_delayslot(prev_insn)) {
+       if (copy_from_kernel_nofault(&prev_insn, p->addr - 1,
+                       sizeof(mips_instruction)) == 0 &&
+           insn_has_delayslot(prev_insn)) {
                pr_notice("Kprobes for branch delayslot are not supported\n");
                ret = -EINVAL;
                goto out;
index 7c32c95..f655af6 100644 (file)
@@ -723,12 +723,14 @@ static int simulate_loongson3_cpucfg(struct pt_regs *regs,
                perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
 
                /* Do not emulate on unsupported core models. */
-               if (!loongson3_cpucfg_emulation_enabled(&current_cpu_data))
+               preempt_disable();
+               if (!loongson3_cpucfg_emulation_enabled(&current_cpu_data)) {
+                       preempt_enable();
                        return -1;
-
+               }
                regs->regs[rd] = loongson3_cpucfg_read_synthesized(
                        &current_cpu_data, sel);
-
+               preempt_enable();
                return 0;
        }
 
@@ -2169,6 +2171,7 @@ static void configure_status(void)
 
        change_c0_status(ST0_CU|ST0_MX|ST0_RE|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
                         status_set);
+       back_to_back_c0_hazard();
 }
 
 unsigned int hwrena;
index 5ae82d9..d242300 100644 (file)
@@ -1722,6 +1722,7 @@ enum emulation_result kvm_mips_emulate_store(union mips_instruction inst,
                          vcpu->arch.gprs[rt], *(u32 *)data);
                break;
 
+#if defined(CONFIG_64BIT) && defined(CONFIG_KVM_MIPS_VZ)
        case sdl_op:
                run->mmio.phys_addr = kvm_mips_callbacks->gva_to_gpa(
                                        vcpu->arch.host_cp0_badvaddr) & (~0x7);
@@ -1815,6 +1816,7 @@ enum emulation_result kvm_mips_emulate_store(union mips_instruction inst,
                          vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr,
                          vcpu->arch.gprs[rt], *(u64 *)data);
                break;
+#endif
 
 #ifdef CONFIG_CPU_LOONGSON64
        case sdc2_op:
@@ -2002,6 +2004,7 @@ enum emulation_result kvm_mips_emulate_load(union mips_instruction inst,
                }
                break;
 
+#if defined(CONFIG_64BIT) && defined(CONFIG_KVM_MIPS_VZ)
        case ldl_op:
                run->mmio.phys_addr = kvm_mips_callbacks->gva_to_gpa(
                                        vcpu->arch.host_cp0_badvaddr) & (~0x7);
@@ -2073,6 +2076,7 @@ enum emulation_result kvm_mips_emulate_load(union mips_instruction inst,
                        break;
                }
                break;
+#endif
 
 #ifdef CONFIG_CPU_LOONGSON64
        case ldc2_op:
index 521bd58..666d335 100644 (file)
@@ -67,7 +67,9 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        VCPU_STAT("vz_ghfc", vz_ghfc_exits),
        VCPU_STAT("vz_gpa", vz_gpa_exits),
        VCPU_STAT("vz_resvd", vz_resvd_exits),
+#ifdef CONFIG_CPU_LOONGSON64
        VCPU_STAT("vz_cpucfg", vz_cpucfg_exits),
+#endif
 #endif
        VCPU_STAT("halt_successful_poll", halt_successful_poll),
        VCPU_STAT("halt_attempted_poll", halt_attempted_poll),
index aa37545..b103420 100644 (file)
@@ -514,8 +514,8 @@ void __init ltq_soc_init(void)
                clkdev_add_pmu("1e10b308.eth", NULL, 0, 0, PMU_SWITCH |
                               PMU_PPE_DP | PMU_PPE_TC);
                clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
-               clkdev_add_pmu("1e108000.gswip", "gphy0", 0, 0, PMU_GPHY);
-               clkdev_add_pmu("1e108000.gswip", "gphy1", 0, 0, PMU_GPHY);
+               clkdev_add_pmu("1e108000.switch", "gphy0", 0, 0, PMU_GPHY);
+               clkdev_add_pmu("1e108000.switch", "gphy1", 0, 0, PMU_GPHY);
                clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
                clkdev_add_pmu("1e116000.mei", "afe", 1, 2, PMU_ANALOG_DSL_AFE);
                clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
@@ -538,8 +538,8 @@ void __init ltq_soc_init(void)
                                PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
                                PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
                                PMU_PPE_QSB | PMU_PPE_TOP);
-               clkdev_add_pmu("1e108000.gswip", "gphy0", 0, 0, PMU_GPHY);
-               clkdev_add_pmu("1e108000.gswip", "gphy1", 0, 0, PMU_GPHY);
+               clkdev_add_pmu("1e108000.switch", "gphy0", 0, 0, PMU_GPHY);
+               clkdev_add_pmu("1e108000.switch", "gphy1", 0, 0, PMU_GPHY);
                clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO);
                clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
                clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
index 3b2552f..5958217 100644 (file)
@@ -627,9 +627,10 @@ static int bridge_probe(struct platform_device *pdev)
                return -ENOMEM;
        domain = irq_domain_create_hierarchy(parent, 0, 8, fn,
                                             &bridge_domain_ops, NULL);
-       irq_domain_free_fwnode(fn);
-       if (!domain)
+       if (!domain) {
+               irq_domain_free_fwnode(fn);
                return -ENOMEM;
+       }
 
        pci_set_flags(PCI_PROBE_ONLY);
 
index 22ab77e..3763b3f 100644 (file)
@@ -131,13 +131,14 @@ static int __ftrace_modify_code(unsigned long pc, unsigned long *old_insn,
        unsigned long orig_insn[3];
 
        if (validate) {
-               if (probe_kernel_read(orig_insn, (void *)pc, MCOUNT_INSN_SIZE))
+               if (copy_from_kernel_nofault(orig_insn, (void *)pc,
+                               MCOUNT_INSN_SIZE))
                        return -EFAULT;
                if (memcmp(orig_insn, old_insn, MCOUNT_INSN_SIZE))
                        return -EINVAL;
        }
 
-       if (probe_kernel_write((void *)pc, new_insn, MCOUNT_INSN_SIZE))
+       if (copy_to_kernel_nofault((void *)pc, new_insn, MCOUNT_INSN_SIZE))
                return -EPERM;
 
        return 0;
index c152a68..3457276 100644 (file)
@@ -74,8 +74,11 @@ void *arch_dma_set_uncached(void *cpu_addr, size_t size)
         * We need to iterate through the pages, clearing the dcache for
         * them and setting the cache-inhibit bit.
         */
+       mmap_read_lock(&init_mm);
        error = walk_page_range(&init_mm, va, va + size, &set_nocache_walk_ops,
                        NULL);
+       mmap_read_unlock(&init_mm);
+
        if (error)
                return ERR_PTR(error);
        return cpu_addr;
@@ -85,9 +88,11 @@ void arch_dma_clear_uncached(void *cpu_addr, size_t size)
 {
        unsigned long va = (unsigned long)cpu_addr;
 
+       mmap_read_lock(&init_mm);
        /* walk_page_range shouldn't be able to fail here */
        WARN_ON(walk_page_range(&init_mm, va, va + size,
                        &clear_nocache_walk_ops, NULL));
+       mmap_read_unlock(&init_mm);
 }
 
 void arch_sync_dma_for_device(phys_addr_t addr, size_t size,
index 118953d..6dd4171 100644 (file)
@@ -212,6 +212,8 @@ atomic64_set(atomic64_t *v, s64 i)
        _atomic_spin_unlock_irqrestore(v, flags);
 }
 
+#define atomic64_set_release(v, i)     atomic64_set((v), (i))
+
 static __inline__ s64
 atomic64_read(const atomic64_t *v)
 {
index ab5c215..0689585 100644 (file)
@@ -60,6 +60,7 @@ extern void __cmpxchg_called_with_bad_pointer(void);
 extern unsigned long __cmpxchg_u32(volatile unsigned int *m, unsigned int old,
                                   unsigned int new_);
 extern u64 __cmpxchg_u64(volatile u64 *ptr, u64 old, u64 new_);
+extern u8 __cmpxchg_u8(volatile u8 *ptr, u8 old, u8 new_);
 
 /* don't worry...optimizer will get rid of most of this */
 static inline unsigned long
@@ -71,6 +72,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size)
 #endif
        case 4: return __cmpxchg_u32((unsigned int *)ptr,
                                     (unsigned int)old, (unsigned int)new_);
+       case 1: return __cmpxchg_u8((u8 *)ptr, (u8)old, (u8)new_);
        }
        __cmpxchg_called_with_bad_pointer();
        return old;
index b836fc6..1df0f67 100644 (file)
@@ -172,7 +172,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 
        ip = (void *)(rec->ip + 4 - size);
 
-       ret = probe_kernel_read(insn, ip, size);
+       ret = copy_from_kernel_nofault(insn, ip, size);
        if (ret)
                return ret;
 
index 664278d..c4554ac 100644 (file)
@@ -154,8 +154,8 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
 
 int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
 {
-       int ret = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
-                               BREAK_INSTR_SIZE);
+       int ret = copy_from_kernel_nofault(bpt->saved_instr,
+                       (char *)bpt->bpt_addr, BREAK_INSTR_SIZE);
        if (ret)
                return ret;
 
index 230a642..b7abb12 100644 (file)
@@ -293,7 +293,7 @@ void *dereference_function_descriptor(void *ptr)
        Elf64_Fdesc *desc = ptr;
        void *p;
 
-       if (!probe_kernel_address(&desc->addr, p))
+       if (!get_kernel_nofault(p, (void *)&desc->addr))
                ptr = p;
        return ptr;
 }
index 70ffbcf..2e4d1f0 100644 (file)
@@ -79,3 +79,15 @@ unsigned long __cmpxchg_u32(volatile unsigned int *ptr, unsigned int old, unsign
        _atomic_spin_unlock_irqrestore(ptr, flags);
        return (unsigned long)prev;
 }
+
+u8 __cmpxchg_u8(volatile u8 *ptr, u8 old, u8 new)
+{
+       unsigned long flags;
+       u8 prev;
+
+       _atomic_spin_lock_irqsave(ptr, flags);
+       if ((prev = *ptr) == old)
+               *ptr = new;
+       _atomic_spin_unlock_irqrestore(ptr, flags);
+       return prev;
+}
index 94a9fe2..4b75388 100644 (file)
@@ -57,7 +57,7 @@ void * memcpy(void * dst,const void *src, size_t count)
 EXPORT_SYMBOL(raw_copy_in_user);
 EXPORT_SYMBOL(memcpy);
 
-bool probe_kernel_read_allowed(const void *unsafe_src, size_t size)
+bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
 {
        if ((unsigned long)unsafe_src < PAGE_SIZE)
                return false;
index 965b1f3..b0c70a3 100644 (file)
@@ -77,6 +77,8 @@ struct coprocessor_completion_block {
 #define CSB_CC_CHAIN           (37)
 #define CSB_CC_SEQUENCE                (38)
 #define CSB_CC_HW              (39)
+/* P9 DD2 NX Workbook 3.2 (Table 4-36): Address translation fault */
+#define        CSB_CC_FAULT_ADDRESS    (250)
 
 #define CSB_SIZE               (0x10)
 #define CSB_ALIGN              CSB_SIZE
index b56f141..b0afbdd 100644 (file)
@@ -205,10 +205,6 @@ static inline void pmd_clear(pmd_t *pmdp)
        *pmdp = __pmd(0);
 }
 
-/* to find an entry in a page-table-directory */
-#define pgd_index(address)      ((address) >> PGDIR_SHIFT)
-#define pgd_offset(mm, address)         ((mm)->pgd + pgd_index(address))
-
 /*
  * PTE updates. This function is called whenever an existing
  * valid PTE is updated. This does -not- include set_pte_at()
@@ -230,6 +226,8 @@ static inline void pmd_clear(pmd_t *pmdp)
  * For other page sizes, we have a single entry in the table.
  */
 #ifdef CONFIG_PPC_8xx
+static pmd_t *pmd_off(struct mm_struct *mm, unsigned long addr);
+
 static inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, pte_t *p,
                                     unsigned long clr, unsigned long set, int huge)
 {
@@ -237,7 +235,7 @@ static inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, p
        pte_basic_t old = pte_val(*p);
        pte_basic_t new = (old & ~(pte_basic_t)clr) | set;
        int num, i;
-       pmd_t *pmd = pmd_offset(pud_offset(p4d_offset(pgd_offset(mm, addr), addr), addr), addr);
+       pmd_t *pmd = pmd_off(mm, addr);
 
        if (!huge)
                num = PAGE_SIZE / SZ_4K;
@@ -286,6 +284,16 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
        return __pte(pte_update(mm, addr, ptep, ~0, 0, 0));
 }
 
+#if defined(CONFIG_PPC_8xx) && defined(CONFIG_PPC_16K_PAGES)
+#define __HAVE_ARCH_PTEP_GET
+static inline pte_t ptep_get(pte_t *ptep)
+{
+       pte_t pte = {READ_ONCE(ptep->pte), 0, 0, 0};
+
+       return pte;
+}
+#endif
+
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
 static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
                                      pte_t *ptep)
index d198717..324d7b2 100644 (file)
@@ -85,7 +85,7 @@ static inline void *dereference_function_descriptor(void *ptr)
        struct ppc64_opd_entry *desc = ptr;
        void *p;
 
-       if (!probe_kernel_address(&desc->funcaddr, p))
+       if (!get_kernel_nofault(p, (void *)&desc->funcaddr))
                ptr = p;
        return ptr;
 }
diff --git a/arch/powerpc/include/uapi/asm/papr_pdsm.h b/arch/powerpc/include/uapi/asm/papr_pdsm.h
new file mode 100644 (file)
index 0000000..9ccecc1
--- /dev/null
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * PAPR nvDimm Specific Methods (PDSM) and structs for libndctl
+ *
+ * (C) Copyright IBM 2020
+ *
+ * Author: Vaibhav Jain <vaibhav at linux.ibm.com>
+ */
+
+#ifndef _UAPI_ASM_POWERPC_PAPR_PDSM_H_
+#define _UAPI_ASM_POWERPC_PAPR_PDSM_H_
+
+#include <linux/types.h>
+#include <linux/ndctl.h>
+
+/*
+ * PDSM Envelope:
+ *
+ * The ioctl ND_CMD_CALL exchange data between user-space and kernel via
+ * envelope which consists of 2 headers sections and payload sections as
+ * illustrated below:
+ *  +-----------------+---------------+---------------------------+
+ *  |   64-Bytes      |   8-Bytes     |       Max 184-Bytes       |
+ *  +-----------------+---------------+---------------------------+
+ *  | ND-HEADER       |  PDSM-HEADER  |      PDSM-PAYLOAD         |
+ *  +-----------------+---------------+---------------------------+
+ *  | nd_family       |               |                           |
+ *  | nd_size_out     | cmd_status    |                           |
+ *  | nd_size_in      | reserved      |     nd_pdsm_payload       |
+ *  | nd_command      | payload   --> |                           |
+ *  | nd_fw_size      |               |                           |
+ *  | nd_payload ---> |               |                           |
+ *  +---------------+-----------------+---------------------------+
+ *
+ * ND Header:
+ * This is the generic libnvdimm header described as 'struct nd_cmd_pkg'
+ * which is interpreted by libnvdimm before passed on to papr_scm. Important
+ * member fields used are:
+ * 'nd_family'         : (In) NVDIMM_FAMILY_PAPR_SCM
+ * 'nd_size_in'                : (In) PDSM-HEADER + PDSM-IN-PAYLOAD (usually 0)
+ * 'nd_size_out'        : (In) PDSM-HEADER + PDSM-RETURN-PAYLOAD
+ * 'nd_command'         : (In) One of PAPR_PDSM_XXX
+ * 'nd_fw_size'         : (Out) PDSM-HEADER + size of actual payload returned
+ *
+ * PDSM Header:
+ * This is papr-scm specific header that precedes the payload. This is defined
+ * as nd_cmd_pdsm_pkg.  Following fields aare available in this header:
+ *
+ * 'cmd_status'                : (Out) Errors if any encountered while servicing PDSM.
+ * 'reserved'          : Not used, reserved for future and should be set to 0.
+ * 'payload'            : A union of all the possible payload structs
+ *
+ * PDSM Payload:
+ *
+ * The layout of the PDSM Payload is defined by various structs shared between
+ * papr_scm and libndctl so that contents of payload can be interpreted. As such
+ * its defined as a union of all possible payload structs as
+ * 'union nd_pdsm_payload'. Based on the value of 'nd_cmd_pkg.nd_command'
+ * appropriate member of the union is accessed.
+ */
+
+/* Max payload size that we can handle */
+#define ND_PDSM_PAYLOAD_MAX_SIZE 184
+
+/* Max payload size that we can handle */
+#define ND_PDSM_HDR_SIZE \
+       (sizeof(struct nd_pkg_pdsm) - ND_PDSM_PAYLOAD_MAX_SIZE)
+
+/* Various nvdimm health indicators */
+#define PAPR_PDSM_DIMM_HEALTHY       0
+#define PAPR_PDSM_DIMM_UNHEALTHY     1
+#define PAPR_PDSM_DIMM_CRITICAL      2
+#define PAPR_PDSM_DIMM_FATAL         3
+
+/*
+ * Struct exchanged between kernel & ndctl in for PAPR_PDSM_HEALTH
+ * Various flags indicate the health status of the dimm.
+ *
+ * extension_flags     : Any extension fields present in the struct.
+ * dimm_unarmed                : Dimm not armed. So contents wont persist.
+ * dimm_bad_shutdown   : Previous shutdown did not persist contents.
+ * dimm_bad_restore    : Contents from previous shutdown werent restored.
+ * dimm_scrubbed       : Contents of the dimm have been scrubbed.
+ * dimm_locked         : Contents of the dimm cant be modified until CEC reboot
+ * dimm_encrypted      : Contents of dimm are encrypted.
+ * dimm_health         : Dimm health indicator. One of PAPR_PDSM_DIMM_XXXX
+ */
+struct nd_papr_pdsm_health {
+       union {
+               struct {
+                       __u32 extension_flags;
+                       __u8 dimm_unarmed;
+                       __u8 dimm_bad_shutdown;
+                       __u8 dimm_bad_restore;
+                       __u8 dimm_scrubbed;
+                       __u8 dimm_locked;
+                       __u8 dimm_encrypted;
+                       __u16 dimm_health;
+               };
+               __u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE];
+       };
+};
+
+/*
+ * Methods to be embedded in ND_CMD_CALL request. These are sent to the kernel
+ * via 'nd_cmd_pkg.nd_command' member of the ioctl struct
+ */
+enum papr_pdsm {
+       PAPR_PDSM_MIN = 0x0,
+       PAPR_PDSM_HEALTH,
+       PAPR_PDSM_MAX,
+};
+
+/* Maximal union that can hold all possible payload types */
+union nd_pdsm_payload {
+       struct nd_papr_pdsm_health health;
+       __u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE];
+} __packed;
+
+/*
+ * PDSM-header + payload expected with ND_CMD_CALL ioctl from libnvdimm
+ * Valid member of union 'payload' is identified via 'nd_cmd_pkg.nd_command'
+ * that should always precede this struct when sent to papr_scm via CMD_CALL
+ * interface.
+ */
+struct nd_pkg_pdsm {
+       __s32 cmd_status;       /* Out: Sub-cmd status returned back */
+       __u16 reserved[2];      /* Ignored and to be set as '0' */
+       union nd_pdsm_payload payload;
+} __packed;
+
+#endif /* _UAPI_ASM_POWERPC_PAPR_PDSM_H_ */
index e70ebb5..446e54c 100644 (file)
@@ -270,7 +270,7 @@ BEGIN_FTR_SECTION
 END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
        .endif
 
-       ld      r10,PACA_EXGEN+EX_CTR(r13)
+       ld      r10,IAREA+EX_CTR(r13)
        mtctr   r10
 BEGIN_FTR_SECTION
        ld      r10,IAREA+EX_PPR(r13)
@@ -298,7 +298,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
 
        .if IKVM_SKIP
 89:    mtocrf  0x80,r9
-       ld      r10,PACA_EXGEN+EX_CTR(r13)
+       ld      r10,IAREA+EX_CTR(r13)
        mtctr   r10
        ld      r9,IAREA+EX_R9(r13)
        ld      r10,IAREA+EX_R10(r13)
@@ -2551,7 +2551,7 @@ EXC_VIRT_NONE(0x5400, 0x100)
 INT_DEFINE_BEGIN(denorm_exception)
        IVEC=0x1500
        IHSRR=1
-       IBRANCH_COMMON=0
+       IBRANCH_TO_COMMON=0
        IKVM_REAL=1
 INT_DEFINE_END(denorm_exception)
 
@@ -3072,10 +3072,18 @@ do_hash_page:
        ori     r0,r0,DSISR_BAD_FAULT_64S@l
        and.    r0,r5,r0                /* weird error? */
        bne-    handle_page_fault       /* if not, try to insert a HPTE */
+
+       /*
+        * If we are in an "NMI" (e.g., an interrupt when soft-disabled), then
+        * don't call hash_page, just fail the fault. This is required to
+        * prevent re-entrancy problems in the hash code, namely perf
+        * interrupts hitting while something holds H_PAGE_BUSY, and taking a
+        * hash fault. See the comment in hash_preload().
+        */
        ld      r11, PACA_THREAD_INFO(r13)
-       lwz     r0,TI_PREEMPT(r11)      /* If we're in an "NMI" */
-       andis.  r0,r0,NMI_MASK@h        /* (i.e. an irq when soft-disabled) */
-       bne     77f                     /* then don't call hash_page now */
+       lwz     r0,TI_PREEMPT(r11)
+       andis.  r0,r0,NMI_MASK@h
+       bne     77f
 
        /*
         * r3 contains the trap number
index 652b285..4090802 100644 (file)
@@ -421,7 +421,7 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
        unsigned int instr;
        struct ppc_inst *addr = (struct ppc_inst *)bpt->bpt_addr;
 
-       err = probe_kernel_address(addr, instr);
+       err = get_kernel_nofault(instr, (unsigned *) addr);
        if (err)
                return err;
 
index 6f96f65..9cc792a 100644 (file)
@@ -289,7 +289,7 @@ int kprobe_handler(struct pt_regs *regs)
        if (!p) {
                unsigned int instr;
 
-               if (probe_kernel_address(addr, instr))
+               if (get_kernel_nofault(instr, addr))
                        goto no_kprobe;
 
                if (instr != BREAKPOINT_INSTRUCTION) {
index f4c2fa1..ae2b188 100644 (file)
@@ -756,7 +756,8 @@ int module_trampoline_target(struct module *mod, unsigned long addr,
 
        stub = (struct ppc64_stub_entry *)addr;
 
-       if (probe_kernel_read(&magic, &stub->magic, sizeof(magic))) {
+       if (copy_from_kernel_nofault(&magic, &stub->magic,
+                       sizeof(magic))) {
                pr_err("%s: fault reading magic for stub %lx for %s\n", __func__, addr, mod->name);
                return -EFAULT;
        }
@@ -766,7 +767,8 @@ int module_trampoline_target(struct module *mod, unsigned long addr,
                return -EFAULT;
        }
 
-       if (probe_kernel_read(&funcdata, &stub->funcdata, sizeof(funcdata))) {
+       if (copy_from_kernel_nofault(&funcdata, &stub->funcdata,
+                       sizeof(funcdata))) {
                pr_err("%s: fault reading funcdata for stub %lx for %s\n", __func__, addr, mod->name);
                 return -EFAULT;
        }
index 2168372..74da65a 100644 (file)
@@ -87,7 +87,7 @@ static void *__init alloc_shared_lppaca(unsigned long size, unsigned long align,
         * This is very early in boot, so no harm done if the kernel crashes at
         * this point.
         */
-       BUG_ON(shared_lppaca_size >= shared_lppaca_total_size);
+       BUG_ON(shared_lppaca_size > shared_lppaca_total_size);
 
        return ptr;
 }
index 7bb7faf..4650b9b 100644 (file)
@@ -1252,29 +1252,31 @@ struct task_struct *__switch_to(struct task_struct *prev,
 static void show_instructions(struct pt_regs *regs)
 {
        int i;
+       unsigned long nip = regs->nip;
        unsigned long pc = regs->nip - (NR_INSN_TO_PRINT * 3 / 4 * sizeof(int));
 
        printk("Instruction dump:");
 
+       /*
+        * If we were executing with the MMU off for instructions, adjust pc
+        * rather than printing XXXXXXXX.
+        */
+       if (!IS_ENABLED(CONFIG_BOOKE) && !(regs->msr & MSR_IR)) {
+               pc = (unsigned long)phys_to_virt(pc);
+               nip = (unsigned long)phys_to_virt(regs->nip);
+       }
+
        for (i = 0; i < NR_INSN_TO_PRINT; i++) {
                int instr;
 
                if (!(i % 8))
                        pr_cont("\n");
 
-#if !defined(CONFIG_BOOKE)
-               /* If executing with the IMMU off, adjust pc rather
-                * than print XXXXXXXX.
-                */
-               if (!(regs->msr & MSR_IR))
-                       pc = (unsigned long)phys_to_virt(pc);
-#endif
-
                if (!__kernel_text_address(pc) ||
-                   probe_kernel_address((const void *)pc, instr)) {
+                   get_kernel_nofault(instr, (const void *)pc)) {
                        pr_cont("XXXXXXXX ");
                } else {
-                       if (regs->nip == pc)
+                       if (nip == pc)
                                pr_cont("<%08x> ", instr);
                        else
                                pr_cont("%08x ", instr);
@@ -1305,7 +1307,8 @@ void show_user_instructions(struct pt_regs *regs)
                for (i = 0; i < 8 && n; i++, n--, pc += sizeof(int)) {
                        int instr;
 
-                       if (probe_user_read(&instr, (void __user *)pc, sizeof(instr))) {
+                       if (copy_from_user_nofault(&instr, (void __user *)pc,
+                                       sizeof(instr))) {
                                seq_buf_printf(&s, "XXXXXXXX ");
                                continue;
                        }
index 5e39962..c1fede6 100644 (file)
@@ -226,7 +226,7 @@ __ftrace_make_nop(struct module *mod,
        unsigned long ip = rec->ip;
        unsigned long tramp;
 
-       if (probe_kernel_read(&op, (void *)ip, MCOUNT_INSN_SIZE))
+       if (copy_from_kernel_nofault(&op, (void *)ip, MCOUNT_INSN_SIZE))
                return -EFAULT;
 
        /* Make sure that that this is still a 24bit jump */
@@ -249,7 +249,7 @@ __ftrace_make_nop(struct module *mod,
        pr_devel("ip:%lx jumps to %lx", ip, tramp);
 
        /* Find where the trampoline jumps to */
-       if (probe_kernel_read(jmp, (void *)tramp, sizeof(jmp))) {
+       if (copy_from_kernel_nofault(jmp, (void *)tramp, sizeof(jmp))) {
                pr_err("Failed to read %lx\n", tramp);
                return -EFAULT;
        }
index 3cb0c98..6a73714 100644 (file)
@@ -40,7 +40,8 @@ unsigned long __kvmhv_copy_tofrom_guest_radix(int lpid, int pid,
        /* Can't access quadrants 1 or 2 in non-HV mode, call the HV to do it */
        if (kvmhv_on_pseries())
                return plpar_hcall_norets(H_COPY_TOFROM_GUEST, lpid, pid, eaddr,
-                                         __pa(to), __pa(from), n);
+                                         (to != NULL) ? __pa(to): 0,
+                                         (from != NULL) ? __pa(from): 0, n);
 
        quadrant = 1;
        if (!pid)
@@ -64,9 +65,9 @@ unsigned long __kvmhv_copy_tofrom_guest_radix(int lpid, int pid,
        isync();
 
        if (is_load)
-               ret = probe_user_read(to, (const void __user *)from, n);
+               ret = copy_from_user_nofault(to, (const void __user *)from, n);
        else
-               ret = probe_user_write((void __user *)to, from, n);
+               ret = copy_to_user_nofault((void __user *)to, from, n);
 
        /* switch the pid first to avoid running host with unallocated pid */
        if (quadrant == 1 && pid != old_pid)
index aedfd6e..9cc17eb 100644 (file)
@@ -15,11 +15,11 @@ int probe_user_read_inst(struct ppc_inst *inst,
        unsigned int val, suffix;
        int err;
 
-       err = probe_user_read(&val, nip, sizeof(val));
+       err = copy_from_user_nofault(&val, nip, sizeof(val));
        if (err)
                return err;
        if (get_op(val) == OP_PREFIX) {
-               err = probe_user_read(&suffix, (void __user *)nip + 4, 4);
+               err = copy_from_user_nofault(&suffix, (void __user *)nip + 4, 4);
                *inst = ppc_inst_prefix(val, suffix);
        } else {
                *inst = ppc_inst(val);
@@ -33,11 +33,11 @@ int probe_kernel_read_inst(struct ppc_inst *inst,
        unsigned int val, suffix;
        int err;
 
-       err = probe_kernel_read(&val, src, sizeof(val));
+       err = copy_from_kernel_nofault(&val, src, sizeof(val));
        if (err)
                return err;
        if (get_op(val) == OP_PREFIX) {
-               err = probe_kernel_read(&suffix, (void *)src + 4, 4);
+               err = copy_from_kernel_nofault(&suffix, (void *)src + 4, 4);
                *inst = ppc_inst_prefix(val, suffix);
        } else {
                *inst = ppc_inst(val);
@@ -51,7 +51,7 @@ int probe_user_read_inst(struct ppc_inst *inst,
        unsigned int val;
        int err;
 
-       err = probe_user_read(&val, nip, sizeof(val));
+       err = copy_from_user_nofault(&val, nip, sizeof(val));
        if (!err)
                *inst = ppc_inst(val);
 
@@ -64,7 +64,7 @@ int probe_kernel_read_inst(struct ppc_inst *inst,
        unsigned int val;
        int err;
 
-       err = probe_kernel_read(&val, src, sizeof(val));
+       err = copy_from_kernel_nofault(&val, src, sizeof(val));
        if (!err)
                *inst = ppc_inst(val);
 
index 468169e..9b9f92a 100644 (file)
@@ -1559,6 +1559,7 @@ static void hash_preload(struct mm_struct *mm, pte_t *ptep, unsigned long ea,
        pgd_t *pgdir;
        int rc, ssize, update_flags = 0;
        unsigned long access = _PAGE_PRESENT | _PAGE_READ | (is_exec ? _PAGE_EXEC : 0);
+       unsigned long flags;
 
        BUG_ON(get_region_id(ea) != USER_REGION_ID);
 
@@ -1592,6 +1593,28 @@ static void hash_preload(struct mm_struct *mm, pte_t *ptep, unsigned long ea,
                return;
 #endif /* CONFIG_PPC_64K_PAGES */
 
+       /*
+        * __hash_page_* must run with interrupts off, as it sets the
+        * H_PAGE_BUSY bit. It's possible for perf interrupts to hit at any
+        * time and may take a hash fault reading the user stack, see
+        * read_user_stack_slow() in the powerpc/perf code.
+        *
+        * If that takes a hash fault on the same page as we lock here, it
+        * will bail out when seeing H_PAGE_BUSY set, and retry the access
+        * leading to an infinite loop.
+        *
+        * Disabling interrupts here does not prevent perf interrupts, but it
+        * will prevent them taking hash faults (see the NMI test in
+        * do_hash_page), then read_user_stack's copy_from_user_nofault will
+        * fail and perf will fall back to read_user_stack_slow(), which
+        * walks the Linux page tables.
+        *
+        * Interrupts must also be off for the duration of the
+        * mm_is_thread_local test and update, to prevent preempt running the
+        * mm on another CPU (XXX: this may be racy vs kthread_use_mm).
+        */
+       local_irq_save(flags);
+
        /* Is that local to this CPU ? */
        if (mm_is_thread_local(mm))
                update_flags |= HPTE_LOCAL_UPDATE;
@@ -1614,6 +1637,8 @@ static void hash_preload(struct mm_struct *mm, pte_t *ptep, unsigned long ea,
                                   mm_ctx_user_psize(&mm->context),
                                   mm_ctx_user_psize(&mm->context),
                                   pte_val(*ptep));
+
+       local_irq_restore(flags);
 }
 
 /*
index 1199fc2..d174106 100644 (file)
@@ -353,16 +353,15 @@ static bool pkey_access_permitted(int pkey, bool write, bool execute)
        int pkey_shift;
        u64 amr;
 
-       if (!is_pkey_enabled(pkey))
-               return true;
-
        pkey_shift = pkeyshift(pkey);
-       if (execute && !(read_iamr() & (IAMR_EX_BIT << pkey_shift)))
-               return true;
+       if (execute)
+               return !(read_iamr() & (IAMR_EX_BIT << pkey_shift));
+
+       amr = read_amr();
+       if (write)
+               return !(amr & (AMR_WR_BIT << pkey_shift));
 
-       amr = read_amr(); /* Delay reading amr until absolutely needed */
-       return ((!write && !(amr & (AMR_RD_BIT << pkey_shift))) ||
-               (write &&  !(amr & (AMR_WR_BIT << pkey_shift))));
+       return !(amr & (AMR_RD_BIT << pkey_shift));
 }
 
 bool arch_pte_access_permitted(u64 pte, bool write, bool execute)
index 4a75f2d..bce0e53 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/memblock.h>
 #include <linux/libfdt.h>
 #include <linux/crash_core.h>
+#include <asm/cacheflush.h>
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
 #include <asm/kdump.h>
index 6f347fa..9db7ada 100644 (file)
@@ -33,7 +33,8 @@ static unsigned int user_getsp32(unsigned int sp, int is_first)
         * which means that we've done all that we can do from
         * interrupt context.
         */
-       if (probe_user_read(stack_frame, (void __user *)p, sizeof(stack_frame)))
+       if (copy_from_user_nofault(stack_frame, (void __user *)p,
+                       sizeof(stack_frame)))
                return 0;
 
        if (!is_first)
@@ -51,7 +52,8 @@ static unsigned long user_getsp64(unsigned long sp, int is_first)
 {
        unsigned long stack_frame[3];
 
-       if (probe_user_read(stack_frame, (void __user *)sp, sizeof(stack_frame)))
+       if (copy_from_user_nofault(stack_frame, (void __user *)sp,
+                       sizeof(stack_frame)))
                return 0;
 
        if (!is_first)
index f7d888d..542e68b 100644 (file)
@@ -44,7 +44,7 @@ static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret)
            ((unsigned long)ptr & 3))
                return -EFAULT;
 
-       rc = probe_user_read(ret, ptr, sizeof(*ret));
+       rc = copy_from_user_nofault(ret, ptr, sizeof(*ret));
 
        if (IS_ENABLED(CONFIG_PPC64) && rc)
                return read_user_stack_slow(ptr, ret, 4);
index 814d1c2..fa2a1b8 100644 (file)
@@ -50,7 +50,7 @@ static int read_user_stack_64(unsigned long __user *ptr, unsigned long *ret)
            ((unsigned long)ptr & 7))
                return -EFAULT;
 
-       if (!probe_user_read(ret, ptr, sizeof(*ret)))
+       if (!copy_from_user_nofault(ret, ptr, sizeof(*ret)))
                return 0;
 
        return read_user_stack_slow(ptr, ret, 8);
index 13b9dd5..01d7028 100644 (file)
@@ -418,14 +418,16 @@ static __u64 power_pmu_bhrb_to(u64 addr)
        __u64 target;
 
        if (is_kernel_addr(addr)) {
-               if (probe_kernel_read(&instr, (void *)addr, sizeof(instr)))
+               if (copy_from_kernel_nofault(&instr, (void *)addr,
+                               sizeof(instr)))
                        return 0;
 
                return branch_target((struct ppc_inst *)&instr);
        }
 
        /* Userspace: need copy instruction here then translate it */
-       if (probe_user_read(&instr, (unsigned int __user *)addr, sizeof(instr)))
+       if (copy_from_user_nofault(&instr, (unsigned int __user *)addr,
+                       sizeof(instr)))
                return 0;
 
        target = branch_target((struct ppc_inst *)&instr);
@@ -2177,6 +2179,12 @@ static void __perf_event_interrupt(struct pt_regs *regs)
 
        perf_read_regs(regs);
 
+       /*
+        * If perf interrupts hit in a local_irq_disable (soft-masked) region,
+        * we consider them as NMIs. This is required to prevent hash faults on
+        * user addresses when reading callchains. See the NMI test in
+        * do_hash_page.
+        */
        nmi = perf_intr_is_nmi(regs);
        if (nmi)
                nmi_enter();
index cbee366..abdef9b 100644 (file)
@@ -35,7 +35,7 @@
  */
 
 static void *spu_syscall_table[] = {
-#define __SYSCALL(nr, entry)   entry,
+#define __SYSCALL(nr, entry) [nr] = entry,
 #include <asm/syscall_table_spu.h>
 #undef __SYSCALL
 };
index 266a6ca..3d21fce 100644 (file)
@@ -79,7 +79,7 @@ static void update_csb(struct vas_window *window,
        csb_addr = (void __user *)be64_to_cpu(crb->csb_addr);
 
        memset(&csb, 0, sizeof(csb));
-       csb.cc = CSB_CC_TRANSLATION;
+       csb.cc = CSB_CC_FAULT_ADDRESS;
        csb.ce = CSB_CE_TERMINATION;
        csb.cs = 0;
        csb.count = 0;
index f355924..9c56907 100644 (file)
 #include <linux/libnvdimm.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <linux/seq_buf.h>
 
 #include <asm/plpar_wrappers.h>
+#include <asm/papr_pdsm.h>
 
 #define BIND_ANY_ADDR (~0ul)
 
 #define PAPR_SCM_DIMM_CMD_MASK \
        ((1ul << ND_CMD_GET_CONFIG_SIZE) | \
         (1ul << ND_CMD_GET_CONFIG_DATA) | \
-        (1ul << ND_CMD_SET_CONFIG_DATA))
-
+        (1ul << ND_CMD_SET_CONFIG_DATA) | \
+        (1ul << ND_CMD_CALL))
+
+/* DIMM health bitmap bitmap indicators */
+/* SCM device is unable to persist memory contents */
+#define PAPR_PMEM_UNARMED                   (1ULL << (63 - 0))
+/* SCM device failed to persist memory contents */
+#define PAPR_PMEM_SHUTDOWN_DIRTY            (1ULL << (63 - 1))
+/* SCM device contents are persisted from previous IPL */
+#define PAPR_PMEM_SHUTDOWN_CLEAN            (1ULL << (63 - 2))
+/* SCM device contents are not persisted from previous IPL */
+#define PAPR_PMEM_EMPTY                     (1ULL << (63 - 3))
+/* SCM device memory life remaining is critically low */
+#define PAPR_PMEM_HEALTH_CRITICAL           (1ULL << (63 - 4))
+/* SCM device will be garded off next IPL due to failure */
+#define PAPR_PMEM_HEALTH_FATAL              (1ULL << (63 - 5))
+/* SCM contents cannot persist due to current platform health status */
+#define PAPR_PMEM_HEALTH_UNHEALTHY          (1ULL << (63 - 6))
+/* SCM device is unable to persist memory contents in certain conditions */
+#define PAPR_PMEM_HEALTH_NON_CRITICAL       (1ULL << (63 - 7))
+/* SCM device is encrypted */
+#define PAPR_PMEM_ENCRYPTED                 (1ULL << (63 - 8))
+/* SCM device has been scrubbed and locked */
+#define PAPR_PMEM_SCRUBBED_AND_LOCKED       (1ULL << (63 - 9))
+
+/* Bits status indicators for health bitmap indicating unarmed dimm */
+#define PAPR_PMEM_UNARMED_MASK (PAPR_PMEM_UNARMED |            \
+                               PAPR_PMEM_HEALTH_UNHEALTHY)
+
+/* Bits status indicators for health bitmap indicating unflushed dimm */
+#define PAPR_PMEM_BAD_SHUTDOWN_MASK (PAPR_PMEM_SHUTDOWN_DIRTY)
+
+/* Bits status indicators for health bitmap indicating unrestored dimm */
+#define PAPR_PMEM_BAD_RESTORE_MASK  (PAPR_PMEM_EMPTY)
+
+/* Bit status indicators for smart event notification */
+#define PAPR_PMEM_SMART_EVENT_MASK (PAPR_PMEM_HEALTH_CRITICAL | \
+                                   PAPR_PMEM_HEALTH_FATAL |    \
+                                   PAPR_PMEM_HEALTH_UNHEALTHY)
+
+/* private struct associated with each region */
 struct papr_scm_priv {
        struct platform_device *pdev;
        struct device_node *dn;
@@ -39,6 +80,15 @@ struct papr_scm_priv {
        struct resource res;
        struct nd_region *region;
        struct nd_interleave_set nd_set;
+
+       /* Protect dimm health data from concurrent read/writes */
+       struct mutex health_mutex;
+
+       /* Last time the health information of the dimm was updated */
+       unsigned long lasthealth_jiffies;
+
+       /* Health information for the dimm */
+       u64 health_bitmap;
 };
 
 static int drc_pmem_bind(struct papr_scm_priv *p)
@@ -144,6 +194,61 @@ err_out:
        return drc_pmem_bind(p);
 }
 
+/*
+ * Issue hcall to retrieve dimm health info and populate papr_scm_priv with the
+ * health information.
+ */
+static int __drc_pmem_query_health(struct papr_scm_priv *p)
+{
+       unsigned long ret[PLPAR_HCALL_BUFSIZE];
+       long rc;
+
+       /* issue the hcall */
+       rc = plpar_hcall(H_SCM_HEALTH, ret, p->drc_index);
+       if (rc != H_SUCCESS) {
+               dev_err(&p->pdev->dev,
+                       "Failed to query health information, Err:%ld\n", rc);
+               return -ENXIO;
+       }
+
+       p->lasthealth_jiffies = jiffies;
+       p->health_bitmap = ret[0] & ret[1];
+
+       dev_dbg(&p->pdev->dev,
+               "Queried dimm health info. Bitmap:0x%016lx Mask:0x%016lx\n",
+               ret[0], ret[1]);
+
+       return 0;
+}
+
+/* Min interval in seconds for assuming stable dimm health */
+#define MIN_HEALTH_QUERY_INTERVAL 60
+
+/* Query cached health info and if needed call drc_pmem_query_health */
+static int drc_pmem_query_health(struct papr_scm_priv *p)
+{
+       unsigned long cache_timeout;
+       int rc;
+
+       /* Protect concurrent modifications to papr_scm_priv */
+       rc = mutex_lock_interruptible(&p->health_mutex);
+       if (rc)
+               return rc;
+
+       /* Jiffies offset for which the health data is assumed to be same */
+       cache_timeout = p->lasthealth_jiffies +
+               msecs_to_jiffies(MIN_HEALTH_QUERY_INTERVAL * 1000);
+
+       /* Fetch new health info is its older than MIN_HEALTH_QUERY_INTERVAL */
+       if (time_after(jiffies, cache_timeout))
+               rc = __drc_pmem_query_health(p);
+       else
+               /* Assume cached health data is valid */
+               rc = 0;
+
+       mutex_unlock(&p->health_mutex);
+       return rc;
+}
 
 static int papr_scm_meta_get(struct papr_scm_priv *p,
                             struct nd_cmd_get_config_data_hdr *hdr)
@@ -246,16 +351,250 @@ static int papr_scm_meta_set(struct papr_scm_priv *p,
        return 0;
 }
 
+/*
+ * Do a sanity checks on the inputs args to dimm-control function and return
+ * '0' if valid. Validation of PDSM payloads happens later in
+ * papr_scm_service_pdsm.
+ */
+static int is_cmd_valid(struct nvdimm *nvdimm, unsigned int cmd, void *buf,
+                       unsigned int buf_len)
+{
+       unsigned long cmd_mask = PAPR_SCM_DIMM_CMD_MASK;
+       struct nd_cmd_pkg *nd_cmd;
+       struct papr_scm_priv *p;
+       enum papr_pdsm pdsm;
+
+       /* Only dimm-specific calls are supported atm */
+       if (!nvdimm)
+               return -EINVAL;
+
+       /* get the provider data from struct nvdimm */
+       p = nvdimm_provider_data(nvdimm);
+
+       if (!test_bit(cmd, &cmd_mask)) {
+               dev_dbg(&p->pdev->dev, "Unsupported cmd=%u\n", cmd);
+               return -EINVAL;
+       }
+
+       /* For CMD_CALL verify pdsm request */
+       if (cmd == ND_CMD_CALL) {
+               /* Verify the envelope and envelop size */
+               if (!buf ||
+                   buf_len < (sizeof(struct nd_cmd_pkg) + ND_PDSM_HDR_SIZE)) {
+                       dev_dbg(&p->pdev->dev, "Invalid pkg size=%u\n",
+                               buf_len);
+                       return -EINVAL;
+               }
+
+               /* Verify that the nd_cmd_pkg.nd_family is correct */
+               nd_cmd = (struct nd_cmd_pkg *)buf;
+
+               if (nd_cmd->nd_family != NVDIMM_FAMILY_PAPR) {
+                       dev_dbg(&p->pdev->dev, "Invalid pkg family=0x%llx\n",
+                               nd_cmd->nd_family);
+                       return -EINVAL;
+               }
+
+               pdsm = (enum papr_pdsm)nd_cmd->nd_command;
+
+               /* Verify if the pdsm command is valid */
+               if (pdsm <= PAPR_PDSM_MIN || pdsm >= PAPR_PDSM_MAX) {
+                       dev_dbg(&p->pdev->dev, "PDSM[0x%x]: Invalid PDSM\n",
+                               pdsm);
+                       return -EINVAL;
+               }
+
+               /* Have enough space to hold returned 'nd_pkg_pdsm' header */
+               if (nd_cmd->nd_size_out < ND_PDSM_HDR_SIZE) {
+                       dev_dbg(&p->pdev->dev, "PDSM[0x%x]: Invalid payload\n",
+                               pdsm);
+                       return -EINVAL;
+               }
+       }
+
+       /* Let the command be further processed */
+       return 0;
+}
+
+/* Fetch the DIMM health info and populate it in provided package. */
+static int papr_pdsm_health(struct papr_scm_priv *p,
+                           union nd_pdsm_payload *payload)
+{
+       int rc;
+
+       /* Ensure dimm health mutex is taken preventing concurrent access */
+       rc = mutex_lock_interruptible(&p->health_mutex);
+       if (rc)
+               goto out;
+
+       /* Always fetch upto date dimm health data ignoring cached values */
+       rc = __drc_pmem_query_health(p);
+       if (rc) {
+               mutex_unlock(&p->health_mutex);
+               goto out;
+       }
+
+       /* update health struct with various flags derived from health bitmap */
+       payload->health = (struct nd_papr_pdsm_health) {
+               .extension_flags = 0,
+               .dimm_unarmed = !!(p->health_bitmap & PAPR_PMEM_UNARMED_MASK),
+               .dimm_bad_shutdown = !!(p->health_bitmap & PAPR_PMEM_BAD_SHUTDOWN_MASK),
+               .dimm_bad_restore = !!(p->health_bitmap & PAPR_PMEM_BAD_RESTORE_MASK),
+               .dimm_scrubbed = !!(p->health_bitmap & PAPR_PMEM_SCRUBBED_AND_LOCKED),
+               .dimm_locked = !!(p->health_bitmap & PAPR_PMEM_SCRUBBED_AND_LOCKED),
+               .dimm_encrypted = !!(p->health_bitmap & PAPR_PMEM_ENCRYPTED),
+               .dimm_health = PAPR_PDSM_DIMM_HEALTHY,
+       };
+
+       /* Update field dimm_health based on health_bitmap flags */
+       if (p->health_bitmap & PAPR_PMEM_HEALTH_FATAL)
+               payload->health.dimm_health = PAPR_PDSM_DIMM_FATAL;
+       else if (p->health_bitmap & PAPR_PMEM_HEALTH_CRITICAL)
+               payload->health.dimm_health = PAPR_PDSM_DIMM_CRITICAL;
+       else if (p->health_bitmap & PAPR_PMEM_HEALTH_UNHEALTHY)
+               payload->health.dimm_health = PAPR_PDSM_DIMM_UNHEALTHY;
+
+       /* struct populated hence can release the mutex now */
+       mutex_unlock(&p->health_mutex);
+       rc = sizeof(struct nd_papr_pdsm_health);
+
+out:
+       return rc;
+}
+
+/*
+ * 'struct pdsm_cmd_desc'
+ * Identifies supported PDSMs' expected length of in/out payloads
+ * and pdsm service function.
+ *
+ * size_in     : Size of input payload if any in the PDSM request.
+ * size_out    : Size of output payload if any in the PDSM request.
+ * service     : Service function for the PDSM request. Return semantics:
+ *               rc < 0 : Error servicing PDSM and rc indicates the error.
+ *               rc >=0 : Serviced successfully and 'rc' indicate number of
+ *                     bytes written to payload.
+ */
+struct pdsm_cmd_desc {
+       u32 size_in;
+       u32 size_out;
+       int (*service)(struct papr_scm_priv *dimm,
+                      union nd_pdsm_payload *payload);
+};
+
+/* Holds all supported PDSMs' command descriptors */
+static const struct pdsm_cmd_desc __pdsm_cmd_descriptors[] = {
+       [PAPR_PDSM_MIN] = {
+               .size_in = 0,
+               .size_out = 0,
+               .service = NULL,
+       },
+       /* New PDSM command descriptors to be added below */
+
+       [PAPR_PDSM_HEALTH] = {
+               .size_in = 0,
+               .size_out = sizeof(struct nd_papr_pdsm_health),
+               .service = papr_pdsm_health,
+       },
+       /* Empty */
+       [PAPR_PDSM_MAX] = {
+               .size_in = 0,
+               .size_out = 0,
+               .service = NULL,
+       },
+};
+
+/* Given a valid pdsm cmd return its command descriptor else return NULL */
+static inline const struct pdsm_cmd_desc *pdsm_cmd_desc(enum papr_pdsm cmd)
+{
+       if (cmd >= 0 || cmd < ARRAY_SIZE(__pdsm_cmd_descriptors))
+               return &__pdsm_cmd_descriptors[cmd];
+
+       return NULL;
+}
+
+/*
+ * For a given pdsm request call an appropriate service function.
+ * Returns errors if any while handling the pdsm command package.
+ */
+static int papr_scm_service_pdsm(struct papr_scm_priv *p,
+                                struct nd_cmd_pkg *pkg)
+{
+       /* Get the PDSM header and PDSM command */
+       struct nd_pkg_pdsm *pdsm_pkg = (struct nd_pkg_pdsm *)pkg->nd_payload;
+       enum papr_pdsm pdsm = (enum papr_pdsm)pkg->nd_command;
+       const struct pdsm_cmd_desc *pdsc;
+       int rc;
+
+       /* Fetch corresponding pdsm descriptor for validation and servicing */
+       pdsc = pdsm_cmd_desc(pdsm);
+
+       /* Validate pdsm descriptor */
+       /* Ensure that reserved fields are 0 */
+       if (pdsm_pkg->reserved[0] || pdsm_pkg->reserved[1]) {
+               dev_dbg(&p->pdev->dev, "PDSM[0x%x]: Invalid reserved field\n",
+                       pdsm);
+               return -EINVAL;
+       }
+
+       /* If pdsm expects some input, then ensure that the size_in matches */
+       if (pdsc->size_in &&
+           pkg->nd_size_in != (pdsc->size_in + ND_PDSM_HDR_SIZE)) {
+               dev_dbg(&p->pdev->dev, "PDSM[0x%x]: Mismatched size_in=%d\n",
+                       pdsm, pkg->nd_size_in);
+               return -EINVAL;
+       }
+
+       /* If pdsm wants to return data, then ensure that  size_out matches */
+       if (pdsc->size_out &&
+           pkg->nd_size_out != (pdsc->size_out + ND_PDSM_HDR_SIZE)) {
+               dev_dbg(&p->pdev->dev, "PDSM[0x%x]: Mismatched size_out=%d\n",
+                       pdsm, pkg->nd_size_out);
+               return -EINVAL;
+       }
+
+       /* Service the pdsm */
+       if (pdsc->service) {
+               dev_dbg(&p->pdev->dev, "PDSM[0x%x]: Servicing..\n", pdsm);
+
+               rc = pdsc->service(p, &pdsm_pkg->payload);
+
+               if (rc < 0) {
+                       /* error encountered while servicing pdsm */
+                       pdsm_pkg->cmd_status = rc;
+                       pkg->nd_fw_size = ND_PDSM_HDR_SIZE;
+               } else {
+                       /* pdsm serviced and 'rc' bytes written to payload */
+                       pdsm_pkg->cmd_status = 0;
+                       pkg->nd_fw_size = ND_PDSM_HDR_SIZE + rc;
+               }
+       } else {
+               dev_dbg(&p->pdev->dev, "PDSM[0x%x]: Unsupported PDSM request\n",
+                       pdsm);
+               pdsm_pkg->cmd_status = -ENOENT;
+               pkg->nd_fw_size = ND_PDSM_HDR_SIZE;
+       }
+
+       return pdsm_pkg->cmd_status;
+}
+
 static int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc,
                          struct nvdimm *nvdimm, unsigned int cmd, void *buf,
                          unsigned int buf_len, int *cmd_rc)
 {
        struct nd_cmd_get_config_size *get_size_hdr;
+       struct nd_cmd_pkg *call_pkg = NULL;
        struct papr_scm_priv *p;
+       int rc;
 
-       /* Only dimm-specific calls are supported atm */
-       if (!nvdimm)
-               return -EINVAL;
+       rc = is_cmd_valid(nvdimm, cmd, buf, buf_len);
+       if (rc) {
+               pr_debug("Invalid cmd=0x%x. Err=%d\n", cmd, rc);
+               return rc;
+       }
+
+       /* Use a local variable in case cmd_rc pointer is NULL */
+       if (!cmd_rc)
+               cmd_rc = &rc;
 
        p = nvdimm_provider_data(nvdimm);
 
@@ -277,7 +616,13 @@ static int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc,
                *cmd_rc = papr_scm_meta_set(p, buf);
                break;
 
+       case ND_CMD_CALL:
+               call_pkg = (struct nd_cmd_pkg *)buf;
+               *cmd_rc = papr_scm_service_pdsm(p, call_pkg);
+               break;
+
        default:
+               dev_dbg(&p->pdev->dev, "Unknown command = %d\n", cmd);
                return -EINVAL;
        }
 
@@ -286,6 +631,64 @@ static int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc,
        return 0;
 }
 
+static ssize_t flags_show(struct device *dev,
+                         struct device_attribute *attr, char *buf)
+{
+       struct nvdimm *dimm = to_nvdimm(dev);
+       struct papr_scm_priv *p = nvdimm_provider_data(dimm);
+       struct seq_buf s;
+       u64 health;
+       int rc;
+
+       rc = drc_pmem_query_health(p);
+       if (rc)
+               return rc;
+
+       /* Copy health_bitmap locally, check masks & update out buffer */
+       health = READ_ONCE(p->health_bitmap);
+
+       seq_buf_init(&s, buf, PAGE_SIZE);
+       if (health & PAPR_PMEM_UNARMED_MASK)
+               seq_buf_printf(&s, "not_armed ");
+
+       if (health & PAPR_PMEM_BAD_SHUTDOWN_MASK)
+               seq_buf_printf(&s, "flush_fail ");
+
+       if (health & PAPR_PMEM_BAD_RESTORE_MASK)
+               seq_buf_printf(&s, "restore_fail ");
+
+       if (health & PAPR_PMEM_ENCRYPTED)
+               seq_buf_printf(&s, "encrypted ");
+
+       if (health & PAPR_PMEM_SMART_EVENT_MASK)
+               seq_buf_printf(&s, "smart_notify ");
+
+       if (health & PAPR_PMEM_SCRUBBED_AND_LOCKED)
+               seq_buf_printf(&s, "scrubbed locked ");
+
+       if (seq_buf_used(&s))
+               seq_buf_printf(&s, "\n");
+
+       return seq_buf_used(&s);
+}
+DEVICE_ATTR_RO(flags);
+
+/* papr_scm specific dimm attributes */
+static struct attribute *papr_nd_attributes[] = {
+       &dev_attr_flags.attr,
+       NULL,
+};
+
+static struct attribute_group papr_nd_attribute_group = {
+       .name = "papr",
+       .attrs = papr_nd_attributes,
+};
+
+static const struct attribute_group *papr_nd_attr_groups[] = {
+       &papr_nd_attribute_group,
+       NULL,
+};
+
 static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
 {
        struct device *dev = &p->pdev->dev;
@@ -312,8 +715,8 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
        dimm_flags = 0;
        set_bit(NDD_LABELING, &dimm_flags);
 
-       p->nvdimm = nvdimm_create(p->bus, p, NULL, dimm_flags,
-                                 PAPR_SCM_DIMM_CMD_MASK, 0, NULL);
+       p->nvdimm = nvdimm_create(p->bus, p, papr_nd_attr_groups,
+                                 dimm_flags, PAPR_SCM_DIMM_CMD_MASK, 0, NULL);
        if (!p->nvdimm) {
                dev_err(dev, "Error creating DIMM object for %pOF\n", p->dn);
                goto err;
@@ -399,6 +802,9 @@ static int papr_scm_probe(struct platform_device *pdev)
        if (!p)
                return -ENOMEM;
 
+       /* Initialize the dimm mutex */
+       mutex_init(&p->health_mutex);
+
        /* optional DT properties */
        of_property_read_u32(dn, "ibm,metadata-size", &metadata_size);
 
index 4a8874b..040b9d0 100644 (file)
@@ -1066,10 +1066,10 @@ int fsl_pci_mcheck_exception(struct pt_regs *regs)
 
        if (is_in_pci_mem_space(addr)) {
                if (user_mode(regs))
-                       ret = probe_user_read(&inst, (void __user *)regs->nip,
-                                             sizeof(inst));
+                       ret = copy_from_user_nofault(&inst,
+                                       (void __user *)regs->nip, sizeof(inst));
                else
-                       ret = probe_kernel_address((void *)regs->nip, inst);
+                       ret = get_kernel_nofault(inst, (void *)regs->nip);
 
                if (!ret && mcheck_handle_load(regs, inst)) {
                        regs->nip += 4;
index 128192e..3230c1d 100644 (file)
@@ -23,6 +23,8 @@ config RISCV
        select ARCH_HAS_SET_DIRECT_MAP
        select ARCH_HAS_SET_MEMORY
        select ARCH_HAS_STRICT_KERNEL_RWX if MMU
+       select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
+       select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT
        select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
        select ARCH_WANT_FRAME_POINTERS
        select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
index 3f1737f..d0e24aa 100644 (file)
@@ -58,8 +58,16 @@ do {                                                                 \
  * The AQ/RL pair provides a RCpc critical section, but there's not really any
  * way we can take advantage of that here because the ordering is only enforced
  * on that one lock.  Thus, we're just doing a full fence.
+ *
+ * Since we allow writeX to be called from preemptive regions we need at least
+ * an "o" in the predecessor set to ensure device writes are visible before the
+ * task is marked as available for scheduling on a new hart.  While I don't see
+ * any concrete reason we need a full IO fence, it seems safer to just upgrade
+ * this in order to avoid any IO crossing a scheduling boundary.  In both
+ * instances the scheduler pairs this with an mb(), so nothing is necessary on
+ * the new hart.
  */
-#define smp_mb__after_spinlock()       RISCV_FENCE(rw,rw)
+#define smp_mb__after_spinlock()       RISCV_FENCE(iorw,iorw)
 
 #include <asm-generic/barrier.h>
 
index d969bab..262e5bb 100644 (file)
                        "       bnez %1, 0b\n"                          \
                        "1:\n"                                          \
                        : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr)    \
-                       : "rJ" (__old), "rJ" (__new)                    \
+                       : "rJ" ((long)__old), "rJ" (__new)              \
                        : "memory");                                    \
                break;                                                  \
        case 8:                                                         \
                        RISCV_ACQUIRE_BARRIER                           \
                        "1:\n"                                          \
                        : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr)    \
-                       : "rJ" (__old), "rJ" (__new)                    \
+                       : "rJ" ((long)__old), "rJ" (__new)              \
                        : "memory");                                    \
                break;                                                  \
        case 8:                                                         \
                        "       bnez %1, 0b\n"                          \
                        "1:\n"                                          \
                        : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr)    \
-                       : "rJ" (__old), "rJ" (__new)                    \
+                       : "rJ" ((long)__old), "rJ" (__new)              \
                        : "memory");                                    \
                break;                                                  \
        case 8:                                                         \
                        "       fence rw, rw\n"                         \
                        "1:\n"                                          \
                        : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr)    \
-                       : "rJ" (__old), "rJ" (__new)                    \
+                       : "rJ" ((long)__old), "rJ" (__new)              \
                        : "memory");                                    \
                break;                                                  \
        case 8:                                                         \
index 041b45f..0934211 100644 (file)
@@ -3,8 +3,7 @@
 #ifndef __ASM_GDB_XML_H_
 #define __ASM_GDB_XML_H_
 
-#define kgdb_arch_gdb_stub_feature riscv_gdb_stub_feature
-static const char riscv_gdb_stub_feature[64] =
+const char riscv_gdb_stub_feature[64] =
                        "PacketSize=800;qXfer:features:read+;";
 
 static const char gdb_xfer_read_target[31] = "qXfer:features:read:target.xml:";
index 8177a45..46677da 100644 (file)
@@ -19,7 +19,6 @@
 
 #ifndef        __ASSEMBLY__
 
-extern int kgdb_has_hit_break(unsigned long addr);
 extern unsigned long kgdb_compiled_break;
 
 static inline void arch_kgdb_breakpoint(void)
@@ -106,7 +105,9 @@ static inline void arch_kgdb_breakpoint(void)
 #define DBG_REG_BADADDR_OFF 34
 #define DBG_REG_CAUSE_OFF 35
 
-#include <asm/gdb_xml.h>
+extern const char riscv_gdb_stub_feature[64];
+
+#define kgdb_arch_gdb_stub_feature riscv_gdb_stub_feature
 
 #endif
 #endif
index 1dd12a0..464a2bb 100644 (file)
 #include <linux/const.h>
 
 /* thread information allocation */
+#ifdef CONFIG_64BIT
+#define THREAD_SIZE_ORDER      (2)
+#else
 #define THREAD_SIZE_ORDER      (1)
+#endif
 #define THREAD_SIZE            (PAGE_SIZE << THREAD_SIZE_ORDER)
 
 #ifndef __ASSEMBLY__
index 0839661..2ff63d0 100644 (file)
@@ -38,7 +38,8 @@ static int ftrace_check_current_call(unsigned long hook_pos,
         * Read the text we want to modify;
         * return must be -EFAULT on read error
         */
-       if (probe_kernel_read(replaced, (void *)hook_pos, MCOUNT_INSN_SIZE))
+       if (copy_from_kernel_nofault(replaced, (void *)hook_pos,
+                       MCOUNT_INSN_SIZE))
                return -EFAULT;
 
        /*
index f16ade8..963ed7e 100644 (file)
@@ -44,25 +44,25 @@ DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ)
 DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ)
 DECLARE_INSN(sret, MATCH_SRET, MASK_SRET)
 
-int decode_register_index(unsigned long opcode, int offset)
+static int decode_register_index(unsigned long opcode, int offset)
 {
        return (opcode >> offset) & 0x1F;
 }
 
-int decode_register_index_short(unsigned long opcode, int offset)
+static int decode_register_index_short(unsigned long opcode, int offset)
 {
        return ((opcode >> offset) & 0x7) + 8;
 }
 
 /* Calculate the new address for after a step */
-int get_step_address(struct pt_regs *regs, unsigned long *next_addr)
+static int get_step_address(struct pt_regs *regs, unsigned long *next_addr)
 {
        unsigned long pc = regs->epc;
        unsigned long *regs_ptr = (unsigned long *)regs;
        unsigned int rs1_num, rs2_num;
        int op_code;
 
-       if (probe_kernel_address((void *)pc, op_code))
+       if (get_kernel_nofault(op_code, (void *)pc))
                return -EINVAL;
        if ((op_code & __INSN_LENGTH_MASK) != __INSN_LENGTH_GE_32) {
                if (is_c_jalr_insn(op_code) || is_c_jr_insn(op_code)) {
@@ -136,7 +136,7 @@ int get_step_address(struct pt_regs *regs, unsigned long *next_addr)
        return 0;
 }
 
-int do_single_step(struct pt_regs *regs)
+static int do_single_step(struct pt_regs *regs)
 {
        /* Determine where the target instruction will send us to */
        unsigned long addr = 0;
@@ -146,14 +146,14 @@ int do_single_step(struct pt_regs *regs)
                return error;
 
        /* Store the op code in the stepped address */
-       error = probe_kernel_address((void *)addr, stepped_opcode);
+       error = get_kernel_nofault(stepped_opcode, (void *)addr);
        if (error)
                return error;
 
        stepped_address = addr;
 
        /* Replace the op code with the break instruction */
-       error = probe_kernel_write((void *)stepped_address,
+       error = copy_to_kernel_nofault((void *)stepped_address,
                                   arch_kgdb_ops.gdb_bpt_instr,
                                   BREAK_INSTR_SIZE);
        /* Flush and return */
@@ -173,7 +173,7 @@ int do_single_step(struct pt_regs *regs)
 static void undo_single_step(struct pt_regs *regs)
 {
        if (stepped_opcode != 0) {
-               probe_kernel_write((void *)stepped_address,
+               copy_to_kernel_nofault((void *)stepped_address,
                                   (void *)&stepped_opcode, BREAK_INSTR_SIZE);
                flush_icache_range(stepped_address,
                                   stepped_address + BREAK_INSTR_SIZE);
@@ -320,7 +320,7 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code,
        return err;
 }
 
-int kgdb_riscv_kgdbbreak(unsigned long addr)
+static int kgdb_riscv_kgdbbreak(unsigned long addr)
 {
        if (stepped_address == addr)
                return KGDB_SW_SINGLE_STEP;
index d4a64df..3fe7a52 100644 (file)
@@ -63,7 +63,7 @@ static int patch_insn_write(void *addr, const void *insn, size_t len)
 
        waddr = patch_map(addr, FIX_TEXT_POKE0);
 
-       ret = probe_kernel_write(waddr, insn, len);
+       ret = copy_to_kernel_nofault(waddr, insn, len);
 
        patch_unmap(FIX_TEXT_POKE0);
 
@@ -76,7 +76,7 @@ NOKPROBE_SYMBOL(patch_insn_write);
 #else
 static int patch_insn_write(void *addr, const void *insn, size_t len)
 {
-       return probe_kernel_write(addr, insn, len);
+       return copy_to_kernel_nofault(addr, insn, len);
 }
 NOKPROBE_SYMBOL(patch_insn_write);
 #endif /* CONFIG_MMU */
index f3619f5..12f8a7f 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/syscalls.h>
 #include <asm/unistd.h>
 #include <asm/cacheflush.h>
+#include <asm-generic/mman-common.h>
 
 static long riscv_sys_mmap(unsigned long addr, unsigned long len,
                           unsigned long prot, unsigned long flags,
@@ -16,6 +17,11 @@ static long riscv_sys_mmap(unsigned long addr, unsigned long len,
 {
        if (unlikely(offset & (~PAGE_MASK >> page_shift_offset)))
                return -EINVAL;
+
+       if ((prot & PROT_WRITE) && (prot & PROT_EXEC))
+               if (unlikely(!(prot & PROT_READ)))
+                       return -EINVAL;
+
        return ksys_mmap_pgoff(addr, len, prot, flags, fd,
                               offset >> (PAGE_SHIFT - page_shift_offset));
 }
index ecec177..7d95cce 100644 (file)
@@ -137,7 +137,7 @@ static inline unsigned long get_break_insn_length(unsigned long pc)
 {
        bug_insn_t insn;
 
-       if (probe_kernel_address((bug_insn_t *)pc, insn))
+       if (get_kernel_nofault(insn, (bug_insn_t *)pc))
                return 0;
 
        return GET_INSN_LENGTH(insn);
@@ -165,7 +165,7 @@ int is_valid_bugaddr(unsigned long pc)
 
        if (pc < VMALLOC_START)
                return 0;
-       if (probe_kernel_address((bug_insn_t *)pc, insn))
+       if (get_kernel_nofault(insn, (bug_insn_t *)pc))
                return 0;
        if ((insn & __INSN_LENGTH_MASK) == __INSN_LENGTH_32)
                return (insn == __BUG_INSN_32);
index 38ba55b..e4c7c2c 100644 (file)
@@ -17,7 +17,7 @@ vdso-syms += flush_icache
 obj-vdso = $(patsubst %, %.o, $(vdso-syms)) note.o
 
 ifneq ($(c-gettimeofday-y),)
-  CFLAGS_vgettimeofday.o += -include $(c-gettimeofday-y)
+  CFLAGS_vgettimeofday.o += -fPIC -include $(c-gettimeofday-y)
 endif
 
 # Build rules
@@ -27,6 +27,9 @@ obj-vdso := $(addprefix $(obj)/, $(obj-vdso))
 obj-y += vdso.o vdso-syms.o
 CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
 
+# Disable -pg to prevent insert call site
+CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) -Os
+
 # Disable gcov profiling for VDSO code
 GCOV_PROFILE := n
 
index d264943..cc0d806 100644 (file)
@@ -9,16 +9,22 @@
 #include <linux/time.h>
 #include <linux/types.h>
 
+extern
+int __vdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts);
 int __vdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
 {
        return __cvdso_clock_gettime(clock, ts);
 }
 
+extern
+int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz);
 int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
 {
        return __cvdso_gettimeofday(tv, tz);
 }
 
+extern
+int __vdso_clock_getres(clockid_t clock_id, struct __kernel_timespec *res);
 int __vdso_clock_getres(clockid_t clock_id, struct __kernel_timespec *res)
 {
        return __cvdso_clock_getres(clock_id, res);
index f4adb36..79e9d55 100644 (file)
@@ -95,19 +95,40 @@ void __init mem_init(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 static void __init setup_initrd(void)
 {
+       phys_addr_t start;
        unsigned long size;
 
-       if (initrd_start >= initrd_end) {
-               pr_info("initrd not found or empty");
+       /* Ignore the virtul address computed during device tree parsing */
+       initrd_start = initrd_end = 0;
+
+       if (!phys_initrd_size)
+               return;
+       /*
+        * Round the memory region to page boundaries as per free_initrd_mem()
+        * This allows us to detect whether the pages overlapping the initrd
+        * are in use, but more importantly, reserves the entire set of pages
+        * as we don't want these pages allocated for other purposes.
+        */
+       start = round_down(phys_initrd_start, PAGE_SIZE);
+       size = phys_initrd_size + (phys_initrd_start - start);
+       size = round_up(size, PAGE_SIZE);
+
+       if (!memblock_is_region_memory(start, size)) {
+               pr_err("INITRD: 0x%08llx+0x%08lx is not a memory region",
+                      (u64)start, size);
                goto disable;
        }
-       if (__pa_symbol(initrd_end) > PFN_PHYS(max_low_pfn)) {
-               pr_err("initrd extends beyond end of memory");
+
+       if (memblock_is_region_reserved(start, size)) {
+               pr_err("INITRD: 0x%08llx+0x%08lx overlaps in-use memory region\n",
+                      (u64)start, size);
                goto disable;
        }
 
-       size = initrd_end - initrd_start;
-       memblock_reserve(__pa_symbol(initrd_start), size);
+       memblock_reserve(start, size);
+       /* Now convert initrd to virtual addresses */
+       initrd_start = (unsigned long)__va(phys_initrd_start);
+       initrd_end = initrd_start + phys_initrd_size;
        initrd_below_start_ok = 1;
 
        pr_info("Initial ramdisk at: 0x%p (%lu bytes)\n",
@@ -126,33 +147,36 @@ void __init setup_bootmem(void)
 {
        struct memblock_region *reg;
        phys_addr_t mem_size = 0;
+       phys_addr_t total_mem = 0;
+       phys_addr_t mem_start, end = 0;
        phys_addr_t vmlinux_end = __pa_symbol(&_end);
        phys_addr_t vmlinux_start = __pa_symbol(&_start);
 
        /* Find the memory region containing the kernel */
        for_each_memblock(memory, reg) {
-               phys_addr_t end = reg->base + reg->size;
-
-               if (reg->base <= vmlinux_start && vmlinux_end <= end) {
-                       mem_size = min(reg->size, (phys_addr_t)-PAGE_OFFSET);
-
-                       /*
-                        * Remove memblock from the end of usable area to the
-                        * end of region
-                        */
-                       if (reg->base + mem_size < end)
-                               memblock_remove(reg->base + mem_size,
-                                               end - reg->base - mem_size);
-               }
+               end = reg->base + reg->size;
+               if (!total_mem)
+                       mem_start = reg->base;
+               if (reg->base <= vmlinux_start && vmlinux_end <= end)
+                       BUG_ON(reg->size == 0);
+               total_mem = total_mem + reg->size;
        }
-       BUG_ON(mem_size == 0);
+
+       /*
+        * Remove memblock from the end of usable area to the
+        * end of region
+        */
+       mem_size = min(total_mem, (phys_addr_t)-PAGE_OFFSET);
+       if (mem_start + mem_size < end)
+               memblock_remove(mem_start + mem_size,
+                               end - mem_start - mem_size);
 
        /* Reserve from the start of the kernel to the end of the kernel */
        memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start);
 
-       set_max_mapnr(PFN_DOWN(mem_size));
        max_pfn = PFN_DOWN(memblock_end_of_DRAM());
        max_low_pfn = max_pfn;
+       set_max_mapnr(max_low_pfn);
 
 #ifdef CONFIG_BLK_DEV_INITRD
        setup_initrd();
index 4a8b618..87b4ab3 100644 (file)
@@ -44,7 +44,7 @@ asmlinkage void __init kasan_early_init(void)
                                (__pa(((uintptr_t) kasan_early_shadow_pmd))),
                                __pgprot(_PAGE_TABLE)));
 
-       flush_tlb_all();
+       local_flush_tlb_all();
 }
 
 static void __init populate(void *start, void *end)
@@ -79,7 +79,7 @@ static void __init populate(void *start, void *end)
                        pfn_pgd(PFN_DOWN(__pa(&pmd[offset])),
                                __pgprot(_PAGE_TABLE)));
 
-       flush_tlb_all();
+       local_flush_tlb_all();
        memset(start, 0, end - start);
 }
 
index ec2c70f..289a9a5 100644 (file)
@@ -151,6 +151,7 @@ int set_memory_nx(unsigned long addr, int numpages)
 
 int set_direct_map_invalid_noflush(struct page *page)
 {
+       int ret;
        unsigned long start = (unsigned long)page_address(page);
        unsigned long end = start + PAGE_SIZE;
        struct pageattr_masks masks = {
@@ -158,11 +159,16 @@ int set_direct_map_invalid_noflush(struct page *page)
                .clear_mask = __pgprot(_PAGE_PRESENT)
        };
 
-       return walk_page_range(&init_mm, start, end, &pageattr_ops, &masks);
+       mmap_read_lock(&init_mm);
+       ret = walk_page_range(&init_mm, start, end, &pageattr_ops, &masks);
+       mmap_read_unlock(&init_mm);
+
+       return ret;
 }
 
 int set_direct_map_default_noflush(struct page *page)
 {
+       int ret;
        unsigned long start = (unsigned long)page_address(page);
        unsigned long end = start + PAGE_SIZE;
        struct pageattr_masks masks = {
@@ -170,7 +176,11 @@ int set_direct_map_default_noflush(struct page *page)
                .clear_mask = __pgprot(0)
        };
 
-       return walk_page_range(&init_mm, start, end, &pageattr_ops, &masks);
+       mmap_read_lock(&init_mm);
+       ret = walk_page_range(&init_mm, start, end, &pageattr_ops, &masks);
+       mmap_read_unlock(&init_mm);
+
+       return ret;
 }
 
 void __kernel_map_pages(struct page *page, int numpages, int enable)
index 1948249..c7d7ede 100644 (file)
@@ -462,6 +462,7 @@ config NUMA
 
 config NODES_SHIFT
        int
+       depends on NEED_MULTIPLE_NODES
        default "1"
 
 config SCHED_SMT
index 46038bc..0cf9a82 100644 (file)
@@ -1,5 +1,6 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_WATCH_QUEUE=y
 CONFIG_AUDIT=y
 CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -14,7 +15,6 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_NUMA_BALANCING=y
 CONFIG_MEMCG=y
-CONFIG_MEMCG_SWAP=y
 CONFIG_BLK_CGROUP=y
 CONFIG_CFS_BANDWIDTH=y
 CONFIG_RT_GROUP_SCHED=y
@@ -31,9 +31,9 @@ CONFIG_NAMESPACES=y
 CONFIG_USER_NS=y
 CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_SCHED_AUTOGROUP=y
-CONFIG_BLK_DEV_INITRD=y
 CONFIG_EXPERT=y
 # CONFIG_SYSFS_SYSCALL is not set
+CONFIG_BPF_LSM=y
 CONFIG_BPF_SYSCALL=y
 CONFIG_USERFAULTFD=y
 # CONFIG_COMPAT_BRK is not set
@@ -51,14 +51,11 @@ CONFIG_CHSC_SCH=y
 CONFIG_VFIO_CCW=m
 CONFIG_VFIO_AP=m
 CONFIG_CRASH_DUMP=y
-CONFIG_HIBERNATION=y
-CONFIG_PM_DEBUG=y
 CONFIG_PROTECTED_VIRTUALIZATION_GUEST=y
 CONFIG_CMM=m
 CONFIG_APPLDATA_BASE=y
 CONFIG_KVM=m
-CONFIG_VHOST_NET=m
-CONFIG_VHOST_VSOCK=m
+CONFIG_S390_UNWIND_SELFTEST=y
 CONFIG_OPROFILE=m
 CONFIG_KPROBES=y
 CONFIG_JUMP_LABEL=y
@@ -77,6 +74,8 @@ CONFIG_BLK_DEV_THROTTLING=y
 CONFIG_BLK_WBT=y
 CONFIG_BLK_CGROUP_IOLATENCY=y
 CONFIG_BLK_CGROUP_IOCOST=y
+CONFIG_BLK_INLINE_ENCRYPTION=y
+CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
 CONFIG_BSD_DISKLABEL=y
@@ -96,7 +95,6 @@ CONFIG_CMA_DEBUG=y
 CONFIG_CMA_DEBUGFS=y
 CONFIG_MEM_SOFT_DIRTY=y
 CONFIG_ZSWAP=y
-CONFIG_ZBUD=m
 CONFIG_ZSMALLOC=m
 CONFIG_ZSMALLOC_STAT=y
 CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
@@ -130,6 +128,7 @@ CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
+CONFIG_INET_ESPINTCP=y
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
@@ -144,6 +143,7 @@ CONFIG_TCP_CONG_ILLINOIS=m
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
+CONFIG_INET6_ESPINTCP=y
 CONFIG_INET6_IPCOMP=m
 CONFIG_IPV6_MIP6=m
 CONFIG_IPV6_VTI=m
@@ -151,7 +151,10 @@ CONFIG_IPV6_SIT=m
 CONFIG_IPV6_GRE=m
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_RPL_LWTUNNEL=y
+CONFIG_MPTCP=y
 CONFIG_NETFILTER=y
+CONFIG_BRIDGE_NETFILTER=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
@@ -317,6 +320,7 @@ CONFIG_L2TP_V3=y
 CONFIG_L2TP_IP=m
 CONFIG_L2TP_ETH=m
 CONFIG_BRIDGE=m
+CONFIG_BRIDGE_MRP=y
 CONFIG_VLAN_8021Q=m
 CONFIG_VLAN_8021Q_GVRP=y
 CONFIG_NET_SCHED=y
@@ -341,6 +345,7 @@ CONFIG_NET_SCH_CODEL=m
 CONFIG_NET_SCH_FQ_CODEL=m
 CONFIG_NET_SCH_INGRESS=m
 CONFIG_NET_SCH_PLUG=m
+CONFIG_NET_SCH_ETS=m
 CONFIG_NET_CLS_BASIC=m
 CONFIG_NET_CLS_TCINDEX=m
 CONFIG_NET_CLS_ROUTE4=m
@@ -364,6 +369,7 @@ CONFIG_NET_ACT_PEDIT=m
 CONFIG_NET_ACT_SIMP=m
 CONFIG_NET_ACT_SKBEDIT=m
 CONFIG_NET_ACT_CSUM=m
+CONFIG_NET_ACT_GATE=m
 CONFIG_DNS_RESOLVER=y
 CONFIG_OPENVSWITCH=m
 CONFIG_VSOCKETS=m
@@ -374,6 +380,7 @@ CONFIG_BPF_JIT=y
 CONFIG_NET_PKTGEN=m
 # CONFIG_NET_DROP_MONITOR is not set
 CONFIG_PCI=y
+# CONFIG_PCIEASPM is not set
 CONFIG_PCI_DEBUG=y
 CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_S390=y
@@ -435,6 +442,7 @@ CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 CONFIG_DM_MULTIPATH_QL=m
 CONFIG_DM_MULTIPATH_ST=m
+CONFIG_DM_MULTIPATH_HST=m
 CONFIG_DM_DELAY=m
 CONFIG_DM_UEVENT=y
 CONFIG_DM_FLAKEY=m
@@ -448,6 +456,8 @@ CONFIG_EQUALIZER=m
 CONFIG_IFB=m
 CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
+CONFIG_VXLAN=m
+CONFIG_BAREUDP=m
 CONFIG_TUN=m
 CONFIG_VETH=m
 CONFIG_VIRTIO_NET=m
@@ -481,7 +491,6 @@ CONFIG_NLMON=m
 CONFIG_MLX4_EN=m
 CONFIG_MLX5_CORE=m
 CONFIG_MLX5_CORE_EN=y
-# CONFIG_MLXFW is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_MICROCHIP is not set
 # CONFIG_NET_VENDOR_MICROSEMI is not set
@@ -514,6 +523,7 @@ CONFIG_MLX5_CORE_EN=y
 # CONFIG_NET_VENDOR_TI is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_NET_VENDOR_XILINX is not set
 CONFIG_PPP=m
 CONFIG_PPP_BSDCOMP=m
 CONFIG_PPP_DEFLATE=m
@@ -561,6 +571,8 @@ CONFIG_VFIO_MDEV_DEVICE=m
 CONFIG_VIRTIO_PCI=m
 CONFIG_VIRTIO_BALLOON=m
 CONFIG_VIRTIO_INPUT=y
+CONFIG_VHOST_NET=m
+CONFIG_VHOST_VSOCK=m
 CONFIG_S390_CCW_IOMMU=y
 CONFIG_S390_AP_IOMMU=y
 CONFIG_EXT4_FS=y
@@ -608,6 +620,7 @@ CONFIG_ZISOFS=y
 CONFIG_UDF_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
+CONFIG_EXFAT_FS=m
 CONFIG_NTFS_FS=m
 CONFIG_NTFS_RW=y
 CONFIG_PROC_KCORE=y
@@ -650,8 +663,8 @@ CONFIG_NLS_UTF8=m
 CONFIG_DLM=m
 CONFIG_UNICODE=y
 CONFIG_PERSISTENT_KEYRINGS=y
-CONFIG_BIG_KEYS=y
 CONFIG_ENCRYPTED_KEYS=m
+CONFIG_KEY_NOTIFICATIONS=y
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 CONFIG_FORTIFY_SOURCE=y
@@ -675,8 +688,11 @@ CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_DH=m
 CONFIG_CRYPTO_ECDH=m
 CONFIG_CRYPTO_ECRDSA=m
+CONFIG_CRYPTO_CURVE25519=m
+CONFIG_CRYPTO_GCM=y
 CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_SEQIV=y
 CONFIG_CRYPTO_CFB=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
@@ -685,6 +701,7 @@ CONFIG_CRYPTO_ADIANTUM=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
+CONFIG_CRYPTO_BLAKE2S=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
@@ -701,6 +718,7 @@ CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SALSA20=m
@@ -719,6 +737,9 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
 CONFIG_CRYPTO_USER_API_AEAD=m
 CONFIG_CRYPTO_STATS=y
+CONFIG_CRYPTO_LIB_BLAKE2S=m
+CONFIG_CRYPTO_LIB_CURVE25519=m
+CONFIG_CRYPTO_LIB_CHACHA20POLY1305=m
 CONFIG_ZCRYPT=m
 CONFIG_PKEY=m
 CONFIG_CRYPTO_PAES_S390=m
@@ -774,6 +795,7 @@ CONFIG_DEBUG_SHIRQ=y
 CONFIG_PANIC_ON_OOPS=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_WQ_WATCHDOG=y
+CONFIG_TEST_LOCKUP=m
 CONFIG_DEBUG_TIMEKEEPING=y
 CONFIG_PROVE_LOCKING=y
 CONFIG_LOCK_STAT=y
@@ -786,7 +808,9 @@ CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_DEBUG_CREDENTIALS=y
 CONFIG_RCU_TORTURE_TEST=m
 CONFIG_RCU_CPU_STALL_TIMEOUT=300
+# CONFIG_RCU_TRACE is not set
 CONFIG_LATENCYTOP=y
+CONFIG_BOOTTIME_TRACING=y
 CONFIG_FUNCTION_PROFILER=y
 CONFIG_STACK_TRACER=y
 CONFIG_IRQSOFF_TRACER=y
@@ -808,10 +832,12 @@ CONFIG_FAULT_INJECTION_DEBUG_FS=y
 CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
 CONFIG_LKDTM=m
 CONFIG_TEST_LIST_SORT=y
+CONFIG_TEST_MIN_HEAP=y
 CONFIG_TEST_SORT=y
 CONFIG_KPROBES_SANITY_TEST=y
 CONFIG_RBTREE_TEST=y
 CONFIG_INTERVAL_TREE_TEST=m
 CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
+CONFIG_TEST_BITOPS=m
 CONFIG_TEST_BPF=m
index 7cd0648..5df9759 100644 (file)
@@ -1,5 +1,6 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_WATCH_QUEUE=y
 CONFIG_AUDIT=y
 CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -13,7 +14,6 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_NUMA_BALANCING=y
 CONFIG_MEMCG=y
-CONFIG_MEMCG_SWAP=y
 CONFIG_BLK_CGROUP=y
 CONFIG_CFS_BANDWIDTH=y
 CONFIG_RT_GROUP_SCHED=y
@@ -30,9 +30,9 @@ CONFIG_NAMESPACES=y
 CONFIG_USER_NS=y
 CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_SCHED_AUTOGROUP=y
-CONFIG_BLK_DEV_INITRD=y
 CONFIG_EXPERT=y
 # CONFIG_SYSFS_SYSCALL is not set
+CONFIG_BPF_LSM=y
 CONFIG_BPF_SYSCALL=y
 CONFIG_USERFAULTFD=y
 # CONFIG_COMPAT_BRK is not set
@@ -41,7 +41,6 @@ CONFIG_LIVEPATCH=y
 CONFIG_TUNE_ZEC12=y
 CONFIG_NR_CPUS=512
 CONFIG_NUMA=y
-# CONFIG_NUMA_EMU is not set
 CONFIG_HZ_100=y
 CONFIG_KEXEC_FILE=y
 CONFIG_KEXEC_SIG=y
@@ -51,14 +50,11 @@ CONFIG_CHSC_SCH=y
 CONFIG_VFIO_CCW=m
 CONFIG_VFIO_AP=m
 CONFIG_CRASH_DUMP=y
-CONFIG_HIBERNATION=y
-CONFIG_PM_DEBUG=y
 CONFIG_PROTECTED_VIRTUALIZATION_GUEST=y
 CONFIG_CMM=m
 CONFIG_APPLDATA_BASE=y
 CONFIG_KVM=m
-CONFIG_VHOST_NET=m
-CONFIG_VHOST_VSOCK=m
+CONFIG_S390_UNWIND_SELFTEST=m
 CONFIG_OPROFILE=m
 CONFIG_KPROBES=y
 CONFIG_JUMP_LABEL=y
@@ -74,6 +70,8 @@ CONFIG_BLK_DEV_THROTTLING=y
 CONFIG_BLK_WBT=y
 CONFIG_BLK_CGROUP_IOLATENCY=y
 CONFIG_BLK_CGROUP_IOCOST=y
+CONFIG_BLK_INLINE_ENCRYPTION=y
+CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
 CONFIG_BSD_DISKLABEL=y
@@ -91,7 +89,6 @@ CONFIG_CLEANCACHE=y
 CONFIG_FRONTSWAP=y
 CONFIG_MEM_SOFT_DIRTY=y
 CONFIG_ZSWAP=y
-CONFIG_ZBUD=m
 CONFIG_ZSMALLOC=m
 CONFIG_ZSMALLOC_STAT=y
 CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
@@ -125,6 +122,7 @@ CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
+CONFIG_INET_ESPINTCP=y
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
@@ -139,6 +137,7 @@ CONFIG_TCP_CONG_ILLINOIS=m
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
+CONFIG_INET6_ESPINTCP=y
 CONFIG_INET6_IPCOMP=m
 CONFIG_IPV6_MIP6=m
 CONFIG_IPV6_VTI=m
@@ -146,7 +145,10 @@ CONFIG_IPV6_SIT=m
 CONFIG_IPV6_GRE=m
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_RPL_LWTUNNEL=y
+CONFIG_MPTCP=y
 CONFIG_NETFILTER=y
+CONFIG_BRIDGE_NETFILTER=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
@@ -311,6 +313,7 @@ CONFIG_L2TP_V3=y
 CONFIG_L2TP_IP=m
 CONFIG_L2TP_ETH=m
 CONFIG_BRIDGE=m
+CONFIG_BRIDGE_MRP=y
 CONFIG_VLAN_8021Q=m
 CONFIG_VLAN_8021Q_GVRP=y
 CONFIG_NET_SCHED=y
@@ -335,6 +338,7 @@ CONFIG_NET_SCH_CODEL=m
 CONFIG_NET_SCH_FQ_CODEL=m
 CONFIG_NET_SCH_INGRESS=m
 CONFIG_NET_SCH_PLUG=m
+CONFIG_NET_SCH_ETS=m
 CONFIG_NET_CLS_BASIC=m
 CONFIG_NET_CLS_TCINDEX=m
 CONFIG_NET_CLS_ROUTE4=m
@@ -358,6 +362,7 @@ CONFIG_NET_ACT_PEDIT=m
 CONFIG_NET_ACT_SIMP=m
 CONFIG_NET_ACT_SKBEDIT=m
 CONFIG_NET_ACT_CSUM=m
+CONFIG_NET_ACT_GATE=m
 CONFIG_DNS_RESOLVER=y
 CONFIG_OPENVSWITCH=m
 CONFIG_VSOCKETS=m
@@ -368,6 +373,7 @@ CONFIG_BPF_JIT=y
 CONFIG_NET_PKTGEN=m
 # CONFIG_NET_DROP_MONITOR is not set
 CONFIG_PCI=y
+# CONFIG_PCIEASPM is not set
 CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_S390=y
 CONFIG_UEVENT_HELPER=y
@@ -430,6 +436,7 @@ CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 CONFIG_DM_MULTIPATH_QL=m
 CONFIG_DM_MULTIPATH_ST=m
+CONFIG_DM_MULTIPATH_HST=m
 CONFIG_DM_DELAY=m
 CONFIG_DM_UEVENT=y
 CONFIG_DM_FLAKEY=m
@@ -444,6 +451,8 @@ CONFIG_EQUALIZER=m
 CONFIG_IFB=m
 CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
+CONFIG_VXLAN=m
+CONFIG_BAREUDP=m
 CONFIG_TUN=m
 CONFIG_VETH=m
 CONFIG_VIRTIO_NET=m
@@ -477,7 +486,6 @@ CONFIG_NLMON=m
 CONFIG_MLX4_EN=m
 CONFIG_MLX5_CORE=m
 CONFIG_MLX5_CORE_EN=y
-# CONFIG_MLXFW is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_MICROCHIP is not set
 # CONFIG_NET_VENDOR_MICROSEMI is not set
@@ -510,6 +518,7 @@ CONFIG_MLX5_CORE_EN=y
 # CONFIG_NET_VENDOR_TI is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_NET_VENDOR_XILINX is not set
 CONFIG_PPP=m
 CONFIG_PPP_BSDCOMP=m
 CONFIG_PPP_DEFLATE=m
@@ -557,6 +566,8 @@ CONFIG_VFIO_MDEV_DEVICE=m
 CONFIG_VIRTIO_PCI=m
 CONFIG_VIRTIO_BALLOON=m
 CONFIG_VIRTIO_INPUT=y
+CONFIG_VHOST_NET=m
+CONFIG_VHOST_VSOCK=m
 CONFIG_S390_CCW_IOMMU=y
 CONFIG_S390_AP_IOMMU=y
 CONFIG_EXT4_FS=y
@@ -600,6 +611,7 @@ CONFIG_ZISOFS=y
 CONFIG_UDF_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
+CONFIG_EXFAT_FS=m
 CONFIG_NTFS_FS=m
 CONFIG_NTFS_RW=y
 CONFIG_PROC_KCORE=y
@@ -642,8 +654,8 @@ CONFIG_NLS_UTF8=m
 CONFIG_DLM=m
 CONFIG_UNICODE=y
 CONFIG_PERSISTENT_KEYRINGS=y
-CONFIG_BIG_KEYS=y
 CONFIG_ENCRYPTED_KEYS=m
+CONFIG_KEY_NOTIFICATIONS=y
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 CONFIG_SECURITY_SELINUX=y
@@ -667,8 +679,11 @@ CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_DH=m
 CONFIG_CRYPTO_ECDH=m
 CONFIG_CRYPTO_ECRDSA=m
+CONFIG_CRYPTO_CURVE25519=m
+CONFIG_CRYPTO_GCM=y
 CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_SEQIV=y
 CONFIG_CRYPTO_CFB=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_OFB=m
@@ -678,6 +693,7 @@ CONFIG_CRYPTO_ADIANTUM=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
+CONFIG_CRYPTO_BLAKE2S=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
@@ -694,6 +710,7 @@ CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SALSA20=m
@@ -712,6 +729,9 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
 CONFIG_CRYPTO_USER_API_AEAD=m
 CONFIG_CRYPTO_STATS=y
+CONFIG_CRYPTO_LIB_BLAKE2S=m
+CONFIG_CRYPTO_LIB_CURVE25519=m
+CONFIG_CRYPTO_LIB_CHACHA20POLY1305=m
 CONFIG_ZCRYPT=m
 CONFIG_PKEY=m
 CONFIG_CRYPTO_PAES_S390=m
@@ -725,6 +745,7 @@ CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_CRYPTO_CRC32_S390=y
 CONFIG_CORDIC=m
+CONFIG_PRIME_NUMBERS=m
 CONFIG_CRC4=m
 CONFIG_CRC7=m
 CONFIG_CRC8=m
@@ -739,10 +760,12 @@ CONFIG_DEBUG_SECTION_MISMATCH=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_PANIC_ON_OOPS=y
+CONFIG_TEST_LOCKUP=m
 CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_RCU_TORTURE_TEST=m
 CONFIG_RCU_CPU_STALL_TIMEOUT=60
 CONFIG_LATENCYTOP=y
+CONFIG_BOOTTIME_TRACING=y
 CONFIG_FUNCTION_PROFILER=y
 CONFIG_STACK_TRACER=y
 CONFIG_SCHED_TRACER=y
index 20c51e5..4091c50 100644 (file)
@@ -30,6 +30,7 @@ CONFIG_IBM_PARTITION=y
 # CONFIG_BOUNCE is not set
 CONFIG_NET=y
 # CONFIG_IUCV is not set
+# CONFIG_ETHTOOL_NETLINK is not set
 CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_RAM=y
 # CONFIG_BLK_DEV_XPRAM is not set
@@ -55,6 +56,8 @@ CONFIG_RAW_DRIVER=y
 # CONFIG_MONWRITER is not set
 # CONFIG_S390_VMUR is not set
 # CONFIG_HID is not set
+# CONFIG_VIRTIO_MENU is not set
+# CONFIG_VHOST_MENU is not set
 # CONFIG_IOMMU_SUPPORT is not set
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY_USER is not set
@@ -62,7 +65,9 @@ CONFIG_CONFIGFS_FS=y
 # CONFIG_MISC_FILESYSTEMS is not set
 # CONFIG_NETWORK_FILESYSTEMS is not set
 CONFIG_LSM="yama,loadpin,safesetid,integrity"
+# CONFIG_ZLIB_DFLTCC is not set
 CONFIG_PRINTK_TIME=y
+# CONFIG_SYMBOLIC_ERRNAME is not set
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
index d977643..e1ae239 100644 (file)
@@ -693,7 +693,7 @@ static ssize_t prng_chunksize_show(struct device *dev,
                                   struct device_attribute *attr,
                                   char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "%u\n", prng_chunk_size);
+       return scnprintf(buf, PAGE_SIZE, "%u\n", prng_chunk_size);
 }
 static DEVICE_ATTR(chunksize, 0444, prng_chunksize_show, NULL);
 
@@ -712,7 +712,7 @@ static ssize_t prng_counter_show(struct device *dev,
                counter = prng_data->prngws.byte_counter;
        mutex_unlock(&prng_data->mutex);
 
-       return snprintf(buf, PAGE_SIZE, "%llu\n", counter);
+       return scnprintf(buf, PAGE_SIZE, "%llu\n", counter);
 }
 static DEVICE_ATTR(byte_counter, 0444, prng_counter_show, NULL);
 
@@ -721,7 +721,7 @@ static ssize_t prng_errorflag_show(struct device *dev,
                                   struct device_attribute *attr,
                                   char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "%d\n", prng_errorflag);
+       return scnprintf(buf, PAGE_SIZE, "%d\n", prng_errorflag);
 }
 static DEVICE_ATTR(errorflag, 0444, prng_errorflag_show, NULL);
 
@@ -731,9 +731,9 @@ static ssize_t prng_mode_show(struct device *dev,
                              char *buf)
 {
        if (prng_mode == PRNG_MODE_TDES)
-               return snprintf(buf, PAGE_SIZE, "TDES\n");
+               return scnprintf(buf, PAGE_SIZE, "TDES\n");
        else
-               return snprintf(buf, PAGE_SIZE, "SHA512\n");
+               return scnprintf(buf, PAGE_SIZE, "SHA512\n");
 }
 static DEVICE_ATTR(mode, 0444, prng_mode_show, NULL);
 
@@ -756,7 +756,7 @@ static ssize_t prng_reseed_limit_show(struct device *dev,
                                      struct device_attribute *attr,
                                      char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "%u\n", prng_reseed_limit);
+       return scnprintf(buf, PAGE_SIZE, "%u\n", prng_reseed_limit);
 }
 static ssize_t prng_reseed_limit_store(struct device *dev,
                                       struct device_attribute *attr,
@@ -787,7 +787,7 @@ static ssize_t prng_strength_show(struct device *dev,
                                  struct device_attribute *attr,
                                  char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "256\n");
+       return scnprintf(buf, PAGE_SIZE, "256\n");
 }
 static DEVICE_ATTR(strength, 0444, prng_strength_show, NULL);
 
index cee3cb6..6ea0820 100644 (file)
 #define KVM_USER_MEM_SLOTS 32
 
 /*
- * These seem to be used for allocating ->chip in the routing table,
- * which we don't use. 4096 is an out-of-thin-air value. If we need
- * to look at ->chip later on, we'll need to revisit this.
+ * These seem to be used for allocating ->chip in the routing table, which we
+ * don't use. 1 is as small as we can get to reduce the needed memory. If we
+ * need to look at ->chip later on, we'll need to revisit this.
  */
 #define KVM_NR_IRQCHIPS 1
-#define KVM_IRQCHIP_NUM_PINS 4096
+#define KVM_IRQCHIP_NUM_PINS 1
 #define KVM_HALT_POLL_NS_DEFAULT 50000
 
 /* s390-specific vcpu->requests bit members */
index f073292..d9d5de0 100644 (file)
@@ -33,7 +33,17 @@ static inline void syscall_rollback(struct task_struct *task,
 static inline long syscall_get_error(struct task_struct *task,
                                     struct pt_regs *regs)
 {
-       return IS_ERR_VALUE(regs->gprs[2]) ? regs->gprs[2] : 0;
+       unsigned long error = regs->gprs[2];
+#ifdef CONFIG_COMPAT
+       if (test_tsk_thread_flag(task, TIF_31BIT)) {
+               /*
+                * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
+                * and will match correctly in comparisons.
+                */
+               error = (long)(int)error;
+       }
+#endif
+       return IS_ERR_VALUE(error) ? error : 0;
 }
 
 static inline long syscall_get_return_value(struct task_struct *task,
index 3bcfdeb..0cd085c 100644 (file)
@@ -36,6 +36,7 @@ struct vdso_data {
        __u32 tk_shift;                 /* Shift used for xtime_nsec    0x60 */
        __u32 ts_dir;                   /* TOD steering direction       0x64 */
        __u64 ts_end;                   /* TOD steering end             0x68 */
+       __u32 hrtimer_res;              /* hrtimer resolution           0x70 */
 };
 
 struct vdso_per_cpu_data {
index 165031b..5d8cc18 100644 (file)
@@ -76,6 +76,7 @@ int main(void)
        OFFSET(__VDSO_TK_SHIFT, vdso_data, tk_shift);
        OFFSET(__VDSO_TS_DIR, vdso_data, ts_dir);
        OFFSET(__VDSO_TS_END, vdso_data, ts_end);
+       OFFSET(__VDSO_CLOCK_REALTIME_RES, vdso_data, hrtimer_res);
        OFFSET(__VDSO_ECTG_BASE, vdso_per_cpu_data, ectg_timer_base);
        OFFSET(__VDSO_ECTG_USER, vdso_per_cpu_data, ectg_user_time);
        OFFSET(__VDSO_GETCPU_VAL, vdso_per_cpu_data, getcpu_val);
@@ -86,7 +87,6 @@ int main(void)
        DEFINE(__CLOCK_REALTIME_COARSE, CLOCK_REALTIME_COARSE);
        DEFINE(__CLOCK_MONOTONIC_COARSE, CLOCK_MONOTONIC_COARSE);
        DEFINE(__CLOCK_THREAD_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID);
-       DEFINE(__CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
        DEFINE(__CLOCK_COARSE_RES, LOW_RES_NSEC);
        BLANK();
        /* idle data offsets */
index 6364460..263075a 100644 (file)
@@ -198,9 +198,10 @@ static debug_entry_t ***debug_areas_alloc(int pages_per_area, int nr_areas)
        if (!areas)
                goto fail_malloc_areas;
        for (i = 0; i < nr_areas; i++) {
+               /* GFP_NOWARN to avoid user triggerable WARN, we handle fails */
                areas[i] = kmalloc_array(pages_per_area,
                                         sizeof(debug_entry_t *),
-                                        GFP_KERNEL);
+                                        GFP_KERNEL | __GFP_NOWARN);
                if (!areas[i])
                        goto fail_malloc_areas2;
                for (j = 0; j < pages_per_area; j++) {
index cd241ee..0782772 100644 (file)
@@ -170,6 +170,8 @@ static noinline __init void setup_lowcore_early(void)
        psw_t psw;
 
        psw.mask = PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA;
+       if (IS_ENABLED(CONFIG_KASAN))
+               psw.mask |= PSW_MASK_DAT;
        psw.addr = (unsigned long) s390_base_ext_handler;
        S390_lowcore.external_new_psw = psw;
        psw.addr = (unsigned long) s390_base_pgm_handler;
index 50ff6dd..969b35b 100644 (file)
@@ -378,9 +378,9 @@ ENTRY(system_call)
        stmg    %r8,%r15,__LC_SAVE_AREA_SYNC
        BPOFF
        lg      %r12,__LC_CURRENT
-       lghi    %r13,__TASK_thread
        lghi    %r14,_PIF_SYSCALL
 .Lsysc_per:
+       lghi    %r13,__TASK_thread
        lg      %r15,__LC_KERNEL_STACK
        la      %r11,STACK_FRAME_OVERHEAD(%r15) # pointer to pt_regs
        UPDATE_VTIME %r8,%r9,__LC_SYNC_ENTER_TIMER
@@ -401,9 +401,9 @@ ENTRY(system_call)
        jnz     .Lsysc_nr_ok
        # svc 0: system call number in %r1
        llgfr   %r1,%r1                         # clear high word in r1
+       sth     %r1,__PT_INT_CODE+2(%r11)
        cghi    %r1,NR_syscalls
        jnl     .Lsysc_nr_ok
-       sth     %r1,__PT_INT_CODE+2(%r11)
        slag    %r8,%r1,3
 .Lsysc_nr_ok:
        xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
index 44e01dd..b388e87 100644 (file)
@@ -83,7 +83,7 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
 {
        struct ftrace_insn orig, new, old;
 
-       if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old)))
+       if (copy_from_kernel_nofault(&old, (void *) rec->ip, sizeof(old)))
                return -EFAULT;
        if (addr == MCOUNT_ADDR) {
                /* Initial code replacement */
@@ -105,7 +105,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 {
        struct ftrace_insn orig, new, old;
 
-       if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old)))
+       if (copy_from_kernel_nofault(&old, (void *) rec->ip, sizeof(old)))
                return -EFAULT;
        /* Replace nop with an ftrace call. */
        ftrace_generate_nop_insn(&orig);
index ccea9a2..90a2a17 100644 (file)
@@ -181,7 +181,7 @@ static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj, \
                struct kobj_attribute *attr,                            \
                char *page)                                             \
 {                                                                      \
-       return snprintf(page, PAGE_SIZE, _format, ##args);              \
+       return scnprintf(page, PAGE_SIZE, _format, ##args);             \
 }
 
 #define IPL_ATTR_CCW_STORE_FN(_prefix, _name, _ipl_blk)                        \
index 1e3df52..37265f5 100644 (file)
@@ -292,7 +292,7 @@ CPUMF_EVENT_ATTR(cf_z15, TX_C_TABORT_SPECIAL, 0x00f5);
 CPUMF_EVENT_ATTR(cf_z15, DFLT_ACCESS, 0x00f7);
 CPUMF_EVENT_ATTR(cf_z15, DFLT_CYCLES, 0x00fc);
 CPUMF_EVENT_ATTR(cf_z15, DFLT_CC, 0x00108);
-CPUMF_EVENT_ATTR(cf_z15, DFLT_CCERROR, 0x00109);
+CPUMF_EVENT_ATTR(cf_z15, DFLT_CCFINISH, 0x00109);
 CPUMF_EVENT_ATTR(cf_z15, MT_DIAG_CYCLES_ONE_THR_ACTIVE, 0x01c0);
 CPUMF_EVENT_ATTR(cf_z15, MT_DIAG_CYCLES_TWO_THR_ACTIVE, 0x01c1);
 
@@ -629,7 +629,7 @@ static struct attribute *cpumcf_z15_pmu_event_attr[] __initdata = {
        CPUMF_EVENT_PTR(cf_z15, DFLT_ACCESS),
        CPUMF_EVENT_PTR(cf_z15, DFLT_CYCLES),
        CPUMF_EVENT_PTR(cf_z15, DFLT_CC),
-       CPUMF_EVENT_PTR(cf_z15, DFLT_CCERROR),
+       CPUMF_EVENT_PTR(cf_z15, DFLT_CCFINISH),
        CPUMF_EVENT_PTR(cf_z15, MT_DIAG_CYCLES_ONE_THR_ACTIVE),
        CPUMF_EVENT_PTR(cf_z15, MT_DIAG_CYCLES_TWO_THR_ACTIVE),
        NULL,
index 85a711d..4f9e462 100644 (file)
@@ -881,12 +881,21 @@ out:
        return err;
 }
 
+static bool is_callchain_event(struct perf_event *event)
+{
+       u64 sample_type = event->attr.sample_type;
+
+       return sample_type & (PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_REGS_USER |
+                             PERF_SAMPLE_STACK_USER);
+}
+
 static int cpumsf_pmu_event_init(struct perf_event *event)
 {
        int err;
 
        /* No support for taken branch sampling */
-       if (has_branch_stack(event))
+       /* No support for callchain, stacks and registers */
+       if (has_branch_stack(event) || is_callchain_event(event))
                return -EOPNOTSUPP;
 
        switch (event->attr.type) {
index ce60a45..3cc15c0 100644 (file)
@@ -323,6 +323,25 @@ static inline void __poke_user_per(struct task_struct *child,
                child->thread.per_user.end = data;
 }
 
+static void fixup_int_code(struct task_struct *child, addr_t data)
+{
+       struct pt_regs *regs = task_pt_regs(child);
+       int ilc = regs->int_code >> 16;
+       u16 insn;
+
+       if (ilc > 6)
+               return;
+
+       if (ptrace_access_vm(child, regs->psw.addr - (regs->int_code >> 16),
+                       &insn, sizeof(insn), FOLL_FORCE) != sizeof(insn))
+               return;
+
+       /* double check that tracee stopped on svc instruction */
+       if ((insn >> 8) != 0xa)
+               return;
+
+       regs->int_code = 0x20000 | (data & 0xffff);
+}
 /*
  * Write a word to the user area of a process at location addr. This
  * operation does have an additional problem compared to peek_user.
@@ -334,7 +353,9 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
        struct user *dummy = NULL;
        addr_t offset;
 
+
        if (addr < (addr_t) &dummy->regs.acrs) {
+               struct pt_regs *regs = task_pt_regs(child);
                /*
                 * psw and gprs are stored on the stack
                 */
@@ -352,7 +373,11 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
                                /* Invalid addressing mode bits */
                                return -EINVAL;
                }
-               *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data;
+
+               if (test_pt_regs_flag(regs, PIF_SYSCALL) &&
+                       addr == offsetof(struct user, regs.gprs[2]))
+                       fixup_int_code(child, data);
+               *(addr_t *)((addr_t) &regs->psw + addr) = data;
 
        } else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) {
                /*
@@ -718,6 +743,10 @@ static int __poke_user_compat(struct task_struct *child,
                        regs->psw.mask = (regs->psw.mask & ~PSW_MASK_BA) |
                                (__u64)(tmp & PSW32_ADDR_AMODE);
                } else {
+
+                       if (test_pt_regs_flag(regs, PIF_SYSCALL) &&
+                               addr == offsetof(struct compat_user, regs.gprs[2]))
+                               fixup_int_code(child, data);
                        /* gpr 0-15 */
                        *(__u32*)((addr_t) &regs->psw + addr*2 + 4) = tmp;
                }
@@ -837,40 +866,66 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
 {
        unsigned long mask = -1UL;
+       long ret = -1;
+
+       if (is_compat_task())
+               mask = 0xffffffff;
 
        /*
         * The sysc_tracesys code in entry.S stored the system
         * call number to gprs[2].
         */
        if (test_thread_flag(TIF_SYSCALL_TRACE) &&
-           (tracehook_report_syscall_entry(regs) ||
-            regs->gprs[2] >= NR_syscalls)) {
+           tracehook_report_syscall_entry(regs)) {
                /*
-                * Tracing decided this syscall should not happen or the
-                * debugger stored an invalid system call number. Skip
+                * Tracing decided this syscall should not happen. Skip
                 * the system call and the system call restart handling.
                 */
-               clear_pt_regs_flag(regs, PIF_SYSCALL);
-               return -1;
+               goto skip;
        }
 
+#ifdef CONFIG_SECCOMP
        /* Do the secure computing check after ptrace. */
-       if (secure_computing()) {
-               /* seccomp failures shouldn't expose any additional code. */
-               return -1;
+       if (unlikely(test_thread_flag(TIF_SECCOMP))) {
+               struct seccomp_data sd;
+
+               if (is_compat_task()) {
+                       sd.instruction_pointer = regs->psw.addr & 0x7fffffff;
+                       sd.arch = AUDIT_ARCH_S390;
+               } else {
+                       sd.instruction_pointer = regs->psw.addr;
+                       sd.arch = AUDIT_ARCH_S390X;
+               }
+
+               sd.nr = regs->int_code & 0xffff;
+               sd.args[0] = regs->orig_gpr2 & mask;
+               sd.args[1] = regs->gprs[3] & mask;
+               sd.args[2] = regs->gprs[4] & mask;
+               sd.args[3] = regs->gprs[5] & mask;
+               sd.args[4] = regs->gprs[6] & mask;
+               sd.args[5] = regs->gprs[7] & mask;
+
+               if (__secure_computing(&sd) == -1)
+                       goto skip;
        }
+#endif /* CONFIG_SECCOMP */
 
        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
-               trace_sys_enter(regs, regs->gprs[2]);
+               trace_sys_enter(regs, regs->int_code & 0xffff);
 
-       if (is_compat_task())
-               mask = 0xffffffff;
 
-       audit_syscall_entry(regs->gprs[2], regs->orig_gpr2 & mask,
+       audit_syscall_entry(regs->int_code & 0xffff, regs->orig_gpr2 & mask,
                            regs->gprs[3] &mask, regs->gprs[4] &mask,
                            regs->gprs[5] &mask);
 
+       if ((signed long)regs->gprs[2] >= NR_syscalls) {
+               regs->gprs[2] = -ENOSYS;
+               ret = -ENOSYS;
+       }
        return regs->gprs[2];
+skip:
+       clear_pt_regs_flag(regs, PIF_SYSCALL);
+       return ret;
 }
 
 asmlinkage void do_syscall_trace_exit(struct pt_regs *regs)
index 5853c98..07aa15b 100644 (file)
@@ -1100,6 +1100,7 @@ void __init setup_arch(char **cmdline_p)
        if (IS_ENABLED(CONFIG_EXPOLINE_AUTO))
                nospec_auto_detect();
 
+       jump_label_init();
        parse_early_param();
 #ifdef CONFIG_CRASH_DUMP
        /* Deactivate elfcorehdr= kernel parameter */
index f9d070d..b1113b5 100644 (file)
@@ -301,6 +301,7 @@ void update_vsyscall(struct timekeeper *tk)
 
        vdso_data->tk_mult = tk->tkr_mono.mult;
        vdso_data->tk_shift = tk->tkr_mono.shift;
+       vdso_data->hrtimer_res = hrtimer_resolution;
        smp_wmb();
        ++vdso_data->tb_update_count;
 }
index 66e89b2..c296e5c 100644 (file)
@@ -331,7 +331,7 @@ EXPORT_SYMBOL_GPL(arch_make_page_accessible);
 static ssize_t uv_query_facilities(struct kobject *kobj,
                                   struct kobj_attribute *attr, char *page)
 {
-       return snprintf(page, PAGE_SIZE, "%lx\n%lx\n%lx\n%lx\n",
+       return scnprintf(page, PAGE_SIZE, "%lx\n%lx\n%lx\n%lx\n",
                        uv_info.inst_calls_list[0],
                        uv_info.inst_calls_list[1],
                        uv_info.inst_calls_list[2],
@@ -344,7 +344,7 @@ static struct kobj_attribute uv_query_facilities_attr =
 static ssize_t uv_query_max_guest_cpus(struct kobject *kobj,
                                       struct kobj_attribute *attr, char *page)
 {
-       return snprintf(page, PAGE_SIZE, "%d\n",
+       return scnprintf(page, PAGE_SIZE, "%d\n",
                        uv_info.max_guest_cpus);
 }
 
@@ -354,7 +354,7 @@ static struct kobj_attribute uv_query_max_guest_cpus_attr =
 static ssize_t uv_query_max_guest_vms(struct kobject *kobj,
                                      struct kobj_attribute *attr, char *page)
 {
-       return snprintf(page, PAGE_SIZE, "%d\n",
+       return scnprintf(page, PAGE_SIZE, "%d\n",
                        uv_info.max_num_sec_conf);
 }
 
@@ -364,7 +364,7 @@ static struct kobj_attribute uv_query_max_guest_vms_attr =
 static ssize_t uv_query_max_guest_addr(struct kobject *kobj,
                                       struct kobj_attribute *attr, char *page)
 {
-       return snprintf(page, PAGE_SIZE, "%lx\n",
+       return scnprintf(page, PAGE_SIZE, "%lx\n",
                        uv_info.max_sec_stor_addr);
 }
 
index bec19e7..4a66a1c 100644 (file)
@@ -18,8 +18,8 @@ KBUILD_AFLAGS_64 += -m64 -s
 
 KBUILD_CFLAGS_64 := $(filter-out -m64,$(KBUILD_CFLAGS))
 KBUILD_CFLAGS_64 += -m64 -fPIC -shared -fno-common -fno-builtin
-KBUILD_CFLAGS_64 += -nostdlib -Wl,-soname=linux-vdso64.so.1 \
-                   -Wl,--hash-style=both
+ldflags-y := -fPIC -shared -nostdlib -soname=linux-vdso64.so.1 \
+            --hash-style=both --build-id -T
 
 $(targets:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_64)
 $(targets:%=$(obj)/%.dbg): KBUILD_AFLAGS = $(KBUILD_AFLAGS_64)
@@ -37,8 +37,8 @@ KASAN_SANITIZE := n
 $(obj)/vdso64_wrapper.o : $(obj)/vdso64.so
 
 # link rule for the .so file, .lds has to be first
-$(obj)/vdso64.so.dbg: $(src)/vdso64.lds $(obj-vdso64) FORCE
-       $(call if_changed,vdso64ld)
+$(obj)/vdso64.so.dbg: $(obj)/vdso64.lds $(obj-vdso64) FORCE
+       $(call if_changed,ld)
 
 # strip rule for the .so file
 $(obj)/%.so: OBJCOPYFLAGS := -S
@@ -50,8 +50,6 @@ $(obj-vdso64): %.o: %.S FORCE
        $(call if_changed_dep,vdso64as)
 
 # actual build commands
-quiet_cmd_vdso64ld = VDSO64L $@
-      cmd_vdso64ld = $(CC) $(c_flags) -Wl,-T $(filter %.lds %.o,$^) -o $@
 quiet_cmd_vdso64as = VDSO64A $@
       cmd_vdso64as = $(CC) $(a_flags) -c -o $@ $<
 
index 0814353..0c79caa 100644 (file)
        .type  __kernel_clock_getres,@function
 __kernel_clock_getres:
        CFI_STARTPROC
-       larl    %r1,4f
+       larl    %r1,3f
+       lg      %r0,0(%r1)
        cghi    %r2,__CLOCK_REALTIME_COARSE
        je      0f
        cghi    %r2,__CLOCK_MONOTONIC_COARSE
        je      0f
-       larl    %r1,3f
+       larl    %r1,_vdso_data
+       llgf    %r0,__VDSO_CLOCK_REALTIME_RES(%r1)
        cghi    %r2,__CLOCK_REALTIME
        je      0f
        cghi    %r2,__CLOCK_MONOTONIC
@@ -36,7 +38,6 @@ __kernel_clock_getres:
        jz      2f
 0:     ltgr    %r3,%r3
        jz      1f                              /* res == NULL */
-       lg      %r0,0(%r1)
        xc      0(8,%r3),0(%r3)                 /* set tp->tv_sec to zero */
        stg     %r0,8(%r3)                      /* store tp->tv_usec */
 1:     lghi    %r2,0
@@ -45,6 +46,5 @@ __kernel_clock_getres:
        svc     0
        br      %r14
        CFI_ENDPROC
-3:     .quad   __CLOCK_REALTIME_RES
-4:     .quad   __CLOCK_COARSE_RES
+3:     .quad   __CLOCK_COARSE_RES
        .size   __kernel_clock_getres,.-__kernel_clock_getres
index 6a24751..d53c2e2 100644 (file)
@@ -105,7 +105,7 @@ static int bad_address(void *p)
 {
        unsigned long dummy;
 
-       return probe_kernel_address((unsigned long *)p, dummy);
+       return get_kernel_nofault(dummy, (unsigned long *)p);
 }
 
 static void dump_pagetable(unsigned long asce, unsigned long address)
index 82df06d..3b5a4d2 100644 (file)
@@ -117,7 +117,7 @@ static inline pte_t __rste_to_pte(unsigned long rste)
                                             _PAGE_YOUNG);
 #ifdef CONFIG_MEM_SOFT_DIRTY
                pte_val(pte) |= move_set_bit(rste, _SEGMENT_ENTRY_SOFT_DIRTY,
-                                            _PAGE_DIRTY);
+                                            _PAGE_SOFT_DIRTY);
 #endif
                pte_val(pte) |= move_set_bit(rste, _SEGMENT_ENTRY_NOEXEC,
                                             _PAGE_NOEXEC);
index 22a0be6..1d17413 100644 (file)
@@ -62,11 +62,15 @@ notrace void *s390_kernel_write(void *dst, const void *src, size_t size)
        long copied;
 
        spin_lock_irqsave(&s390_kernel_write_lock, flags);
-       while (size) {
-               copied = s390_kernel_write_odd(tmp, src, size);
-               tmp += copied;
-               src += copied;
-               size -= copied;
+       if (!(flags & PSW_MASK_DAT)) {
+               memcpy(dst, src, size);
+       } else {
+               while (size) {
+                       copied = s390_kernel_write_odd(tmp, src, size);
+                       tmp += copied;
+                       src += copied;
+                       size -= copied;
+               }
        }
        spin_unlock_irqrestore(&s390_kernel_write_lock, flags);
 
index 08e1d61..fdebd28 100644 (file)
@@ -94,7 +94,18 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
                }
                zdev->fh = ccdf->fh;
                zdev->state = ZPCI_FN_STATE_CONFIGURED;
-               zpci_create_device(zdev);
+               ret = zpci_enable_device(zdev);
+               if (ret)
+                       break;
+
+               pdev = pci_scan_single_device(zdev->zbus->bus, zdev->devfn);
+               if (!pdev)
+                       break;
+
+               pci_bus_add_device(pdev);
+               pci_lock_rescan_remove();
+               pci_bus_add_devices(zdev->zbus->bus);
+               pci_unlock_rescan_remove();
                break;
        case 0x0302: /* Reserved -> Standby */
                if (!zdev) {
index 22d968b..d770da3 100644 (file)
@@ -12,6 +12,7 @@ extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
 extern void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd);
 extern pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address);
 extern void pmd_free(struct mm_struct *mm, pmd_t *pmd);
+#define __pmd_free_tlb(tlb, pmdp, addr)                pmd_free((tlb)->mm, (pmdp))
 #endif
 
 static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
@@ -33,13 +34,4 @@ do {                                                 \
        tlb_remove_page((tlb), (pte));                  \
 } while (0)
 
-#if CONFIG_PGTABLE_LEVELS > 2
-#define __pmd_free_tlb(tlb, pmdp, addr)                        \
-do {                                                   \
-       struct page *page = virt_to_page(pmdp);         \
-       pgtable_pmd_page_dtor(page);                    \
-       tlb_remove_page((tlb), page);                   \
-} while (0);
-#endif
-
 #endif /* __ASM_SH_PGALLOC_H */
index 956a7a0..9bac5bb 100644 (file)
@@ -199,7 +199,7 @@ syscall_trace_entry:
        mov.l   @(OFF_R7,r15), r7   ! arg3
        mov.l   @(OFF_R3,r15), r3   ! syscall_nr
        !
-       mov.l   2f, r10                 ! Number of syscalls
+       mov.l   6f, r10                 ! Number of syscalls
        cmp/hs  r10, r3
        bf      syscall_call
        mov     #-ENOSYS, r0
@@ -353,7 +353,7 @@ ENTRY(system_call)
        tst     r9, r8
        bf      syscall_trace_entry
        !
-       mov.l   2f, r8                  ! Number of syscalls
+       mov.l   6f, r8                  ! Number of syscalls
        cmp/hs  r8, r3
        bt      syscall_badsys
        !
@@ -392,7 +392,7 @@ syscall_exit:
 #if !defined(CONFIG_CPU_SH2)
 1:     .long   TRA
 #endif
-2:     .long   NR_syscalls
+6:     .long   NR_syscalls
 3:     .long   sys_call_table
 7:     .long   do_syscall_trace_enter
 8:     .long   do_syscall_trace_leave
index 1b04270..0646c59 100644 (file)
@@ -119,7 +119,7 @@ static void ftrace_mod_code(void)
         * But if one were to fail, then they all should, and if one were
         * to succeed, then they all should.
         */
-       mod_code_status = probe_kernel_write(mod_code_ip, mod_code_newcode,
+       mod_code_status = copy_to_kernel_nofault(mod_code_ip, mod_code_newcode,
                                             MCOUNT_INSN_SIZE);
 
        /* if we fail, then kill any new writers */
@@ -203,7 +203,7 @@ static int ftrace_modify_code(unsigned long ip, unsigned char *old_code,
         */
 
        /* read the text we want to modify */
-       if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
+       if (copy_from_kernel_nofault(replaced, (void *)ip, MCOUNT_INSN_SIZE))
                return -EFAULT;
 
        /* Make sure it is what we expect it to be */
@@ -268,7 +268,7 @@ static int ftrace_mod(unsigned long ip, unsigned long old_addr,
 {
        unsigned char code[MCOUNT_INSN_SIZE];
 
-       if (probe_kernel_read(code, (void *)ip, MCOUNT_INSN_SIZE))
+       if (copy_from_kernel_nofault(code, (void *)ip, MCOUNT_INSN_SIZE))
                return -EFAULT;
 
        if (old_addr != __raw_readl((unsigned long *)code))
index a330254..9c3d32b 100644 (file)
@@ -118,7 +118,7 @@ int is_valid_bugaddr(unsigned long addr)
 
        if (addr < PAGE_OFFSET)
                return 0;
-       if (probe_kernel_address((insn_size_t *)addr, opcode))
+       if (get_kernel_nofault(opcode, (insn_size_t *)addr))
                return 0;
        if (opcode == TRAPA_BUG_OPCODE)
                return 1;
index e929c09..8ccd568 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/kernel.h>
 #include <os.h>
 
-bool probe_kernel_read_allowed(const void *src, size_t size)
+bool copy_from_kernel_nofault_allowed(const void *src, size_t size)
 {
        void *psrc = (void *)rounddown((unsigned long)src, PAGE_SIZE);
 
index 6a0cc52..883da0a 100644 (file)
@@ -67,7 +67,7 @@ config X86
        select ARCH_HAS_FILTER_PGPROT
        select ARCH_HAS_FORTIFY_SOURCE
        select ARCH_HAS_GCOV_PROFILE_ALL
-       select ARCH_HAS_KCOV                    if X86_64
+       select ARCH_HAS_KCOV                    if X86_64 && STACK_VALIDATION
        select ARCH_HAS_MEM_ENCRYPT
        select ARCH_HAS_MEMBARRIER_SYNC_CORE
        select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
index 7619742..5a828fd 100644 (file)
@@ -90,8 +90,8 @@ endif
 
 vmlinux-objs-$(CONFIG_ACPI) += $(obj)/acpi.o
 
-vmlinux-objs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
 vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o
+efi-obj-$(CONFIG_EFI_STUB) = $(objtree)/drivers/firmware/efi/libstub/lib.a
 
 # The compressed kernel is built with -fPIC/-fPIE so that a boot loader
 # can place it anywhere in memory and it will still run. However, since
@@ -115,7 +115,7 @@ endef
 quiet_cmd_check-and-link-vmlinux = LD      $@
       cmd_check-and-link-vmlinux = $(cmd_check_data_rel); $(cmd_ld)
 
-$(obj)/vmlinux: $(vmlinux-objs-y) FORCE
+$(obj)/vmlinux: $(vmlinux-objs-y) $(efi-obj-y) FORCE
        $(call if_changed,check-and-link-vmlinux)
 
 OBJCOPYFLAGS_vmlinux.bin :=  -R .comment -S
index e821a7d..97d37f0 100644 (file)
@@ -213,7 +213,6 @@ SYM_FUNC_START(startup_32)
         * We place all of the values on our mini stack so lret can
         * used to perform that far jump.
         */
-       pushl   $__KERNEL_CS
        leal    startup_64(%ebp), %eax
 #ifdef CONFIG_EFI_MIXED
        movl    efi32_boot_args(%ebp), %edi
@@ -224,11 +223,20 @@ SYM_FUNC_START(startup_32)
        movl    efi32_boot_args+8(%ebp), %edx   // saved bootparams pointer
        cmpl    $0, %edx
        jnz     1f
+       /*
+        * efi_pe_entry uses MS calling convention, which requires 32 bytes of
+        * shadow space on the stack even if all arguments are passed in
+        * registers. We also need an additional 8 bytes for the space that
+        * would be occupied by the return address, and this also results in
+        * the correct stack alignment for entry.
+        */
+       subl    $40, %esp
        leal    efi_pe_entry(%ebp), %eax
        movl    %edi, %ecx                      // MS calling convention
        movl    %esi, %edx
 1:
 #endif
+       pushl   $__KERNEL_CS
        pushl   %eax
 
        /* Enter paged protected Mode, activating Long Mode */
@@ -784,6 +792,7 @@ SYM_DATA_LOCAL(boot_heap,   .fill BOOT_HEAP_SIZE, 1, 0)
 
 SYM_DATA_START_LOCAL(boot_stack)
        .fill BOOT_STACK_SIZE, 1, 0
+       .balign 16
 SYM_DATA_END_LABEL(boot_stack, SYM_L_LOCAL, boot_stack_end)
 
 /*
index b7a5790..08bf95d 100644 (file)
@@ -7,12 +7,20 @@ KASAN_SANITIZE := n
 UBSAN_SANITIZE := n
 KCOV_INSTRUMENT := n
 
-CFLAGS_REMOVE_common.o = $(CC_FLAGS_FTRACE) -fstack-protector -fstack-protector-strong
-CFLAGS_REMOVE_syscall_32.o = $(CC_FLAGS_FTRACE) -fstack-protector -fstack-protector-strong
-CFLAGS_REMOVE_syscall_64.o = $(CC_FLAGS_FTRACE) -fstack-protector -fstack-protector-strong
+CFLAGS_REMOVE_common.o         = $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_syscall_64.o     = $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_syscall_32.o     = $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_syscall_x32.o    = $(CC_FLAGS_FTRACE)
+
+CFLAGS_common.o                        += -fno-stack-protector
+CFLAGS_syscall_64.o            += -fno-stack-protector
+CFLAGS_syscall_32.o            += -fno-stack-protector
+CFLAGS_syscall_x32.o           += -fno-stack-protector
 
 CFLAGS_syscall_64.o            += $(call cc-option,-Wno-override-init,)
 CFLAGS_syscall_32.o            += $(call cc-option,-Wno-override-init,)
+CFLAGS_syscall_x32.o           += $(call cc-option,-Wno-override-init,)
+
 obj-y                          := entry_$(BITS).o thunk_$(BITS).o syscall_$(BITS).o
 obj-y                          += common.o
 
index bd3f141..f092884 100644 (file)
 #define CREATE_TRACE_POINTS
 #include <trace/events/syscalls.h>
 
+/* Check that the stack and regs on entry from user mode are sane. */
+static noinstr void check_user_regs(struct pt_regs *regs)
+{
+       if (IS_ENABLED(CONFIG_DEBUG_ENTRY)) {
+               /*
+                * Make sure that the entry code gave us a sensible EFLAGS
+                * register.  Native because we want to check the actual CPU
+                * state, not the interrupt state as imagined by Xen.
+                */
+               unsigned long flags = native_save_fl();
+               WARN_ON_ONCE(flags & (X86_EFLAGS_AC | X86_EFLAGS_DF |
+                                     X86_EFLAGS_NT));
+
+               /* We think we came from user mode. Make sure pt_regs agrees. */
+               WARN_ON_ONCE(!user_mode(regs));
+
+               /*
+                * All entries from user mode (except #DF) should be on the
+                * normal thread stack and should have user pt_regs in the
+                * correct location.
+                */
+               WARN_ON_ONCE(!on_thread_stack());
+               WARN_ON_ONCE(regs != task_pt_regs(current));
+       }
+}
+
 #ifdef CONFIG_CONTEXT_TRACKING
 /**
  * enter_from_user_mode - Establish state when coming from user mode
@@ -127,9 +153,6 @@ static long syscall_trace_enter(struct pt_regs *regs)
        unsigned long ret = 0;
        u32 work;
 
-       if (IS_ENABLED(CONFIG_DEBUG_ENTRY))
-               BUG_ON(regs != task_pt_regs(current));
-
        work = READ_ONCE(ti->flags);
 
        if (work & (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_EMU)) {
@@ -271,7 +294,7 @@ static void __prepare_exit_to_usermode(struct pt_regs *regs)
 #endif
 }
 
-__visible noinstr void prepare_exit_to_usermode(struct pt_regs *regs)
+static noinstr void prepare_exit_to_usermode(struct pt_regs *regs)
 {
        instrumentation_begin();
        __prepare_exit_to_usermode(regs);
@@ -346,6 +369,8 @@ __visible noinstr void do_syscall_64(unsigned long nr, struct pt_regs *regs)
 {
        struct thread_info *ti;
 
+       check_user_regs(regs);
+
        enter_from_user_mode();
        instrumentation_begin();
 
@@ -409,6 +434,8 @@ static void do_syscall_32_irqs_on(struct pt_regs *regs)
 /* Handles int $0x80 */
 __visible noinstr void do_int80_syscall_32(struct pt_regs *regs)
 {
+       check_user_regs(regs);
+
        enter_from_user_mode();
        instrumentation_begin();
 
@@ -460,6 +487,8 @@ __visible noinstr long do_fast_syscall_32(struct pt_regs *regs)
                                        vdso_image_32.sym_int80_landing_pad;
        bool success;
 
+       check_user_regs(regs);
+
        /*
         * SYSENTER loses EIP, and even SYSCALL32 needs us to skip forward
         * so that 'regs->ip -= 2' lands back on an int $0x80 instruction.
@@ -510,6 +539,18 @@ __visible noinstr long do_fast_syscall_32(struct pt_regs *regs)
                (regs->flags & (X86_EFLAGS_RF | X86_EFLAGS_TF | X86_EFLAGS_VM)) == 0;
 #endif
 }
+
+/* Returns 0 to return using IRET or 1 to return using SYSEXIT/SYSRETL. */
+__visible noinstr long do_SYSENTER_32(struct pt_regs *regs)
+{
+       /* SYSENTER loses RSP, but the vDSO saved it in RBP. */
+       regs->sp = regs->bp;
+
+       /* SYSENTER clobbers EFLAGS.IF.  Assume it was set in usermode. */
+       regs->flags |= X86_EFLAGS_IF;
+
+       return do_fast_syscall_32(regs);
+}
 #endif
 
 SYSCALL_DEFINE0(ni_syscall)
@@ -553,6 +594,7 @@ SYSCALL_DEFINE0(ni_syscall)
 bool noinstr idtentry_enter_cond_rcu(struct pt_regs *regs)
 {
        if (user_mode(regs)) {
+               check_user_regs(regs);
                enter_from_user_mode();
                return false;
        }
@@ -686,6 +728,7 @@ void noinstr idtentry_exit_cond_rcu(struct pt_regs *regs, bool rcu_exit)
  */
 void noinstr idtentry_enter_user(struct pt_regs *regs)
 {
+       check_user_regs(regs);
        enter_from_user_mode();
 }
 
index 024d7d2..2d0bd5d 100644 (file)
@@ -933,9 +933,8 @@ SYM_FUNC_START(entry_SYSENTER_32)
 
 .Lsysenter_past_esp:
        pushl   $__USER_DS              /* pt_regs->ss */
-       pushl   %ebp                    /* pt_regs->sp (stashed in bp) */
+       pushl   $0                      /* pt_regs->sp (placeholder) */
        pushfl                          /* pt_regs->flags (except IF = 0) */
-       orl     $X86_EFLAGS_IF, (%esp)  /* Fix IF */
        pushl   $__USER_CS              /* pt_regs->cs */
        pushl   $0                      /* pt_regs->ip = 0 (placeholder) */
        pushl   %eax                    /* pt_regs->orig_ax */
@@ -965,7 +964,7 @@ SYM_FUNC_START(entry_SYSENTER_32)
 .Lsysenter_flags_fixed:
 
        movl    %esp, %eax
-       call    do_fast_syscall_32
+       call    do_SYSENTER_32
        /* XEN PV guests always use IRET path */
        ALTERNATIVE "testl %eax, %eax; jz .Lsyscall_32_done", \
                    "jmp .Lsyscall_32_done", X86_FEATURE_XENPV
index 0f974ae..541fdaf 100644 (file)
@@ -57,29 +57,30 @@ SYM_CODE_START(entry_SYSENTER_compat)
 
        movq    PER_CPU_VAR(cpu_current_top_of_stack), %rsp
 
-       /*
-        * User tracing code (ptrace or signal handlers) might assume that
-        * the saved RAX contains a 32-bit number when we're invoking a 32-bit
-        * syscall.  Just in case the high bits are nonzero, zero-extend
-        * the syscall number.  (This could almost certainly be deleted
-        * with no ill effects.)
-        */
-       movl    %eax, %eax
-
        /* Construct struct pt_regs on stack */
        pushq   $__USER32_DS            /* pt_regs->ss */
-       pushq   %rbp                    /* pt_regs->sp (stashed in bp) */
+       pushq   $0                      /* pt_regs->sp = 0 (placeholder) */
 
        /*
         * Push flags.  This is nasty.  First, interrupts are currently
-        * off, but we need pt_regs->flags to have IF set.  Second, even
-        * if TF was set when SYSENTER started, it's clear by now.  We fix
-        * that later using TIF_SINGLESTEP.
+        * off, but we need pt_regs->flags to have IF set.  Second, if TS
+        * was set in usermode, it's still set, and we're singlestepping
+        * through this code.  do_SYSENTER_32() will fix up IF.
         */
        pushfq                          /* pt_regs->flags (except IF = 0) */
-       orl     $X86_EFLAGS_IF, (%rsp)  /* Fix saved flags */
        pushq   $__USER32_CS            /* pt_regs->cs */
        pushq   $0                      /* pt_regs->ip = 0 (placeholder) */
+SYM_INNER_LABEL(entry_SYSENTER_compat_after_hwframe, SYM_L_GLOBAL)
+
+       /*
+        * User tracing code (ptrace or signal handlers) might assume that
+        * the saved RAX contains a 32-bit number when we're invoking a 32-bit
+        * syscall.  Just in case the high bits are nonzero, zero-extend
+        * the syscall number.  (This could almost certainly be deleted
+        * with no ill effects.)
+        */
+       movl    %eax, %eax
+
        pushq   %rax                    /* pt_regs->orig_ax */
        pushq   %rdi                    /* pt_regs->di */
        pushq   %rsi                    /* pt_regs->si */
@@ -135,7 +136,7 @@ SYM_CODE_START(entry_SYSENTER_compat)
 .Lsysenter_flags_fixed:
 
        movq    %rsp, %rdi
-       call    do_fast_syscall_32
+       call    do_SYSENTER_32
        /* XEN PV guests always use IRET path */
        ALTERNATIVE "testl %eax, %eax; jz swapgs_restore_regs_and_return_to_usermode", \
                    "jmp swapgs_restore_regs_and_return_to_usermode", X86_FEATURE_XENPV
index 12c42eb..9933c0e 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-y                                  += core.o probe.o
-obj-$(PERF_EVENTS_INTEL_RAPL)          += rapl.o
+obj-$(CONFIG_PERF_EVENTS_INTEL_RAPL)   += rapl.o
 obj-y                                  += amd/
 obj-$(CONFIG_X86_LOCAL_APIC)            += msr.o
 obj-$(CONFIG_CPU_SUP_INTEL)            += intel/
index a54c6a4..6035df1 100644 (file)
@@ -375,7 +375,10 @@ void __init hyperv_init(void)
        guest_id = generate_guest_id(0, LINUX_VERSION_CODE, 0);
        wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id);
 
-       hv_hypercall_pg = vmalloc_exec(PAGE_SIZE);
+       hv_hypercall_pg = __vmalloc_node_range(PAGE_SIZE, 1, VMALLOC_START,
+                       VMALLOC_END, GFP_KERNEL, PAGE_KERNEL_ROX,
+                       VM_FLUSH_RESET_PERMS, NUMA_NO_NODE,
+                       __builtin_return_address(0));
        if (hv_hypercall_pg == NULL) {
                wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
                goto remove_cpuhp_state;
index 35460fe..0367efd 100644 (file)
@@ -201,12 +201,8 @@ arch_test_and_change_bit(long nr, volatile unsigned long *addr)
        return GEN_BINARY_RMWcc(LOCK_PREFIX __ASM_SIZE(btc), *addr, c, "Ir", nr);
 }
 
-static __no_kcsan_or_inline bool constant_test_bit(long nr, const volatile unsigned long *addr)
+static __always_inline bool constant_test_bit(long nr, const volatile unsigned long *addr)
 {
-       /*
-        * Because this is a plain access, we need to disable KCSAN here to
-        * avoid double instrumentation via instrumented bitops.
-        */
        return ((1UL << (nr & (BITS_PER_LONG-1))) &
                (addr[nr >> _BITOPS_LONG_SHIFT])) != 0;
 }
index fb34ff6..0281895 100644 (file)
@@ -75,6 +75,12 @@ do {                                                         \
        unreachable();                                          \
 } while (0)
 
+/*
+ * This instrumentation_begin() is strictly speaking incorrect; but it
+ * suppresses the complaints from WARN()s in noinstr code. If such a WARN()
+ * were to trigger, we'd rather wreck the machine in an attempt to get the
+ * message out than not know about it.
+ */
 #define __WARN_FLAGS(flags)                                    \
 do {                                                           \
        instrumentation_begin();                                \
index dd17c2d..da78ccb 100644 (file)
@@ -58,4 +58,9 @@ static inline bool handle_guest_split_lock(unsigned long ip)
        return false;
 }
 #endif
+#ifdef CONFIG_IA32_FEAT_CTL
+void init_ia32_feat_ctl(struct cpuinfo_x86 *c);
+#else
+static inline void init_ia32_feat_ctl(struct cpuinfo_x86 *c) {}
+#endif
 #endif /* _ASM_X86_CPU_H */
index 6722ffc..3afa990 100644 (file)
@@ -11,5 +11,23 @@ extern cpumask_var_t cpu_sibling_setup_mask;
 
 extern void setup_cpu_local_masks(void);
 
+/*
+ * NMI and MCE exceptions need cpu_is_offline() _really_ early,
+ * provide an arch_ special for them to avoid instrumentation.
+ */
+#if NR_CPUS > 1
+static __always_inline bool arch_cpu_online(int cpu)
+{
+       return arch_test_bit(cpu, cpumask_bits(cpu_online_mask));
+}
+#else
+static __always_inline bool arch_cpu_online(int cpu)
+{
+       return cpu == 0;
+}
+#endif
+
+#define arch_cpu_is_offline(cpu)       unlikely(!arch_cpu_online(cpu))
+
 #endif /* __ASSEMBLY__ */
 #endif /* _ASM_X86_CPUMASK_H */
index 42159f4..845e748 100644 (file)
@@ -623,6 +623,11 @@ static inline void switch_fpu_finish(struct fpu *new_fpu)
  * MXCSR and XCR definitions:
  */
 
+static inline void ldmxcsr(u32 mxcsr)
+{
+       asm volatile("ldmxcsr %0" :: "m" (mxcsr));
+}
+
 extern unsigned int mxcsr_feature_mask;
 
 #define XCR_XFEATURE_ENABLED_MASK      0x00000000
index cf51c50..80d3b30 100644 (file)
@@ -353,10 +353,6 @@ static __always_inline void __##func(struct pt_regs *regs)
 
 #else  /* CONFIG_X86_64 */
 
-/* Maps to a regular IDTENTRY on 32bit for now */
-# define DECLARE_IDTENTRY_IST          DECLARE_IDTENTRY
-# define DEFINE_IDTENTRY_IST           DEFINE_IDTENTRY
-
 /**
  * DECLARE_IDTENTRY_DF - Declare functions for double fault 32bit variant
  * @vector:    Vector number (ignored for C)
@@ -387,28 +383,18 @@ __visible noinstr void func(struct pt_regs *regs,                 \
 #endif /* !CONFIG_X86_64 */
 
 /* C-Code mapping */
+#define DECLARE_IDTENTRY_NMI           DECLARE_IDTENTRY_RAW
+#define DEFINE_IDTENTRY_NMI            DEFINE_IDTENTRY_RAW
+
+#ifdef CONFIG_X86_64
 #define DECLARE_IDTENTRY_MCE           DECLARE_IDTENTRY_IST
 #define DEFINE_IDTENTRY_MCE            DEFINE_IDTENTRY_IST
 #define DEFINE_IDTENTRY_MCE_USER       DEFINE_IDTENTRY_NOIST
 
-#define DECLARE_IDTENTRY_NMI           DECLARE_IDTENTRY_RAW
-#define DEFINE_IDTENTRY_NMI            DEFINE_IDTENTRY_RAW
-
 #define DECLARE_IDTENTRY_DEBUG         DECLARE_IDTENTRY_IST
 #define DEFINE_IDTENTRY_DEBUG          DEFINE_IDTENTRY_IST
 #define DEFINE_IDTENTRY_DEBUG_USER     DEFINE_IDTENTRY_NOIST
-
-/**
- * DECLARE_IDTENTRY_XEN - Declare functions for XEN redirect IDT entry points
- * @vector:    Vector number (ignored for C)
- * @func:      Function name of the entry point
- *
- * Used for xennmi and xendebug redirections. No DEFINE as this is all ASM
- * indirection magic.
- */
-#define DECLARE_IDTENTRY_XEN(vector, func)                             \
-       asmlinkage void xen_asm_exc_xen##func(void);                    \
-       asmlinkage void asm_exc_xen##func(void)
+#endif
 
 #else /* !__ASSEMBLY__ */
 
@@ -455,9 +441,6 @@ __visible noinstr void func(struct pt_regs *regs,                   \
 # define DECLARE_IDTENTRY_MCE(vector, func)                            \
        DECLARE_IDTENTRY(vector, func)
 
-# define DECLARE_IDTENTRY_DEBUG(vector, func)                          \
-       DECLARE_IDTENTRY(vector, func)
-
 /* No ASM emitted for DF as this goes through a C shim */
 # define DECLARE_IDTENTRY_DF(vector, func)
 
@@ -469,10 +452,6 @@ __visible noinstr void func(struct pt_regs *regs,                  \
 /* No ASM code emitted for NMI */
 #define DECLARE_IDTENTRY_NMI(vector, func)
 
-/* XEN NMI and DB wrapper */
-#define DECLARE_IDTENTRY_XEN(vector, func)                             \
-       idtentry vector asm_exc_xen##func exc_##func has_error_code=0
-
 /*
  * ASM code to emit the common vector entry stubs where each stub is
  * packed into 8 bytes.
@@ -490,16 +469,15 @@ __visible noinstr void func(struct pt_regs *regs,                 \
        .align 8
 SYM_CODE_START(irq_entries_start)
     vector=FIRST_EXTERNAL_VECTOR
-    pos = .
     .rept (FIRST_SYSTEM_VECTOR - FIRST_EXTERNAL_VECTOR)
        UNWIND_HINT_IRET_REGS
+0 :
        .byte   0x6a, vector
        jmp     asm_common_interrupt
        nop
        /* Ensure that the above is 8 bytes max */
-       . = pos + 8
-    pos=pos+8
-    vector=vector+1
+       . = 0b + 8
+       vector = vector+1
     .endr
 SYM_CODE_END(irq_entries_start)
 
@@ -507,16 +485,15 @@ SYM_CODE_END(irq_entries_start)
        .align 8
 SYM_CODE_START(spurious_entries_start)
     vector=FIRST_SYSTEM_VECTOR
-    pos = .
     .rept (NR_VECTORS - FIRST_SYSTEM_VECTOR)
        UNWIND_HINT_IRET_REGS
+0 :
        .byte   0x6a, vector
        jmp     asm_spurious_interrupt
        nop
        /* Ensure that the above is 8 bytes max */
-       . = pos + 8
-    pos=pos+8
-    vector=vector+1
+       . = 0b + 8
+       vector = vector+1
     .endr
 SYM_CODE_END(spurious_entries_start)
 #endif
@@ -565,16 +542,28 @@ DECLARE_IDTENTRY_RAW(X86_TRAP_BP,         exc_int3);
 DECLARE_IDTENTRY_RAW_ERRORCODE(X86_TRAP_PF,    exc_page_fault);
 
 #ifdef CONFIG_X86_MCE
+#ifdef CONFIG_X86_64
 DECLARE_IDTENTRY_MCE(X86_TRAP_MC,      exc_machine_check);
+#else
+DECLARE_IDTENTRY_RAW(X86_TRAP_MC,      exc_machine_check);
+#endif
 #endif
 
 /* NMI */
 DECLARE_IDTENTRY_NMI(X86_TRAP_NMI,     exc_nmi);
-DECLARE_IDTENTRY_XEN(X86_TRAP_NMI,     nmi);
+#if defined(CONFIG_XEN_PV) && defined(CONFIG_X86_64)
+DECLARE_IDTENTRY_RAW(X86_TRAP_NMI,     xenpv_exc_nmi);
+#endif
 
 /* #DB */
+#ifdef CONFIG_X86_64
 DECLARE_IDTENTRY_DEBUG(X86_TRAP_DB,    exc_debug);
-DECLARE_IDTENTRY_XEN(X86_TRAP_DB,      debug);
+#else
+DECLARE_IDTENTRY_RAW(X86_TRAP_DB,      exc_debug);
+#endif
+#if defined(CONFIG_XEN_PV) && defined(CONFIG_X86_64)
+DECLARE_IDTENTRY_RAW(X86_TRAP_DB,      xenpv_exc_debug);
+#endif
 
 /* #DF */
 DECLARE_IDTENTRY_DF(X86_TRAP_DF,       exc_double_fault);
@@ -635,8 +624,8 @@ DECLARE_IDTENTRY_SYSVEC(POSTED_INTR_NESTED_VECTOR,  sysvec_kvm_posted_intr_nested
 
 #if IS_ENABLED(CONFIG_HYPERV)
 DECLARE_IDTENTRY_SYSVEC(HYPERVISOR_CALLBACK_VECTOR,    sysvec_hyperv_callback);
-DECLARE_IDTENTRY_SYSVEC(HYPERVISOR_REENLIGHTENMENT_VECTOR,     sysvec_hyperv_reenlightenment);
-DECLARE_IDTENTRY_SYSVEC(HYPERVISOR_STIMER0_VECTOR,     sysvec_hyperv_stimer0);
+DECLARE_IDTENTRY_SYSVEC(HYPERV_REENLIGHTENMENT_VECTOR, sysvec_hyperv_reenlightenment);
+DECLARE_IDTENTRY_SYSVEC(HYPERV_STIMER0_VECTOR, sysvec_hyperv_stimer0);
 #endif
 
 #if IS_ENABLED(CONFIG_ACRN_GUEST)
index ac1a99f..7f080f5 100644 (file)
@@ -19,12 +19,28 @@ struct task_struct;
 void io_bitmap_share(struct task_struct *tsk);
 void io_bitmap_exit(struct task_struct *tsk);
 
+static inline void native_tss_invalidate_io_bitmap(void)
+{
+       /*
+        * Invalidate the I/O bitmap by moving io_bitmap_base outside the
+        * TSS limit so any subsequent I/O access from user space will
+        * trigger a #GP.
+        *
+        * This is correct even when VMEXIT rewrites the TSS limit
+        * to 0x67 as the only requirement is that the base points
+        * outside the limit.
+        */
+       this_cpu_write(cpu_tss_rw.x86_tss.io_bitmap_base,
+                      IO_BITMAP_OFFSET_INVALID);
+}
+
 void native_tss_update_io_bitmap(void);
 
 #ifdef CONFIG_PARAVIRT_XXL
 #include <asm/paravirt.h>
 #else
 #define tss_update_io_bitmap native_tss_update_io_bitmap
+#define tss_invalidate_io_bitmap native_tss_invalidate_io_bitmap
 #endif
 
 #else
index 5270ff3..a1911fe 100644 (file)
@@ -39,6 +39,7 @@
 #define BT_MBI_UNIT_PMC                0x04
 #define BT_MBI_UNIT_GFX                0x06
 #define BT_MBI_UNIT_SMI                0x0C
+#define BT_MBI_UNIT_CCK                0x14
 #define BT_MBI_UNIT_USB                0x43
 #define BT_MBI_UNIT_SATA       0xA3
 #define BT_MBI_UNIT_PCIE       0xA6
index f8998e9..be5363b 100644 (file)
@@ -943,7 +943,7 @@ struct kvm_arch {
        atomic_t vapics_in_nmi_mode;
        struct mutex apic_map_lock;
        struct kvm_apic_map *apic_map;
-       bool apic_map_dirty;
+       atomic_t apic_map_dirty;
 
        bool apic_access_page_done;
        unsigned long apicv_inhibit_reasons;
@@ -1220,7 +1220,7 @@ struct kvm_x86_ops {
        void (*enable_log_dirty_pt_masked)(struct kvm *kvm,
                                           struct kvm_memory_slot *slot,
                                           gfn_t offset, unsigned long mask);
-       int (*write_log_dirty)(struct kvm_vcpu *vcpu);
+       int (*write_log_dirty)(struct kvm_vcpu *vcpu, gpa_t l2_gpa);
 
        /* pmu operations of sub-arch */
        const struct kvm_pmu_ops *pmu_ops;
index 73d997a..e039a93 100644 (file)
@@ -25,8 +25,6 @@
 #define TPAUSE_C01_STATE               1
 #define TPAUSE_C02_STATE               0
 
-u32 get_umwait_control_msr(void);
-
 static inline void __monitor(const void *eax, unsigned long ecx,
                             unsigned long edx)
 {
index 5ca5d29..3d2afec 100644 (file)
@@ -302,6 +302,11 @@ static inline void write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
 }
 
 #ifdef CONFIG_X86_IOPL_IOPERM
+static inline void tss_invalidate_io_bitmap(void)
+{
+       PVOP_VCALL0(cpu.invalidate_io_bitmap);
+}
+
 static inline void tss_update_io_bitmap(void)
 {
        PVOP_VCALL0(cpu.update_io_bitmap);
index 732f62e..8dfcb25 100644 (file)
@@ -141,6 +141,7 @@ struct pv_cpu_ops {
        void (*load_sp0)(unsigned long sp0);
 
 #ifdef CONFIG_X86_IOPL_IOPERM
+       void (*invalidate_io_bitmap)(void);
        void (*update_io_bitmap)(void);
 #endif
 
index 2da1f95..816b31c 100644 (file)
@@ -194,6 +194,7 @@ enum page_cache_mode {
 #define _PAGE_TABLE_NOENC       (__PP|__RW|_USR|___A|   0|___D|   0|   0)
 #define _PAGE_TABLE             (__PP|__RW|_USR|___A|   0|___D|   0|   0| _ENC)
 #define __PAGE_KERNEL_RO        (__PP|   0|   0|___A|__NX|___D|   0|___G)
+#define __PAGE_KERNEL_ROX       (__PP|   0|   0|___A|   0|___D|   0|___G)
 #define __PAGE_KERNEL_NOCACHE   (__PP|__RW|   0|___A|__NX|___D|   0|___G| __NC)
 #define __PAGE_KERNEL_VVAR      (__PP|   0|_USR|___A|__NX|___D|   0|___G)
 #define __PAGE_KERNEL_LARGE     (__PP|__RW|   0|___A|__NX|___D|_PSE|___G)
@@ -219,6 +220,7 @@ enum page_cache_mode {
 #define PAGE_KERNEL_RO         __pgprot_mask(__PAGE_KERNEL_RO         | _ENC)
 #define PAGE_KERNEL_EXEC       __pgprot_mask(__PAGE_KERNEL_EXEC       | _ENC)
 #define PAGE_KERNEL_EXEC_NOENC __pgprot_mask(__PAGE_KERNEL_EXEC       |    0)
+#define PAGE_KERNEL_ROX                __pgprot_mask(__PAGE_KERNEL_ROX        | _ENC)
 #define PAGE_KERNEL_NOCACHE    __pgprot_mask(__PAGE_KERNEL_NOCACHE    | _ENC)
 #define PAGE_KERNEL_LARGE      __pgprot_mask(__PAGE_KERNEL_LARGE      | _ENC)
 #define PAGE_KERNEL_LARGE_EXEC __pgprot_mask(__PAGE_KERNEL_LARGE_EXEC | _ENC)
index 42cd333..03b7c4c 100644 (file)
@@ -370,7 +370,7 @@ struct x86_hw_tss {
 #define IO_BITMAP_OFFSET_INVALID       (__KERNEL_TSS_LIMIT + 1)
 
 struct entry_stack {
-       unsigned long           words[64];
+       char    stack[PAGE_SIZE];
 };
 
 struct entry_stack_page {
index ebedeab..255b2dd 100644 (file)
@@ -278,7 +278,7 @@ static inline unsigned long *regs_get_kernel_stack_nth_addr(struct pt_regs *regs
 }
 
 /* To avoid include hell, we can't include uaccess.h */
-extern long probe_kernel_read(void *dst, const void *src, size_t size);
+extern long copy_from_kernel_nofault(void *dst, const void *src, size_t size);
 
 /**
  * regs_get_kernel_stack_nth() - get Nth entry of the stack
@@ -298,7 +298,7 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
 
        addr = regs_get_kernel_stack_nth_addr(regs, n);
        if (addr) {
-               ret = probe_kernel_read(&val, addr, sizeof(val));
+               ret = copy_from_kernel_nofault(&val, addr, sizeof(val));
                if (!ret)
                        return val;
        }
index 17c5a03..0780f97 100644 (file)
@@ -408,14 +408,15 @@ struct kvm_vmx_nested_state_data {
 };
 
 struct kvm_vmx_nested_state_hdr {
-       __u32 flags;
        __u64 vmxon_pa;
        __u64 vmcs12_pa;
-       __u64 preemption_timer_deadline;
 
        struct {
                __u16 flags;
        } smm;
+
+       __u32 flags;
+       __u64 preemption_timer_deadline;
 };
 
 struct kvm_svm_nested_state_data {
index ce61e3e..81ffcfb 100644 (file)
@@ -2316,12 +2316,12 @@ static int mp_irqdomain_create(int ioapic)
        ip->irqdomain = irq_domain_create_linear(fn, hwirqs, cfg->ops,
                                                 (void *)(long)ioapic);
 
-       /* Release fw handle if it was allocated above */
-       if (!cfg->dev)
-               irq_domain_free_fwnode(fn);
-
-       if (!ip->irqdomain)
+       if (!ip->irqdomain) {
+               /* Release fw handle if it was allocated above */
+               if (!cfg->dev)
+                       irq_domain_free_fwnode(fn);
                return -ENOMEM;
+       }
 
        ip->irqdomain->parent = parent;
 
index 5cbaca5..c2b2911 100644 (file)
@@ -263,12 +263,13 @@ void __init arch_init_msi_domain(struct irq_domain *parent)
                msi_default_domain =
                        pci_msi_create_irq_domain(fn, &pci_msi_domain_info,
                                                  parent);
-               irq_domain_free_fwnode(fn);
        }
-       if (!msi_default_domain)
+       if (!msi_default_domain) {
+               irq_domain_free_fwnode(fn);
                pr_warn("failed to initialize irqdomain for MSI/MSI-x.\n");
-       else
+       } else {
                msi_default_domain->flags |= IRQ_DOMAIN_MSI_NOMASK_QUIRK;
+       }
 }
 
 #ifdef CONFIG_IRQ_REMAP
@@ -301,7 +302,8 @@ struct irq_domain *arch_create_remap_msi_irq_domain(struct irq_domain *parent,
        if (!fn)
                return NULL;
        d = pci_msi_create_irq_domain(fn, &pci_msi_ir_domain_info, parent);
-       irq_domain_free_fwnode(fn);
+       if (!d)
+               irq_domain_free_fwnode(fn);
        return d;
 }
 #endif
@@ -364,7 +366,8 @@ static struct irq_domain *dmar_get_irq_domain(void)
        if (fn) {
                dmar_domain = msi_create_irq_domain(fn, &dmar_msi_domain_info,
                                                    x86_vector_domain);
-               irq_domain_free_fwnode(fn);
+               if (!dmar_domain)
+                       irq_domain_free_fwnode(fn);
        }
 out:
        mutex_unlock(&dmar_lock);
@@ -489,7 +492,10 @@ struct irq_domain *hpet_create_irq_domain(int hpet_id)
        }
 
        d = msi_create_irq_domain(fn, domain_info, parent);
-       irq_domain_free_fwnode(fn);
+       if (!d) {
+               irq_domain_free_fwnode(fn);
+               kfree(domain_info);
+       }
        return d;
 }
 
index c48be6e..7649da2 100644 (file)
@@ -446,12 +446,10 @@ static int x86_vector_activate(struct irq_domain *dom, struct irq_data *irqd,
        trace_vector_activate(irqd->irq, apicd->is_managed,
                              apicd->can_reserve, reserve);
 
-       /* Nothing to do for fixed assigned vectors */
-       if (!apicd->can_reserve && !apicd->is_managed)
-               return 0;
-
        raw_spin_lock_irqsave(&vector_lock, flags);
-       if (reserve || irqd_is_managed_and_shutdown(irqd))
+       if (!apicd->can_reserve && !apicd->is_managed)
+               assign_irq_vector_any_locked(irqd);
+       else if (reserve || irqd_is_managed_and_shutdown(irqd))
                vector_assign_managed_shutdown(irqd);
        else if (apicd->is_managed)
                ret = activate_managed(irqd);
@@ -709,7 +707,6 @@ int __init arch_early_irq_init(void)
        x86_vector_domain = irq_domain_create_tree(fn, &x86_vector_domain_ops,
                                                   NULL);
        BUG_ON(x86_vector_domain == NULL);
-       irq_domain_free_fwnode(fn);
        irq_set_default_host(x86_vector_domain);
 
        arch_init_msi_domain(x86_vector_domain);
@@ -775,20 +772,10 @@ void lapic_offline(void)
 static int apic_set_affinity(struct irq_data *irqd,
                             const struct cpumask *dest, bool force)
 {
-       struct apic_chip_data *apicd = apic_chip_data(irqd);
        int err;
 
-       /*
-        * Core code can call here for inactive interrupts. For inactive
-        * interrupts which use managed or reservation mode there is no
-        * point in going through the vector assignment right now as the
-        * activation will assign a vector which fits the destination
-        * cpumask. Let the core code store the destination mask and be
-        * done with it.
-        */
-       if (!irqd_is_activated(irqd) &&
-           (apicd->is_managed || apicd->can_reserve))
-               return IRQ_SET_MASK_OK;
+       if (WARN_ON_ONCE(!irqd_is_activated(irqd)))
+               return -EIO;
 
        raw_spin_lock(&vector_lock);
        cpumask_and(vector_searchmask, dest, cpu_online_mask);
index 4267925..c5cf336 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/sched.h>
 #include <linux/sched/clock.h>
 
+#include <asm/cpu.h>
 #include <asm/cpufeature.h>
 #include <asm/e820/api.h>
 #include <asm/mtrr.h>
index 043d93c..95c090a 100644 (file)
@@ -347,6 +347,9 @@ out:
        cr4_clear_bits(X86_CR4_UMIP);
 }
 
+/* These bits should not change their value after CPU init is finished. */
+static const unsigned long cr4_pinned_mask =
+       X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP | X86_CR4_FSGSBASE;
 static DEFINE_STATIC_KEY_FALSE_RO(cr_pinning);
 static unsigned long cr4_pinned_bits __ro_after_init;
 
@@ -371,20 +374,20 @@ EXPORT_SYMBOL(native_write_cr0);
 
 void native_write_cr4(unsigned long val)
 {
-       unsigned long bits_missing = 0;
+       unsigned long bits_changed = 0;
 
 set_register:
        asm volatile("mov %0,%%cr4": "+r" (val), "+m" (cr4_pinned_bits));
 
        if (static_branch_likely(&cr_pinning)) {
-               if (unlikely((val & cr4_pinned_bits) != cr4_pinned_bits)) {
-                       bits_missing = ~val & cr4_pinned_bits;
-                       val |= bits_missing;
+               if (unlikely((val & cr4_pinned_mask) != cr4_pinned_bits)) {
+                       bits_changed = (val & cr4_pinned_mask) ^ cr4_pinned_bits;
+                       val = (val & ~cr4_pinned_mask) | cr4_pinned_bits;
                        goto set_register;
                }
-               /* Warn after we've set the missing bits. */
-               WARN_ONCE(bits_missing, "CR4 bits went missing: %lx!?\n",
-                         bits_missing);
+               /* Warn after we've corrected the changed bits. */
+               WARN_ONCE(bits_changed, "pinned CR4 bits changed: 0x%lx!?\n",
+                         bits_changed);
        }
 }
 #if IS_MODULE(CONFIG_LKDTM)
@@ -419,7 +422,7 @@ void cr4_init(void)
        if (boot_cpu_has(X86_FEATURE_PCID))
                cr4 |= X86_CR4_PCIDE;
        if (static_branch_likely(&cr_pinning))
-               cr4 |= cr4_pinned_bits;
+               cr4 = (cr4 & ~cr4_pinned_mask) | cr4_pinned_bits;
 
        __write_cr4(cr4);
 
@@ -434,10 +437,7 @@ void cr4_init(void)
  */
 static void __init setup_cr_pinning(void)
 {
-       unsigned long mask;
-
-       mask = (X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP);
-       cr4_pinned_bits = this_cpu_read(cpu_tlbstate.cr4) & mask;
+       cr4_pinned_bits = this_cpu_read(cpu_tlbstate.cr4) & cr4_pinned_mask;
        static_key_enable(&cr_pinning.key);
 }
 
index fb538fc..9d03369 100644 (file)
@@ -81,8 +81,4 @@ extern void update_srbds_msr(void);
 
 extern u64 x86_read_arch_cap_msr(void);
 
-#ifdef CONFIG_IA32_FEAT_CTL
-void init_ia32_feat_ctl(struct cpuinfo_x86 *c);
-#endif
-
 #endif /* ARCH_X86_CPU_H */
index c25a67a..0ab48f1 100644 (file)
@@ -49,6 +49,13 @@ enum split_lock_detect_state {
 static enum split_lock_detect_state sld_state __ro_after_init = sld_off;
 static u64 msr_test_ctrl_cache __ro_after_init;
 
+/*
+ * With a name like MSR_TEST_CTL it should go without saying, but don't touch
+ * MSR_TEST_CTL unless the CPU is one of the whitelisted models.  Writing it
+ * on CPUs that do not support SLD can cause fireworks, even when writing '0'.
+ */
+static bool cpu_model_supports_sld __ro_after_init;
+
 /*
  * Processors which have self-snooping capability can handle conflicting
  * memory type across CPUs by snooping its own cache. However, there exists
@@ -1071,7 +1078,8 @@ static void sld_update_msr(bool on)
 
 static void split_lock_init(void)
 {
-       split_lock_verify_msr(sld_state != sld_off);
+       if (cpu_model_supports_sld)
+               split_lock_verify_msr(sld_state != sld_off);
 }
 
 static void split_lock_warn(unsigned long ip)
@@ -1177,5 +1185,6 @@ void __init cpu_set_core_cap_bits(struct cpuinfo_x86 *c)
                return;
        }
 
+       cpu_model_supports_sld = true;
        split_lock_setup();
 }
index ce9120c..14e4b4d 100644 (file)
@@ -1083,7 +1083,7 @@ static noinstr bool mce_check_crashing_cpu(void)
 {
        unsigned int cpu = smp_processor_id();
 
-       if (cpu_is_offline(cpu) ||
+       if (arch_cpu_is_offline(cpu) ||
            (crashing_cpu != -1 && crashing_cpu != cpu)) {
                u64 mcgstatus;
 
@@ -1901,6 +1901,8 @@ void (*machine_check_vector)(struct pt_regs *) = unexpected_machine_check;
 
 static __always_inline void exc_machine_check_kernel(struct pt_regs *regs)
 {
+       WARN_ON_ONCE(user_mode(regs));
+
        /*
         * Only required when from kernel mode. See
         * mce_check_crashing_cpu() for details.
@@ -1954,7 +1956,7 @@ DEFINE_IDTENTRY_MCE_USER(exc_machine_check)
 }
 #else
 /* 32bit unified entry point */
-DEFINE_IDTENTRY_MCE(exc_machine_check)
+DEFINE_IDTENTRY_RAW(exc_machine_check)
 {
        unsigned long dr7;
 
index 12f967c..6a9df71 100644 (file)
@@ -981,10 +981,10 @@ void resctrl_cpu_detect(struct cpuinfo_x86 *c)
 
                c->x86_cache_max_rmid  = ecx;
                c->x86_cache_occ_scale = ebx;
-               if (c->x86_vendor == X86_VENDOR_INTEL)
-                       c->x86_cache_mbm_width_offset = eax & 0xff;
-               else
-                       c->x86_cache_mbm_width_offset = -1;
+               c->x86_cache_mbm_width_offset = eax & 0xff;
+
+               if (c->x86_vendor == X86_VENDOR_AMD && !c->x86_cache_mbm_width_offset)
+                       c->x86_cache_mbm_width_offset = MBM_CNTR_WIDTH_OFFSET_AMD;
        }
 }
 
index f20a47d..5ffa322 100644 (file)
@@ -37,6 +37,7 @@
 #define MBA_IS_LINEAR                  0x4
 #define MBA_MAX_MBPS                   U32_MAX
 #define MAX_MBA_BW_AMD                 0x800
+#define MBM_CNTR_WIDTH_OFFSET_AMD      20
 
 #define RMID_VAL_ERROR                 BIT_ULL(63)
 #define RMID_VAL_UNAVAIL               BIT_ULL(62)
index 23b4b61..3f844f1 100644 (file)
@@ -1117,6 +1117,7 @@ static int rdt_cdp_peer_get(struct rdt_resource *r, struct rdt_domain *d,
        _d_cdp = rdt_find_domain(_r_cdp, d->id, NULL);
        if (WARN_ON(IS_ERR_OR_NULL(_d_cdp))) {
                _r_cdp = NULL;
+               _d_cdp = NULL;
                ret = -EINVAL;
        }
 
index 300e3fd..ec8064c 100644 (file)
  */
 static u32 umwait_control_cached = UMWAIT_CTRL_VAL(100000, UMWAIT_C02_ENABLE);
 
-u32 get_umwait_control_msr(void)
-{
-       return umwait_control_cached;
-}
-EXPORT_SYMBOL_GPL(get_umwait_control_msr);
-
 /*
  * Cache the original IA32_UMWAIT_CONTROL MSR value which is configured by
  * hardware or BIOS before kernel boot.
index df1358b..05fa4ef 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/sched.h>
 #include <linux/sched/clock.h>
 
+#include <asm/cpu.h>
 #include <asm/cpufeature.h>
 
 #include "cpu.h"
index 456511b..7401cc1 100644 (file)
@@ -71,6 +71,22 @@ static void printk_stack_address(unsigned long address, int reliable,
        printk("%s %s%pB\n", log_lvl, reliable ? "" : "? ", (void *)address);
 }
 
+static int copy_code(struct pt_regs *regs, u8 *buf, unsigned long src,
+                    unsigned int nbytes)
+{
+       if (!user_mode(regs))
+               return copy_from_kernel_nofault(buf, (u8 *)src, nbytes);
+
+       /*
+        * Make sure userspace isn't trying to trick us into dumping kernel
+        * memory by pointing the userspace instruction pointer at it.
+        */
+       if (__chk_range_not_ok(src, nbytes, TASK_SIZE_MAX))
+               return -EINVAL;
+
+       return copy_from_user_nmi(buf, (void __user *)src, nbytes);
+}
+
 /*
  * There are a couple of reasons for the 2/3rd prologue, courtesy of Linus:
  *
@@ -97,17 +113,8 @@ void show_opcodes(struct pt_regs *regs, const char *loglvl)
 #define OPCODE_BUFSIZE (PROLOGUE_SIZE + 1 + EPILOGUE_SIZE)
        u8 opcodes[OPCODE_BUFSIZE];
        unsigned long prologue = regs->ip - PROLOGUE_SIZE;
-       bool bad_ip;
-
-       /*
-        * Make sure userspace isn't trying to trick us into dumping kernel
-        * memory by pointing the userspace instruction pointer at it.
-        */
-       bad_ip = user_mode(regs) &&
-               __chk_range_not_ok(prologue, OPCODE_BUFSIZE, TASK_SIZE_MAX);
 
-       if (bad_ip || probe_kernel_read(opcodes, (u8 *)prologue,
-                                       OPCODE_BUFSIZE)) {
+       if (copy_code(regs, opcodes, prologue, sizeof(opcodes))) {
                printk("%sCode: Bad RIP value.\n", loglvl);
        } else {
                printk("%sCode: %" __stringify(PROLOGUE_SIZE) "ph <%02x> %"
index 06c8189..15247b9 100644 (file)
@@ -101,6 +101,12 @@ void kernel_fpu_begin(void)
                copy_fpregs_to_fpstate(&current->thread.fpu);
        }
        __cpu_invalidate_fpregs_state();
+
+       if (boot_cpu_has(X86_FEATURE_XMM))
+               ldmxcsr(MXCSR_DEFAULT);
+
+       if (boot_cpu_has(X86_FEATURE_FPU))
+               asm volatile ("fninit");
 }
 EXPORT_SYMBOL_GPL(kernel_fpu_begin);
 
index bda2e5e..ad3a2b3 100644 (file)
@@ -1074,7 +1074,7 @@ int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int of
                copy_part(offsetof(struct fxregs_state, st_space), 128,
                          &xsave->i387.st_space, &kbuf, &offset_start, &count);
        if (header.xfeatures & XFEATURE_MASK_SSE)
-               copy_part(xstate_offsets[XFEATURE_MASK_SSE], 256,
+               copy_part(xstate_offsets[XFEATURE_SSE], 256,
                          &xsave->i387.xmm_space, &kbuf, &offset_start, &count);
        /*
         * Fill xsave->i387.sw_reserved value for ptrace frame:
index c84d28e..5150456 100644 (file)
@@ -86,7 +86,7 @@ static int ftrace_verify_code(unsigned long ip, const char *old_code)
         * sure what we read is what we expected it to be before modifying it.
         */
        /* read the text we want to modify */
-       if (probe_kernel_read(cur_code, (void *)ip, MCOUNT_INSN_SIZE)) {
+       if (copy_from_kernel_nofault(cur_code, (void *)ip, MCOUNT_INSN_SIZE)) {
                WARN_ON(1);
                return -EFAULT;
        }
@@ -355,7 +355,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
        npages = DIV_ROUND_UP(*tramp_size, PAGE_SIZE);
 
        /* Copy ftrace_caller onto the trampoline memory */
-       ret = probe_kernel_read(trampoline, (void *)start_offset, size);
+       ret = copy_from_kernel_nofault(trampoline, (void *)start_offset, size);
        if (WARN_ON(ret < 0))
                goto fail;
 
@@ -363,13 +363,13 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
 
        /* The trampoline ends with ret(q) */
        retq = (unsigned long)ftrace_stub;
-       ret = probe_kernel_read(ip, (void *)retq, RET_SIZE);
+       ret = copy_from_kernel_nofault(ip, (void *)retq, RET_SIZE);
        if (WARN_ON(ret < 0))
                goto fail;
 
        if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) {
                ip = trampoline + (ftrace_regs_caller_ret - ftrace_regs_caller);
-               ret = probe_kernel_read(ip, (void *)retq, RET_SIZE);
+               ret = copy_from_kernel_nofault(ip, (void *)retq, RET_SIZE);
                if (WARN_ON(ret < 0))
                        goto fail;
        }
@@ -506,7 +506,7 @@ static void *addr_from_call(void *ptr)
        union text_poke_insn call;
        int ret;
 
-       ret = probe_kernel_read(&call, ptr, CALL_INSN_SIZE);
+       ret = copy_from_kernel_nofault(&call, ptr, CALL_INSN_SIZE);
        if (WARN_ON_ONCE(ret < 0))
                return NULL;
 
index c44fe7d..68acd30 100644 (file)
@@ -732,11 +732,11 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
        int err;
 
        bpt->type = BP_BREAKPOINT;
-       err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
+       err = copy_from_kernel_nofault(bpt->saved_instr, (char *)bpt->bpt_addr,
                                BREAK_INSTR_SIZE);
        if (err)
                return err;
-       err = probe_kernel_write((char *)bpt->bpt_addr,
+       err = copy_to_kernel_nofault((char *)bpt->bpt_addr,
                                 arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
        if (!err)
                return err;
@@ -768,7 +768,7 @@ int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
        return 0;
 
 knl_write:
-       return probe_kernel_write((char *)bpt->bpt_addr,
+       return copy_to_kernel_nofault((char *)bpt->bpt_addr,
                                  (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
 }
 
index 3bafe1b..ada39dd 100644 (file)
@@ -243,7 +243,7 @@ __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr)
         * Fortunately, we know that the original code is the ideal 5-byte
         * long NOP.
         */
-       if (probe_kernel_read(buf, (void *)addr,
+       if (copy_from_kernel_nofault(buf, (void *)addr,
                MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
                return 0UL;
 
@@ -346,7 +346,8 @@ int __copy_instruction(u8 *dest, u8 *src, u8 *real, struct insn *insn)
                return 0;
 
        /* This can access kernel text if given address is not recovered */
-       if (probe_kernel_read(dest, (void *)recovered_insn, MAX_INSN_SIZE))
+       if (copy_from_kernel_nofault(dest, (void *)recovered_insn,
+                       MAX_INSN_SIZE))
                return 0;
 
        kernel_insn_init(insn, dest, MAX_INSN_SIZE);
@@ -753,16 +754,11 @@ asm(
 NOKPROBE_SYMBOL(kretprobe_trampoline);
 STACK_FRAME_NON_STANDARD(kretprobe_trampoline);
 
-static struct kprobe kretprobe_kprobe = {
-       .addr = (void *)kretprobe_trampoline,
-};
-
 /*
  * Called from kretprobe_trampoline
  */
 __used __visible void *trampoline_handler(struct pt_regs *regs)
 {
-       struct kprobe_ctlblk *kcb;
        struct kretprobe_instance *ri = NULL;
        struct hlist_head *head, empty_rp;
        struct hlist_node *tmp;
@@ -772,16 +768,12 @@ __used __visible void *trampoline_handler(struct pt_regs *regs)
        void *frame_pointer;
        bool skipped = false;
 
-       preempt_disable();
-
        /*
         * Set a dummy kprobe for avoiding kretprobe recursion.
         * Since kretprobe never run in kprobe handler, kprobe must not
         * be running at this point.
         */
-       kcb = get_kprobe_ctlblk();
-       __this_cpu_write(current_kprobe, &kretprobe_kprobe);
-       kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+       kprobe_busy_begin();
 
        INIT_HLIST_HEAD(&empty_rp);
        kretprobe_hash_lock(current, &head, &flags);
@@ -857,7 +849,7 @@ __used __visible void *trampoline_handler(struct pt_regs *regs)
                        __this_cpu_write(current_kprobe, &ri->rp->kp);
                        ri->ret_addr = correct_ret_addr;
                        ri->rp->handler(ri, regs);
-                       __this_cpu_write(current_kprobe, &kretprobe_kprobe);
+                       __this_cpu_write(current_kprobe, &kprobe_busy);
                }
 
                recycle_rp_inst(ri, &empty_rp);
@@ -873,8 +865,7 @@ __used __visible void *trampoline_handler(struct pt_regs *regs)
 
        kretprobe_hash_unlock(current, &flags);
 
-       __this_cpu_write(current_kprobe, NULL);
-       preempt_enable();
+       kprobe_busy_end();
 
        hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
                hlist_del(&ri->hlist);
index 321c199..7af4c61 100644 (file)
@@ -56,7 +56,7 @@ found:
         * overwritten by jump destination address. In this case, original
         * bytes must be recovered from op->optinsn.copied_insn buffer.
         */
-       if (probe_kernel_read(buf, (void *)addr,
+       if (copy_from_kernel_nofault(buf, (void *)addr,
                MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
                return 0UL;
 
index 8748321..b8aee71 100644 (file)
@@ -29,6 +29,8 @@
 #include <asm/mmu_context.h>
 #include <asm/pgtable_areas.h>
 
+#include <xen/xen.h>
+
 /* This is a multiple of PAGE_SIZE. */
 #define LDT_SLOT_STRIDE (LDT_ENTRIES * LDT_ENTRY_SIZE)
 
@@ -543,6 +545,28 @@ static int read_default_ldt(void __user *ptr, unsigned long bytecount)
        return bytecount;
 }
 
+static bool allow_16bit_segments(void)
+{
+       if (!IS_ENABLED(CONFIG_X86_16BIT))
+               return false;
+
+#ifdef CONFIG_XEN_PV
+       /*
+        * Xen PV does not implement ESPFIX64, which means that 16-bit
+        * segments will not work correctly.  Until either Xen PV implements
+        * ESPFIX64 and can signal this fact to the guest or unless someone
+        * provides compelling evidence that allowing broken 16-bit segments
+        * is worthwhile, disallow 16-bit segments under Xen PV.
+        */
+       if (xen_pv_domain()) {
+               pr_info_once("Warning: 16-bit segments do not work correctly in a Xen PV guest\n");
+               return false;
+       }
+#endif
+
+       return true;
+}
+
 static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
 {
        struct mm_struct *mm = current->mm;
@@ -574,7 +598,7 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
                /* The user wants to clear the entry. */
                memset(&ldt, 0, sizeof(ldt));
        } else {
-               if (!IS_ENABLED(CONFIG_X86_16BIT) && !ldt_info.seg_32bit) {
+               if (!ldt_info.seg_32bit && !allow_16bit_segments()) {
                        error = -EINVAL;
                        goto out;
                }
index 2de365f..d7c5e44 100644 (file)
@@ -478,7 +478,7 @@ static DEFINE_PER_CPU(unsigned long, nmi_dr7);
 
 DEFINE_IDTENTRY_RAW(exc_nmi)
 {
-       if (IS_ENABLED(CONFIG_SMP) && cpu_is_offline(smp_processor_id()))
+       if (IS_ENABLED(CONFIG_SMP) && arch_cpu_is_offline(smp_processor_id()))
                return;
 
        if (this_cpu_read(nmi_state) != NMI_NOT_RUNNING) {
index 674a7d6..de2138b 100644 (file)
@@ -324,7 +324,8 @@ struct paravirt_patch_template pv_ops = {
        .cpu.swapgs             = native_swapgs,
 
 #ifdef CONFIG_X86_IOPL_IOPERM
-       .cpu.update_io_bitmap   = native_tss_update_io_bitmap,
+       .cpu.invalidate_io_bitmap       = native_tss_invalidate_io_bitmap,
+       .cpu.update_io_bitmap           = native_tss_update_io_bitmap,
 #endif
 
        .cpu.start_context_switch       = paravirt_nop,
index ee02863..9e1def3 100644 (file)
@@ -94,12 +94,12 @@ static bool match_id(struct pci_dev *pdev, unsigned short vendor, unsigned short
 }
 
 static bool probe_list(struct pci_dev *pdev, unsigned short vendor,
-                      const unsigned char *rom_list)
+                      const void *rom_list)
 {
        unsigned short device;
 
        do {
-               if (probe_kernel_address(rom_list, device) != 0)
+               if (get_kernel_nofault(device, rom_list) != 0)
                        device = 0;
 
                if (device && match_id(pdev, vendor, device))
@@ -119,19 +119,19 @@ static struct resource *find_oprom(struct pci_dev *pdev)
        for (i = 0; i < ARRAY_SIZE(adapter_rom_resources); i++) {
                struct resource *res = &adapter_rom_resources[i];
                unsigned short offset, vendor, device, list, rev;
-               const unsigned char *rom;
+               const void *rom;
 
                if (res->end == 0)
                        break;
 
                rom = isa_bus_to_virt(res->start);
-               if (probe_kernel_address(rom + 0x18, offset) != 0)
+               if (get_kernel_nofault(offset, rom + 0x18) != 0)
                        continue;
 
-               if (probe_kernel_address(rom + offset + 0x4, vendor) != 0)
+               if (get_kernel_nofault(vendor, rom + offset + 0x4) != 0)
                        continue;
 
-               if (probe_kernel_address(rom + offset + 0x6, device) != 0)
+               if (get_kernel_nofault(device, rom + offset + 0x6) != 0)
                        continue;
 
                if (match_id(pdev, vendor, device)) {
@@ -139,8 +139,8 @@ static struct resource *find_oprom(struct pci_dev *pdev)
                        break;
                }
 
-               if (probe_kernel_address(rom + offset + 0x8, list) == 0 &&
-                   probe_kernel_address(rom + offset + 0xc, rev) == 0 &&
+               if (get_kernel_nofault(list, rom + offset + 0x8) == 0 &&
+                   get_kernel_nofault(rev, rom + offset + 0xc) == 0 &&
                    rev >= 3 && list &&
                    probe_list(pdev, vendor, rom + offset + list)) {
                        oprom = res;
@@ -183,14 +183,14 @@ static int __init romsignature(const unsigned char *rom)
        const unsigned short * const ptr = (const unsigned short *)rom;
        unsigned short sig;
 
-       return probe_kernel_address(ptr, sig) == 0 && sig == ROMSIGNATURE;
+       return get_kernel_nofault(sig, ptr) == 0 && sig == ROMSIGNATURE;
 }
 
 static int __init romchecksum(const unsigned char *rom, unsigned long length)
 {
        unsigned char sum, c;
 
-       for (sum = 0; length && probe_kernel_address(rom++, c) == 0; length--)
+       for (sum = 0; length && get_kernel_nofault(c, rom++) == 0; length--)
                sum += c;
        return !length && !sum;
 }
@@ -211,7 +211,7 @@ void __init probe_roms(void)
 
                video_rom_resource.start = start;
 
-               if (probe_kernel_address(rom + 2, c) != 0)
+               if (get_kernel_nofault(c, rom + 2) != 0)
                        continue;
 
                /* 0 < length <= 0x7f * 512, historically */
@@ -249,7 +249,7 @@ void __init probe_roms(void)
                if (!romsignature(rom))
                        continue;
 
-               if (probe_kernel_address(rom + 2, c) != 0)
+               if (get_kernel_nofault(c, rom + 2) != 0)
                        continue;
 
                /* 0 < length <= 0x7f * 512, historically */
index f362ce0..fe67dbd 100644 (file)
@@ -322,20 +322,6 @@ void arch_setup_new_exec(void)
 }
 
 #ifdef CONFIG_X86_IOPL_IOPERM
-static inline void tss_invalidate_io_bitmap(struct tss_struct *tss)
-{
-       /*
-        * Invalidate the I/O bitmap by moving io_bitmap_base outside the
-        * TSS limit so any subsequent I/O access from user space will
-        * trigger a #GP.
-        *
-        * This is correct even when VMEXIT rewrites the TSS limit
-        * to 0x67 as the only requirement is that the base points
-        * outside the limit.
-        */
-       tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET_INVALID;
-}
-
 static inline void switch_to_bitmap(unsigned long tifp)
 {
        /*
@@ -346,7 +332,7 @@ static inline void switch_to_bitmap(unsigned long tifp)
         * user mode.
         */
        if (tifp & _TIF_IO_BITMAP)
-               tss_invalidate_io_bitmap(this_cpu_ptr(&cpu_tss_rw));
+               tss_invalidate_io_bitmap();
 }
 
 static void tss_copy_io_bitmap(struct tss_struct *tss, struct io_bitmap *iobm)
@@ -380,7 +366,7 @@ void native_tss_update_io_bitmap(void)
        u16 *base = &tss->x86_tss.io_bitmap_base;
 
        if (!test_thread_flag(TIF_IO_BITMAP)) {
-               tss_invalidate_io_bitmap(tss);
+               native_tss_invalidate_io_bitmap();
                return;
        }
 
index 6ad43fc..2fd698e 100644 (file)
@@ -58,7 +58,6 @@ int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
                         * or a page fault), which can make frame pointers
                         * unreliable.
                         */
-
                        if (IS_ENABLED(CONFIG_FRAME_POINTER))
                                return -EINVAL;
                }
@@ -81,10 +80,6 @@ int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
        if (unwind_error(&state))
                return -EINVAL;
 
-       /* Success path for non-user tasks, i.e. kthreads and idle tasks */
-       if (!(task->flags & (PF_KTHREAD | PF_IDLE)))
-               return -EINVAL;
-
        return 0;
 }
 
index af75109..b7cb3e0 100644 (file)
@@ -84,17 +84,16 @@ static inline void cond_local_irq_disable(struct pt_regs *regs)
                local_irq_disable();
 }
 
-int is_valid_bugaddr(unsigned long addr)
+__always_inline int is_valid_bugaddr(unsigned long addr)
 {
-       unsigned short ud;
-
        if (addr < TASK_SIZE_MAX)
                return 0;
 
-       if (probe_kernel_address((unsigned short *)addr, ud))
-               return 0;
-
-       return ud == INSN_UD0 || ud == INSN_UD2;
+       /*
+        * We got #UD, if the text isn't readable we'd have gotten
+        * a different exception.
+        */
+       return *(unsigned short *)addr == INSN_UD2;
 }
 
 static nokprobe_inline int
@@ -216,40 +215,45 @@ static inline void handle_invalid_op(struct pt_regs *regs)
                      ILL_ILLOPN, error_get_trap_addr(regs));
 }
 
-DEFINE_IDTENTRY_RAW(exc_invalid_op)
+static noinstr bool handle_bug(struct pt_regs *regs)
 {
-       bool rcu_exit;
+       bool handled = false;
+
+       if (!is_valid_bugaddr(regs->ip))
+               return handled;
 
        /*
-        * Handle BUG/WARN like NMIs instead of like normal idtentries:
-        * if we bugged/warned in a bad RCU context, for example, the last
-        * thing we want is to BUG/WARN again in the idtentry code, ad
-        * infinitum.
+        * All lies, just get the WARN/BUG out.
+        */
+       instrumentation_begin();
+       /*
+        * Since we're emulating a CALL with exceptions, restore the interrupt
+        * state to what it was at the exception site.
         */
-       if (!user_mode(regs) && is_valid_bugaddr(regs->ip)) {
-               enum bug_trap_type type;
+       if (regs->flags & X86_EFLAGS_IF)
+               raw_local_irq_enable();
+       if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN) {
+               regs->ip += LEN_UD2;
+               handled = true;
+       }
+       if (regs->flags & X86_EFLAGS_IF)
+               raw_local_irq_disable();
+       instrumentation_end();
 
-               nmi_enter();
-               instrumentation_begin();
-               trace_hardirqs_off_finish();
-               type = report_bug(regs->ip, regs);
-               if (regs->flags & X86_EFLAGS_IF)
-                       trace_hardirqs_on_prepare();
-               instrumentation_end();
-               nmi_exit();
+       return handled;
+}
 
-               if (type == BUG_TRAP_TYPE_WARN) {
-                       /* Skip the ud2. */
-                       regs->ip += LEN_UD2;
-                       return;
-               }
+DEFINE_IDTENTRY_RAW(exc_invalid_op)
+{
+       bool rcu_exit;
 
-               /*
-                * Else, if this was a BUG and report_bug returns or if this
-                * was just a normal #UD, we want to continue onward and
-                * crash.
-                */
-       }
+       /*
+        * We use UD2 as a short encoding for 'CALL __WARN', as such
+        * handle it before exception entry to avoid recursive WARN
+        * in case exception entry is the one triggering WARNs.
+        */
+       if (!user_mode(regs) && handle_bug(regs))
+               return;
 
        rcu_exit = idtentry_enter_cond_rcu(regs);
        instrumentation_begin();
@@ -299,6 +303,8 @@ DEFINE_IDTENTRY_ERRORCODE(exc_alignment_check)
 
        do_trap(X86_TRAP_AC, SIGBUS, "alignment check", regs,
                error_code, BUS_ADRALN, NULL);
+
+       local_irq_disable();
 }
 
 #ifdef CONFIG_VMAP_STACK
@@ -488,7 +494,8 @@ static enum kernel_gp_hint get_kernel_gp_address(struct pt_regs *regs,
        u8 insn_buf[MAX_INSN_SIZE];
        struct insn insn;
 
-       if (probe_kernel_read(insn_buf, (void *)regs->ip, MAX_INSN_SIZE))
+       if (copy_from_kernel_nofault(insn_buf, (void *)regs->ip,
+                       MAX_INSN_SIZE))
                return GP_NO_HINT;
 
        kernel_insn_init(&insn, insn_buf, MAX_INSN_SIZE);
@@ -690,13 +697,13 @@ struct bad_iret_stack *fixup_bad_iret(struct bad_iret_stack *s)
                (struct bad_iret_stack *)__this_cpu_read(cpu_tss_rw.x86_tss.sp0) - 1;
 
        /* Copy the IRET target to the temporary storage. */
-       memcpy(&tmp.regs.ip, (void *)s->regs.sp, 5*8);
+       __memcpy(&tmp.regs.ip, (void *)s->regs.sp, 5*8);
 
        /* Copy the remainder of the stack from the current stack. */
-       memcpy(&tmp, s, offsetof(struct bad_iret_stack, regs.ip));
+       __memcpy(&tmp, s, offsetof(struct bad_iret_stack, regs.ip));
 
        /* Update the entry stack */
-       memcpy(new_stack, &tmp, sizeof(tmp));
+       __memcpy(new_stack, &tmp, sizeof(tmp));
 
        BUG_ON(!user_mode(&new_stack->regs));
        return new_stack;
@@ -864,6 +871,12 @@ static __always_inline void exc_debug_kernel(struct pt_regs *regs,
        instrumentation_begin();
        trace_hardirqs_off_finish();
 
+       /*
+        * If something gets miswired and we end up here for a user mode
+        * #DB, we will malfunction.
+        */
+       WARN_ON_ONCE(user_mode(regs));
+
        /*
         * Catch SYSENTER with TF set and clear DR_STEP. If this hit a
         * watchpoint at the same time then that will still be handled.
@@ -882,6 +895,12 @@ static __always_inline void exc_debug_kernel(struct pt_regs *regs,
 static __always_inline void exc_debug_user(struct pt_regs *regs,
                                           unsigned long dr6)
 {
+       /*
+        * If something gets miswired and we end up here for a kernel mode
+        * #DB, we will malfunction.
+        */
+       WARN_ON_ONCE(!user_mode(regs));
+
        idtentry_enter_user(regs);
        instrumentation_begin();
 
@@ -912,7 +931,7 @@ DEFINE_IDTENTRY_DEBUG_USER(exc_debug)
 }
 #else
 /* 32 bit does not have separate entry points. */
-DEFINE_IDTENTRY_DEBUG(exc_debug)
+DEFINE_IDTENTRY_RAW(exc_debug)
 {
        unsigned long dr6, dr7;
 
index 7f969b2..ec88bbe 100644 (file)
@@ -440,8 +440,11 @@ bool unwind_next_frame(struct unwind_state *state)
        /*
         * Find the orc_entry associated with the text address.
         *
-        * Decrement call return addresses by one so they work for sibling
-        * calls and calls to noreturn functions.
+        * For a call frame (as opposed to a signal frame), state->ip points to
+        * the instruction after the call.  That instruction's stack layout
+        * could be different from the call instruction's layout, for example
+        * if the call was to a noreturn function.  So get the ORC data for the
+        * call instruction itself.
         */
        orc = orc_find(state->signal ? state->ip : state->ip - 1);
        if (!orc) {
@@ -662,6 +665,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
                state->sp = task->thread.sp;
                state->bp = READ_ONCE_NOCHECK(frame->bp);
                state->ip = READ_ONCE_NOCHECK(frame->ret_addr);
+               state->signal = (void *)state->ip == ret_from_fork;
        }
 
        if (get_stack_info((unsigned long *)state->sp, state->task,
index 3bfc8dd..9a03e5b 100644 (file)
@@ -358,6 +358,7 @@ SECTIONS
        .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
                __bss_start = .;
                *(.bss..page_aligned)
+               . = ALIGN(PAGE_SIZE);
                *(BSS_MAIN)
                BSS_DECRYPTED
                . = ALIGN(PAGE_SIZE);
index ff2d0e9..cfe83d4 100644 (file)
@@ -7,7 +7,7 @@
 #define KVM_POSSIBLE_CR0_GUEST_BITS X86_CR0_TS
 #define KVM_POSSIBLE_CR4_GUEST_BITS                              \
        (X86_CR4_PVI | X86_CR4_DE | X86_CR4_PCE | X86_CR4_OSFXSR  \
-        | X86_CR4_OSXMMEXCPT | X86_CR4_LA57 | X86_CR4_PGE)
+        | X86_CR4_OSXMMEXCPT | X86_CR4_LA57 | X86_CR4_PGE | X86_CR4_TSD)
 
 #define BUILD_KVM_GPR_ACCESSORS(lname, uname)                                \
 static __always_inline unsigned long kvm_##lname##_read(struct kvm_vcpu *vcpu)\
index 34a7e05..5bf72fc 100644 (file)
@@ -169,6 +169,18 @@ static void kvm_apic_map_free(struct rcu_head *rcu)
        kvfree(map);
 }
 
+/*
+ * CLEAN -> DIRTY and UPDATE_IN_PROGRESS -> DIRTY changes happen without a lock.
+ *
+ * DIRTY -> UPDATE_IN_PROGRESS and UPDATE_IN_PROGRESS -> CLEAN happen with
+ * apic_map_lock_held.
+ */
+enum {
+       CLEAN,
+       UPDATE_IN_PROGRESS,
+       DIRTY
+};
+
 void kvm_recalculate_apic_map(struct kvm *kvm)
 {
        struct kvm_apic_map *new, *old = NULL;
@@ -176,17 +188,17 @@ void kvm_recalculate_apic_map(struct kvm *kvm)
        int i;
        u32 max_id = 255; /* enough space for any xAPIC ID */
 
-       if (!kvm->arch.apic_map_dirty) {
-               /*
-                * Read kvm->arch.apic_map_dirty before
-                * kvm->arch.apic_map
-                */
-               smp_rmb();
+       /* Read kvm->arch.apic_map_dirty before kvm->arch.apic_map.  */
+       if (atomic_read_acquire(&kvm->arch.apic_map_dirty) == CLEAN)
                return;
-       }
 
        mutex_lock(&kvm->arch.apic_map_lock);
-       if (!kvm->arch.apic_map_dirty) {
+       /*
+        * Read kvm->arch.apic_map_dirty before kvm->arch.apic_map
+        * (if clean) or the APIC registers (if dirty).
+        */
+       if (atomic_cmpxchg_acquire(&kvm->arch.apic_map_dirty,
+                                  DIRTY, UPDATE_IN_PROGRESS) == CLEAN) {
                /* Someone else has updated the map. */
                mutex_unlock(&kvm->arch.apic_map_lock);
                return;
@@ -256,11 +268,11 @@ out:
                        lockdep_is_held(&kvm->arch.apic_map_lock));
        rcu_assign_pointer(kvm->arch.apic_map, new);
        /*
-        * Write kvm->arch.apic_map before
-        * clearing apic->apic_map_dirty
+        * Write kvm->arch.apic_map before clearing apic->apic_map_dirty.
+        * If another update has come in, leave it DIRTY.
         */
-       smp_wmb();
-       kvm->arch.apic_map_dirty = false;
+       atomic_cmpxchg_release(&kvm->arch.apic_map_dirty,
+                              UPDATE_IN_PROGRESS, CLEAN);
        mutex_unlock(&kvm->arch.apic_map_lock);
 
        if (old)
@@ -282,20 +294,20 @@ static inline void apic_set_spiv(struct kvm_lapic *apic, u32 val)
                else
                        static_key_slow_inc(&apic_sw_disabled.key);
 
-               apic->vcpu->kvm->arch.apic_map_dirty = true;
+               atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
        }
 }
 
 static inline void kvm_apic_set_xapic_id(struct kvm_lapic *apic, u8 id)
 {
        kvm_lapic_set_reg(apic, APIC_ID, id << 24);
-       apic->vcpu->kvm->arch.apic_map_dirty = true;
+       atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
 }
 
 static inline void kvm_apic_set_ldr(struct kvm_lapic *apic, u32 id)
 {
        kvm_lapic_set_reg(apic, APIC_LDR, id);
-       apic->vcpu->kvm->arch.apic_map_dirty = true;
+       atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
 }
 
 static inline u32 kvm_apic_calc_x2apic_ldr(u32 id)
@@ -311,7 +323,7 @@ static inline void kvm_apic_set_x2apic_id(struct kvm_lapic *apic, u32 id)
 
        kvm_lapic_set_reg(apic, APIC_ID, id);
        kvm_lapic_set_reg(apic, APIC_LDR, ldr);
-       apic->vcpu->kvm->arch.apic_map_dirty = true;
+       atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
 }
 
 static inline int apic_lvt_enabled(struct kvm_lapic *apic, int lvt_type)
@@ -1976,7 +1988,7 @@ int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
        case APIC_DFR:
                if (!apic_x2apic_mode(apic)) {
                        kvm_lapic_set_reg(apic, APIC_DFR, val | 0x0FFFFFFF);
-                       apic->vcpu->kvm->arch.apic_map_dirty = true;
+                       atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
                } else
                        ret = 1;
                break;
@@ -2232,7 +2244,7 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
                        static_key_slow_dec_deferred(&apic_hw_disabled);
                } else {
                        static_key_slow_inc(&apic_hw_disabled.key);
-                       vcpu->kvm->arch.apic_map_dirty = true;
+                       atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
                }
        }
 
@@ -2273,7 +2285,6 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
        if (!apic)
                return;
 
-       vcpu->kvm->arch.apic_map_dirty = false;
        /* Stop the timer in case it's a reset to an active apic */
        hrtimer_cancel(&apic->lapic_timer.timer);
 
@@ -2567,6 +2578,7 @@ int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
        }
        memcpy(vcpu->arch.apic->regs, s->regs, sizeof(*s));
 
+       atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
        kvm_recalculate_apic_map(vcpu->kvm);
        kvm_apic_set_version(vcpu);
 
index 0ad06bf..444bb9c 100644 (file)
@@ -222,7 +222,7 @@ void kvm_mmu_gfn_disallow_lpage(struct kvm_memory_slot *slot, gfn_t gfn);
 void kvm_mmu_gfn_allow_lpage(struct kvm_memory_slot *slot, gfn_t gfn);
 bool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm,
                                    struct kvm_memory_slot *slot, u64 gfn);
-int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu);
+int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu, gpa_t l2_gpa);
 
 int kvm_mmu_post_init_vm(struct kvm *kvm);
 void kvm_mmu_pre_destroy_vm(struct kvm *kvm);
index fdd05c2..6d6a0ae 100644 (file)
@@ -1745,10 +1745,10 @@ void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm,
  * Emulate arch specific page modification logging for the
  * nested hypervisor
  */
-int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu)
+int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu, gpa_t l2_gpa)
 {
        if (kvm_x86_ops.write_log_dirty)
-               return kvm_x86_ops.write_log_dirty(vcpu);
+               return kvm_x86_ops.write_log_dirty(vcpu, l2_gpa);
 
        return 0;
 }
@@ -4449,7 +4449,7 @@ __reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
                        nonleaf_bit8_rsvd | rsvd_bits(7, 7) |
                        rsvd_bits(maxphyaddr, 51);
                rsvd_check->rsvd_bits_mask[0][2] = exb_bit_rsvd |
-                       nonleaf_bit8_rsvd | gbpages_bit_rsvd |
+                       gbpages_bit_rsvd |
                        rsvd_bits(maxphyaddr, 51);
                rsvd_check->rsvd_bits_mask[0][1] = exb_bit_rsvd |
                        rsvd_bits(maxphyaddr, 51);
index a6d484e..bd70ece 100644 (file)
@@ -235,7 +235,7 @@ static inline unsigned FNAME(gpte_access)(u64 gpte)
 static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu,
                                             struct kvm_mmu *mmu,
                                             struct guest_walker *walker,
-                                            int write_fault)
+                                            gpa_t addr, int write_fault)
 {
        unsigned level, index;
        pt_element_t pte, orig_pte;
@@ -260,7 +260,7 @@ static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu,
                                !(pte & PT_GUEST_DIRTY_MASK)) {
                        trace_kvm_mmu_set_dirty_bit(table_gfn, index, sizeof(pte));
 #if PTTYPE == PTTYPE_EPT
-                       if (kvm_arch_write_log_dirty(vcpu))
+                       if (kvm_arch_write_log_dirty(vcpu, addr))
                                return -EINVAL;
 #endif
                        pte |= PT_GUEST_DIRTY_MASK;
@@ -360,7 +360,6 @@ retry_walk:
        ++walker->level;
 
        do {
-               gfn_t real_gfn;
                unsigned long host_addr;
 
                pt_access = pte_access;
@@ -375,7 +374,7 @@ retry_walk:
                walker->table_gfn[walker->level - 1] = table_gfn;
                walker->pte_gpa[walker->level - 1] = pte_gpa;
 
-               real_gfn = mmu->translate_gpa(vcpu, gfn_to_gpa(table_gfn),
+               real_gpa = mmu->translate_gpa(vcpu, gfn_to_gpa(table_gfn),
                                              nested_access,
                                              &walker->fault);
 
@@ -389,12 +388,10 @@ retry_walk:
                 * information to fix the exit_qualification or exit_info_1
                 * fields.
                 */
-               if (unlikely(real_gfn == UNMAPPED_GVA))
+               if (unlikely(real_gpa == UNMAPPED_GVA))
                        return 0;
 
-               real_gfn = gpa_to_gfn(real_gfn);
-
-               host_addr = kvm_vcpu_gfn_to_hva_prot(vcpu, real_gfn,
+               host_addr = kvm_vcpu_gfn_to_hva_prot(vcpu, gpa_to_gfn(real_gpa),
                                            &walker->pte_writable[walker->level - 1]);
                if (unlikely(kvm_is_error_hva(host_addr)))
                        goto error;
@@ -457,7 +454,8 @@ retry_walk:
                        (PT_GUEST_DIRTY_SHIFT - PT_GUEST_ACCESSED_SHIFT);
 
        if (unlikely(!accessed_dirty)) {
-               ret = FNAME(update_accessed_dirty_bits)(vcpu, mmu, walker, write_fault);
+               ret = FNAME(update_accessed_dirty_bits)(vcpu, mmu, walker,
+                                                       addr, write_fault);
                if (unlikely(ret < 0))
                        goto error;
                else if (ret)
index 8ccfa41..c0da4dd 100644 (file)
@@ -3344,7 +3344,7 @@ static fastpath_t svm_exit_handlers_fastpath(struct kvm_vcpu *vcpu)
 
 void __svm_vcpu_run(unsigned long vmcb_pa, unsigned long *regs);
 
-static fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
+static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
 {
        fastpath_t exit_fastpath;
        struct vcpu_svm *svm = to_svm(vcpu);
index d1af20b..d4a4cec 100644 (file)
@@ -4109,7 +4109,7 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
         * CR0_GUEST_HOST_MASK is already set in the original vmcs01
         * (KVM doesn't change it);
         */
-       vcpu->arch.cr0_guest_owned_bits = X86_CR0_TS;
+       vcpu->arch.cr0_guest_owned_bits = KVM_POSSIBLE_CR0_GUEST_BITS;
        vmx_set_cr0(vcpu, vmcs12->host_cr0);
 
        /* Same as above - no reason to call set_cr4_guest_host_mask().  */
@@ -4259,7 +4259,7 @@ static void nested_vmx_restore_host_state(struct kvm_vcpu *vcpu)
         */
        vmx_set_efer(vcpu, nested_vmx_get_vmcs01_guest_efer(vmx));
 
-       vcpu->arch.cr0_guest_owned_bits = X86_CR0_TS;
+       vcpu->arch.cr0_guest_owned_bits = KVM_POSSIBLE_CR0_GUEST_BITS;
        vmx_set_cr0(vcpu, vmcs_readl(CR0_READ_SHADOW));
 
        vcpu->arch.cr4_guest_owned_bits = ~vmcs_readl(CR4_GUEST_HOST_MASK);
@@ -6176,6 +6176,7 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu,
                        goto error_guest_mode;
        }
 
+       vmx->nested.has_preemption_timer_deadline = false;
        if (kvm_state->hdr.vmx.flags & KVM_STATE_VMX_PREEMPTION_TIMER_DEADLINE) {
                vmx->nested.has_preemption_timer_deadline = true;
                vmx->nested.preemption_timer_deadline =
index 5c0ff80..7a3675f 100644 (file)
@@ -72,11 +72,24 @@ struct loaded_vmcs {
        struct vmcs_controls_shadow controls_shadow;
 };
 
+static inline bool is_intr_type(u32 intr_info, u32 type)
+{
+       const u32 mask = INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK;
+
+       return (intr_info & mask) == (INTR_INFO_VALID_MASK | type);
+}
+
+static inline bool is_intr_type_n(u32 intr_info, u32 type, u8 vector)
+{
+       const u32 mask = INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK |
+                        INTR_INFO_VECTOR_MASK;
+
+       return (intr_info & mask) == (INTR_INFO_VALID_MASK | type | vector);
+}
+
 static inline bool is_exception_n(u32 intr_info, u8 vector)
 {
-       return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
-                            INTR_INFO_VALID_MASK)) ==
-               (INTR_TYPE_HARD_EXCEPTION | vector | INTR_INFO_VALID_MASK);
+       return is_intr_type_n(intr_info, INTR_TYPE_HARD_EXCEPTION, vector);
 }
 
 static inline bool is_debug(u32 intr_info)
@@ -106,28 +119,23 @@ static inline bool is_gp_fault(u32 intr_info)
 
 static inline bool is_machine_check(u32 intr_info)
 {
-       return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
-                            INTR_INFO_VALID_MASK)) ==
-               (INTR_TYPE_HARD_EXCEPTION | MC_VECTOR | INTR_INFO_VALID_MASK);
+       return is_exception_n(intr_info, MC_VECTOR);
 }
 
 /* Undocumented: icebp/int1 */
 static inline bool is_icebp(u32 intr_info)
 {
-       return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
-               == (INTR_TYPE_PRIV_SW_EXCEPTION | INTR_INFO_VALID_MASK);
+       return is_intr_type(intr_info, INTR_TYPE_PRIV_SW_EXCEPTION);
 }
 
 static inline bool is_nmi(u32 intr_info)
 {
-       return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
-               == (INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK);
+       return is_intr_type(intr_info, INTR_TYPE_NMI_INTR);
 }
 
 static inline bool is_external_intr(u32 intr_info)
 {
-       return (intr_info & (INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK))
-               == (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR);
+       return is_intr_type(intr_info, INTR_TYPE_EXT_INTR);
 }
 
 enum vmcs_field_width {
index 36c7717..13745f2 100644 (file)
@@ -133,9 +133,6 @@ module_param_named(preemption_timer, enable_preemption_timer, bool, S_IRUGO);
 #define KVM_VM_CR0_ALWAYS_ON                           \
        (KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST |      \
         X86_CR0_WP | X86_CR0_PG | X86_CR0_PE)
-#define KVM_CR4_GUEST_OWNED_BITS                                     \
-       (X86_CR4_PVI | X86_CR4_DE | X86_CR4_PCE | X86_CR4_OSFXSR      \
-        | X86_CR4_OSXMMEXCPT | X86_CR4_LA57 | X86_CR4_TSD)
 
 #define KVM_VM_CR4_ALWAYS_ON_UNRESTRICTED_GUEST X86_CR4_VMXE
 #define KVM_PMODE_VM_CR4_ALWAYS_ON (X86_CR4_PAE | X86_CR4_VMXE)
@@ -4034,9 +4031,9 @@ void vmx_set_constant_host_state(struct vcpu_vmx *vmx)
 
 void set_cr4_guest_host_mask(struct vcpu_vmx *vmx)
 {
-       vmx->vcpu.arch.cr4_guest_owned_bits = KVM_CR4_GUEST_OWNED_BITS;
-       if (enable_ept)
-               vmx->vcpu.arch.cr4_guest_owned_bits |= X86_CR4_PGE;
+       vmx->vcpu.arch.cr4_guest_owned_bits = KVM_POSSIBLE_CR4_GUEST_BITS;
+       if (!enable_ept)
+               vmx->vcpu.arch.cr4_guest_owned_bits &= ~X86_CR4_PGE;
        if (is_guest_mode(&vmx->vcpu))
                vmx->vcpu.arch.cr4_guest_owned_bits &=
                        ~get_vmcs12(&vmx->vcpu)->cr4_guest_host_mask;
@@ -4333,8 +4330,8 @@ static void init_vmcs(struct vcpu_vmx *vmx)
        /* 22.2.1, 20.8.1 */
        vm_entry_controls_set(vmx, vmx_vmentry_ctrl());
 
-       vmx->vcpu.arch.cr0_guest_owned_bits = X86_CR0_TS;
-       vmcs_writel(CR0_GUEST_HOST_MASK, ~X86_CR0_TS);
+       vmx->vcpu.arch.cr0_guest_owned_bits = KVM_POSSIBLE_CR0_GUEST_BITS;
+       vmcs_writel(CR0_GUEST_HOST_MASK, ~vmx->vcpu.arch.cr0_guest_owned_bits);
 
        set_cr4_guest_host_mask(vmx);
 
@@ -6606,23 +6603,6 @@ static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx)
                                        msrs[i].host, false);
 }
 
-static void atomic_switch_umwait_control_msr(struct vcpu_vmx *vmx)
-{
-       u32 host_umwait_control;
-
-       if (!vmx_has_waitpkg(vmx))
-               return;
-
-       host_umwait_control = get_umwait_control_msr();
-
-       if (vmx->msr_ia32_umwait_control != host_umwait_control)
-               add_atomic_switch_msr(vmx, MSR_IA32_UMWAIT_CONTROL,
-                       vmx->msr_ia32_umwait_control,
-                       host_umwait_control, false);
-       else
-               clear_atomic_switch_msr(vmx, MSR_IA32_UMWAIT_CONTROL);
-}
-
 static void vmx_update_hv_timer(struct kvm_vcpu *vcpu)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -6728,9 +6708,7 @@ reenter_guest:
 
        pt_guest_enter(vmx);
 
-       if (vcpu_to_pmu(vcpu)->version)
-               atomic_switch_perf_msrs(vmx);
-       atomic_switch_umwait_control_msr(vmx);
+       atomic_switch_perf_msrs(vmx);
 
        if (enable_preemption_timer)
                vmx_update_hv_timer(vcpu);
@@ -7501,11 +7479,11 @@ static void vmx_flush_log_dirty(struct kvm *kvm)
        kvm_flush_pml_buffers(kvm);
 }
 
-static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu)
+static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu, gpa_t gpa)
 {
        struct vmcs12 *vmcs12;
        struct vcpu_vmx *vmx = to_vmx(vcpu);
-       gpa_t gpa, dst;
+       gpa_t dst;
 
        if (is_guest_mode(vcpu)) {
                WARN_ON_ONCE(vmx->nested.pml_full);
@@ -7524,7 +7502,7 @@ static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu)
                        return 1;
                }
 
-               gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS) & ~0xFFFull;
+               gpa &= ~0xFFFull;
                dst = vmcs12->pml_address + sizeof(u64) * vmcs12->guest_pml_index;
 
                if (kvm_write_guest_page(vcpu->kvm, gpa_to_gfn(dst), &gpa,
index 8a83b5e..639798e 100644 (file)
@@ -288,8 +288,6 @@ struct vcpu_vmx {
 
        u64 current_tsc_ratio;
 
-       u32 host_pkru;
-
        unsigned long host_debugctlmsr;
 
        /*
index 00c88c2..88c593f 100644 (file)
@@ -975,6 +975,8 @@ int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
        if (is_long_mode(vcpu)) {
                if (!(cr4 & X86_CR4_PAE))
                        return 1;
+               if ((cr4 ^ old_cr4) & X86_CR4_LA57)
+                       return 1;
        } else if (is_paging(vcpu) && (cr4 & X86_CR4_PAE)
                   && ((cr4 ^ old_cr4) & pdptr_bits)
                   && !load_pdptrs(vcpu, vcpu->arch.walk_mmu,
@@ -2693,6 +2695,9 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
        if (data & 0x30)
                return 1;
 
+       if (!lapic_in_kernel(vcpu))
+               return 1;
+
        vcpu->arch.apf.msr_en_val = data;
 
        if (!kvm_pv_async_pf_enabled(vcpu)) {
@@ -2856,7 +2861,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                return kvm_mtrr_set_msr(vcpu, msr, data);
        case MSR_IA32_APICBASE:
                return kvm_set_apic_base(vcpu, msr_info);
-       case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
+       case APIC_BASE_MSR ... APIC_BASE_MSR + 0xff:
                return kvm_x2apic_msr_write(vcpu, msr, data);
        case MSR_IA32_TSCDEADLINE:
                kvm_set_lapic_tscdeadline_msr(vcpu, data);
@@ -3196,7 +3201,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
        case MSR_IA32_APICBASE:
                msr_info->data = kvm_get_apic_base(vcpu);
                break;
-       case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
+       case APIC_BASE_MSR ... APIC_BASE_MSR + 0xff:
                return kvm_x2apic_msr_read(vcpu, msr_info->index, &msr_info->data);
        case MSR_IA32_TSCDEADLINE:
                msr_info->data = kvm_get_lapic_tscdeadline_msr(vcpu);
@@ -4603,7 +4608,8 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                r = -EINVAL;
                user_tsc_khz = (u32)arg;
 
-               if (user_tsc_khz >= kvm_max_guest_tsc_khz)
+               if (kvm_has_tsc_control &&
+                   user_tsc_khz >= kvm_max_guest_tsc_khz)
                        goto out;
 
                if (user_tsc_khz == 0)
index 56b243b..bbcc05b 100644 (file)
@@ -8,6 +8,8 @@
 #include <asm/alternative-asm.h>
 #include <asm/export.h>
 
+.pushsection .noinstr.text, "ax"
+
 /*
  * We build a jump to memcpy_orig by default which gets NOPped out on
  * the majority of x86 CPUs which set REP_GOOD. In addition, CPUs which
@@ -184,6 +186,8 @@ SYM_FUNC_START_LOCAL(memcpy_orig)
        retq
 SYM_FUNC_END(memcpy_orig)
 
+.popsection
+
 #ifndef CONFIG_UML
 
 MCSAFE_TEST_CTL
index fff28c6..b0dfac3 100644 (file)
@@ -24,6 +24,7 @@ unsigned long __clear_user(void __user *addr, unsigned long size)
        asm volatile(
                "       testq  %[size8],%[size8]\n"
                "       jz     4f\n"
+               "       .align 16\n"
                "0:     movq $0,(%[dst])\n"
                "       addq   $8,%[dst]\n"
                "       decl %%ecx ; jnz   0b\n"
index 3b2b581..40526dd 100644 (file)
@@ -209,7 +209,7 @@ sqrt_stage_2_finish:
 
 #ifdef PARANOID
 /* It should be possible to get here only if the arg is ffff....ffff */
-       cmp     $0xffffffff,FPU_fsqrt_arg_1
+       cmpl    $0xffffffff,FPU_fsqrt_arg_1
        jnz     sqrt_stage_2_error
 #endif /* PARANOID */
 
index 66be9bd..1ead568 100644 (file)
@@ -99,7 +99,7 @@ check_prefetch_opcode(struct pt_regs *regs, unsigned char *instr,
                return !instr_lo || (instr_lo>>1) == 1;
        case 0x00:
                /* Prefetch instruction is 0x0F0D or 0x0F18 */
-               if (probe_kernel_address(instr, opcode))
+               if (get_kernel_nofault(opcode, instr))
                        return 0;
 
                *prefetch = (instr_lo == 0xF) &&
@@ -133,7 +133,7 @@ is_prefetch(struct pt_regs *regs, unsigned long error_code, unsigned long addr)
        while (instr < max_instr) {
                unsigned char opcode;
 
-               if (probe_kernel_address(instr, opcode))
+               if (get_kernel_nofault(opcode, instr))
                        break;
 
                instr++;
@@ -301,7 +301,7 @@ static int bad_address(void *p)
 {
        unsigned long dummy;
 
-       return probe_kernel_address((unsigned long *)p, dummy);
+       return get_kernel_nofault(dummy, (unsigned long *)p);
 }
 
 static void dump_pagetable(unsigned long address)
@@ -442,7 +442,7 @@ static void show_ldttss(const struct desc_ptr *gdt, const char *name, u16 index)
                return;
        }
 
-       if (probe_kernel_read(&desc, (void *)(gdt->address + offset),
+       if (copy_from_kernel_nofault(&desc, (void *)(gdt->address + offset),
                              sizeof(struct ldttss_desc))) {
                pr_alert("%s: 0x%hx -- GDT entry is not readable\n",
                         name, index);
index bda909e..8b4afad 100644 (file)
@@ -737,7 +737,7 @@ static void __init test_wp_bit(void)
 
        __set_fixmap(FIX_WP_TEST, __pa_symbol(empty_zero_page), PAGE_KERNEL_RO);
 
-       if (probe_kernel_write((char *)fix_to_virt(FIX_WP_TEST), &z, 1)) {
+       if (copy_to_kernel_nofault((char *)fix_to_virt(FIX_WP_TEST), &z, 1)) {
                clear_fixmap(FIX_WP_TEST);
                printk(KERN_CONT "Ok.\n");
                return;
index e1d7d74..92ec176 100644 (file)
@@ -9,7 +9,7 @@ static __always_inline u64 canonical_address(u64 vaddr, u8 vaddr_bits)
        return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
 }
 
-bool probe_kernel_read_allowed(const void *unsafe_src, size_t size)
+bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
 {
        unsigned long vaddr = (unsigned long)unsafe_src;
 
@@ -22,7 +22,7 @@ bool probe_kernel_read_allowed(const void *unsafe_src, size_t size)
               canonical_address(vaddr, boot_cpu_data.x86_virt_bits) == vaddr;
 }
 #else
-bool probe_kernel_read_allowed(const void *unsafe_src, size_t size)
+bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
 {
        return (unsigned long)unsafe_src >= TASK_SIZE_MAX;
 }
index 9c97d81..4f15280 100644 (file)
@@ -302,7 +302,7 @@ static const struct pci_raw_ops *__init pci_find_bios(void)
             check <= (union bios32 *) __va(0xffff0);
             ++check) {
                long sig;
-               if (probe_kernel_address(&check->fields.signature, sig))
+               if (get_kernel_nofault(sig, &check->fields.signature))
                        continue;
 
                if (check->fields.signature != BIOS32_SIGNATURE)
index b8f7f19..30bd571 100644 (file)
@@ -287,8 +287,8 @@ void intel_scu_devices_create(void)
 
                adapter = i2c_get_adapter(i2c_bus[i]);
                if (adapter) {
-                       client = i2c_new_device(adapter, i2c_devs[i]);
-                       if (!client)
+                       client = i2c_new_client_device(adapter, i2c_devs[i]);
+                       if (IS_ERR(client))
                                pr_err("can't create i2c device %s\n",
                                        i2c_devs[i]->type);
                } else
index fc13cbb..abb6075 100644 (file)
@@ -167,9 +167,10 @@ static struct irq_domain *uv_get_irq_domain(void)
                goto out;
 
        uv_domain = irq_domain_create_tree(fn, &uv_domain_ops, NULL);
-       irq_domain_free_fwnode(fn);
        if (uv_domain)
                uv_domain->parent = x86_vector_domain;
+       else
+               irq_domain_free_fwnode(fn);
 out:
        mutex_unlock(&uv_lock);
 
index 7c65102..db1378c 100644 (file)
@@ -193,6 +193,8 @@ static void fix_processor_context(void)
  */
 static void notrace __restore_processor_state(struct saved_context *ctxt)
 {
+       struct cpuinfo_x86 *c;
+
        if (ctxt->misc_enable_saved)
                wrmsrl(MSR_IA32_MISC_ENABLE, ctxt->misc_enable);
        /*
@@ -263,6 +265,10 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)
        mtrr_bp_restore();
        perf_restore_debug_store();
        msr_restore_context(ctxt);
+
+       c = &cpu_data(smp_processor_id());
+       if (cpu_has(c, X86_FEATURE_MSR_IA32_FEAT_CTL))
+               init_ia32_feat_ctl(c);
 }
 
 /* Needed by apm.c */
index b04e6e7..088bd76 100644 (file)
@@ -34,6 +34,7 @@ KCOV_INSTRUMENT := n
 PURGATORY_CFLAGS_REMOVE := -mcmodel=kernel
 PURGATORY_CFLAGS := -mcmodel=large -ffreestanding -fno-zero-initialized-in-bss
 PURGATORY_CFLAGS += $(DISABLE_STACKLEAK_PLUGIN) -DDISABLE_BRANCH_PROFILING
+PURGATORY_CFLAGS += $(call cc-option,-fno-stack-protector)
 
 # Default KBUILD_CFLAGS can have -pg option set when FTRACE is enabled. That
 # in turn leaves some undefined symbols like __fentry__ in purgatory and not
index 33b309d..c46b9f2 100644 (file)
@@ -386,7 +386,7 @@ static void set_aliased_prot(void *v, pgprot_t prot)
 
        preempt_disable();
 
-       probe_kernel_read(&dummy, v, 1);
+       copy_from_kernel_nofault(&dummy, v, 1);
 
        if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0))
                BUG();
@@ -598,6 +598,26 @@ static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum,
 }
 
 #ifdef CONFIG_X86_64
+void noist_exc_debug(struct pt_regs *regs);
+
+DEFINE_IDTENTRY_RAW(xenpv_exc_nmi)
+{
+       /* On Xen PV, NMI doesn't use IST.  The C part is the sane as native. */
+       exc_nmi(regs);
+}
+
+DEFINE_IDTENTRY_RAW(xenpv_exc_debug)
+{
+       /*
+        * There's no IST on Xen PV, but we still need to dispatch
+        * to the correct handler.
+        */
+       if (user_mode(regs))
+               noist_exc_debug(regs);
+       else
+               exc_debug(regs);
+}
+
 struct trap_array_entry {
        void (*orig)(void);
        void (*xen)(void);
@@ -609,18 +629,18 @@ struct trap_array_entry {
        .xen            = xen_asm_##func,               \
        .ist_okay       = ist_ok }
 
-#define TRAP_ENTRY_REDIR(func, xenfunc, ist_ok) {      \
+#define TRAP_ENTRY_REDIR(func, ist_ok) {               \
        .orig           = asm_##func,                   \
-       .xen            = xen_asm_##xenfunc,            \
+       .xen            = xen_asm_xenpv_##func,         \
        .ist_okay       = ist_ok }
 
 static struct trap_array_entry trap_array[] = {
-       TRAP_ENTRY_REDIR(exc_debug, exc_xendebug,       true  ),
+       TRAP_ENTRY_REDIR(exc_debug,                     true  ),
        TRAP_ENTRY(exc_double_fault,                    true  ),
 #ifdef CONFIG_X86_MCE
        TRAP_ENTRY(exc_machine_check,                   true  ),
 #endif
-       TRAP_ENTRY_REDIR(exc_nmi, exc_xennmi,           true  ),
+       TRAP_ENTRY_REDIR(exc_nmi,                       true  ),
        TRAP_ENTRY(exc_int3,                            false ),
        TRAP_ENTRY(exc_overflow,                        false ),
 #ifdef CONFIG_IA32_EMULATION
@@ -850,6 +870,17 @@ static void xen_load_sp0(unsigned long sp0)
 }
 
 #ifdef CONFIG_X86_IOPL_IOPERM
+static void xen_invalidate_io_bitmap(void)
+{
+       struct physdev_set_iobitmap iobitmap = {
+               .bitmap = 0,
+               .nr_ports = 0,
+       };
+
+       native_tss_invalidate_io_bitmap();
+       HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, &iobitmap);
+}
+
 static void xen_update_io_bitmap(void)
 {
        struct physdev_set_iobitmap iobitmap;
@@ -1079,6 +1110,7 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
        .load_sp0 = xen_load_sp0,
 
 #ifdef CONFIG_X86_IOPL_IOPERM
+       .invalidate_io_bitmap = xen_invalidate_io_bitmap,
        .update_io_bitmap = xen_update_io_bitmap,
 #endif
        .io_delay = xen_io_delay,
index 5d252aa..aab1d99 100644 (file)
@@ -29,10 +29,9 @@ _ASM_NOKPROBE(xen_\name)
 .endm
 
 xen_pv_trap asm_exc_divide_error
-xen_pv_trap asm_exc_debug
-xen_pv_trap asm_exc_xendebug
+xen_pv_trap asm_xenpv_exc_debug
 xen_pv_trap asm_exc_int3
-xen_pv_trap asm_exc_xennmi
+xen_pv_trap asm_xenpv_exc_nmi
 xen_pv_trap asm_exc_overflow
 xen_pv_trap asm_exc_bounds
 xen_pv_trap asm_exc_invalid_op
@@ -161,10 +160,22 @@ SYM_FUNC_END(xen_syscall32_target)
 
 /* 32-bit compat sysenter target */
 SYM_FUNC_START(xen_sysenter_target)
-       mov 0*8(%rsp), %rcx
-       mov 1*8(%rsp), %r11
-       mov 5*8(%rsp), %rsp
-       jmp entry_SYSENTER_compat
+       /*
+        * NB: Xen is polite and clears TF from EFLAGS for us.  This means
+        * that we don't need to guard against single step exceptions here.
+        */
+       popq %rcx
+       popq %r11
+
+       /*
+        * Neither Xen nor the kernel really knows what the old SS and
+        * CS were.  The kernel expects __USER32_DS and __USER32_CS, so
+        * report those values even though Xen will guess its own values.
+        */
+       movq $__USER32_DS, 4*8(%rsp)
+       movq $__USER32_CS, 1*8(%rsp)
+
+       jmp entry_SYSENTER_compat_after_hwframe
 SYM_FUNC_END(xen_sysenter_target)
 
 #else /* !CONFIG_IA32_EMULATION */
index d8292cc..243a5fe 100644 (file)
@@ -57,7 +57,7 @@ static inline
 __wsum csum_and_copy_from_user(const void __user *src, void *dst,
                                   int len, __wsum sum, int *err_ptr)
 {
-       if (access_ok(dst, len))
+       if (access_ok(src, len))
                return csum_partial_copy_generic((__force const void *)src, dst,
                                        len, sum, err_ptr, NULL);
        if (len)
index 9bae79f..99fcd63 100644 (file)
@@ -362,9 +362,7 @@ irqreturn_t xtensa_pmu_irq_handler(int irq, void *dev_id)
        struct xtensa_pmu_events *ev = this_cpu_ptr(&xtensa_pmu_events);
        unsigned i;
 
-       for (i = find_first_bit(ev->used_mask, XCHAL_NUM_PERF_COUNTERS);
-            i < XCHAL_NUM_PERF_COUNTERS;
-            i = find_next_bit(ev->used_mask, XCHAL_NUM_PERF_COUNTERS, i + 1)) {
+       for_each_set_bit(i, ev->used_mask, XCHAL_NUM_PERF_COUNTERS) {
                uint32_t v = get_er(XTENSA_PMU_PMSTAT(i));
                struct perf_event *event = ev->event[i];
                struct hw_perf_event *hwc = &event->hw;
index d9204dc..be2c78f 100644 (file)
@@ -724,7 +724,8 @@ c_start(struct seq_file *f, loff_t *pos)
 static void *
 c_next(struct seq_file *f, void *v, loff_t *pos)
 {
-       return NULL;
+       ++*pos;
+       return c_start(f, pos);
 }
 
 static void
index 4092555..24cf697 100644 (file)
@@ -87,13 +87,13 @@ void __xtensa_libgcc_window_spill(void)
 }
 EXPORT_SYMBOL(__xtensa_libgcc_window_spill);
 
-unsigned long __sync_fetch_and_and_4(unsigned long *p, unsigned long v)
+unsigned int __sync_fetch_and_and_4(volatile void *p, unsigned int v)
 {
        BUG();
 }
 EXPORT_SYMBOL(__sync_fetch_and_and_4);
 
-unsigned long __sync_fetch_and_or_4(unsigned long *p, unsigned long v)
+unsigned int __sync_fetch_and_or_4(volatile void *p, unsigned int v)
 {
        BUG();
 }
index 23632a3..9ffd7e2 100644 (file)
@@ -24,6 +24,19 @@ void blk_flush_integrity(void)
        flush_workqueue(kintegrityd_wq);
 }
 
+static void __bio_integrity_free(struct bio_set *bs,
+                                struct bio_integrity_payload *bip)
+{
+       if (bs && mempool_initialized(&bs->bio_integrity_pool)) {
+               if (bip->bip_vec)
+                       bvec_free(&bs->bvec_integrity_pool, bip->bip_vec,
+                                 bip->bip_slab);
+               mempool_free(bip, &bs->bio_integrity_pool);
+       } else {
+               kfree(bip);
+       }
+}
+
 /**
  * bio_integrity_alloc - Allocate integrity payload and attach it to bio
  * @bio:       bio to attach integrity metadata to
@@ -78,7 +91,7 @@ struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
 
        return bip;
 err:
-       mempool_free(bip, &bs->bio_integrity_pool);
+       __bio_integrity_free(bs, bip);
        return ERR_PTR(-ENOMEM);
 }
 EXPORT_SYMBOL(bio_integrity_alloc);
@@ -99,14 +112,7 @@ void bio_integrity_free(struct bio *bio)
                kfree(page_address(bip->bip_vec->bv_page) +
                      bip->bip_vec->bv_offset);
 
-       if (bs && mempool_initialized(&bs->bio_integrity_pool)) {
-               bvec_free(&bs->bvec_integrity_pool, bip->bip_vec, bip->bip_slab);
-
-               mempool_free(bip, &bs->bio_integrity_pool);
-       } else {
-               kfree(bip);
-       }
-
+       __bio_integrity_free(bs, bip);
        bio->bi_integrity = NULL;
        bio->bi_opf &= ~REQ_INTEGRITY;
 }
index 15df3a3..e0b2bc1 100644 (file)
@@ -125,6 +125,9 @@ static const char *const blk_queue_flag_name[] = {
        QUEUE_FLAG_NAME(REGISTERED),
        QUEUE_FLAG_NAME(SCSI_PASSTHROUGH),
        QUEUE_FLAG_NAME(QUIESCED),
+       QUEUE_FLAG_NAME(PCI_P2PDMA),
+       QUEUE_FLAG_NAME(ZONE_RESETALL),
+       QUEUE_FLAG_NAME(RQ_ALLOC_TIME),
 };
 #undef QUEUE_FLAG_NAME
 
index 44f3d09..ae722f8 100644 (file)
@@ -376,7 +376,7 @@ static void __blk_mq_all_tag_iter(struct blk_mq_tags *tags,
 void blk_mq_all_tag_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn,
                void *priv)
 {
-       return __blk_mq_all_tag_iter(tags, fn, priv, BT_TAG_ITER_STATIC_RQS);
+       __blk_mq_all_tag_iter(tags, fn, priv, BT_TAG_ITER_STATIC_RQS);
 }
 
 /**
index 4f57d27..4e0d173 100644 (file)
@@ -828,10 +828,10 @@ static bool blk_mq_rq_inflight(struct blk_mq_hw_ctx *hctx, struct request *rq,
                               void *priv, bool reserved)
 {
        /*
-        * If we find a request that is inflight and the queue matches,
+        * If we find a request that isn't idle and the queue matches,
         * we know the queue is busy. Return false to stop the iteration.
         */
-       if (rq->state == MQ_RQ_IN_FLIGHT && rq->q == hctx->queue) {
+       if (blk_mq_request_started(rq) && rq->q == hctx->queue) {
                bool *busy = priv;
 
                *busy = true;
@@ -3479,7 +3479,9 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
 
        if (set->nr_maps == 1 && nr_hw_queues > nr_cpu_ids)
                nr_hw_queues = nr_cpu_ids;
-       if (nr_hw_queues < 1 || nr_hw_queues == set->nr_hw_queues)
+       if (nr_hw_queues < 1)
+               return;
+       if (set->nr_maps == 1 && nr_hw_queues == set->nr_hw_queues)
                return;
 
        list_for_each_entry(q, &set->tag_list, tag_set_list)
index c2ef41b..35abcb1 100644 (file)
@@ -374,8 +374,7 @@ void blk_ksm_destroy(struct blk_keyslot_manager *ksm)
        if (!ksm)
                return;
        kvfree(ksm->slot_hashtable);
-       memzero_explicit(ksm->slots, sizeof(ksm->slots[0]) * ksm->num_slots);
-       kvfree(ksm->slots);
+       kvfree_sensitive(ksm->slots, sizeof(ksm->slots[0]) * ksm->num_slots);
        memzero_explicit(ksm, sizeof(*ksm));
 }
 EXPORT_SYMBOL_GPL(blk_ksm_destroy);
index 6fdfcb4..d333786 100644 (file)
@@ -910,7 +910,7 @@ static bool ldm_parse_dsk4 (const u8 *buffer, int buflen, struct vblk *vb)
                return false;
 
        disk = &vb->vblk.disk;
-       uuid_copy(&disk->disk_id, (uuid_t *)(buffer + 0x18 + r_name));
+       import_uuid(&disk->disk_id, buffer + 0x18 + r_name);
        return true;
 }
 
index 841580a..d8d6bea 100644 (file)
@@ -93,7 +93,7 @@ struct frag {                         /* VBLK Fragment handling */
        u8              num;            /* Total number of records */
        u8              rec;            /* This is record number n */
        u8              map;            /* Which portions are in use */
-       u8              data[0];
+       u8              data[];
 };
 
 /* In memory LDM database structures. */
index b1cd353..28fc323 100644 (file)
@@ -128,21 +128,15 @@ EXPORT_SYMBOL_GPL(af_alg_release);
 void af_alg_release_parent(struct sock *sk)
 {
        struct alg_sock *ask = alg_sk(sk);
-       unsigned int nokey = ask->nokey_refcnt;
-       bool last = nokey && !ask->refcnt;
+       unsigned int nokey = atomic_read(&ask->nokey_refcnt);
 
        sk = ask->parent;
        ask = alg_sk(sk);
 
-       local_bh_disable();
-       bh_lock_sock(sk);
-       ask->nokey_refcnt -= nokey;
-       if (!last)
-               last = !--ask->refcnt;
-       bh_unlock_sock(sk);
-       local_bh_enable();
+       if (nokey)
+               atomic_dec(&ask->nokey_refcnt);
 
-       if (last)
+       if (atomic_dec_and_test(&ask->refcnt))
                sock_put(sk);
 }
 EXPORT_SYMBOL_GPL(af_alg_release_parent);
@@ -187,7 +181,7 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 
        err = -EBUSY;
        lock_sock(sk);
-       if (ask->refcnt | ask->nokey_refcnt)
+       if (atomic_read(&ask->refcnt))
                goto unlock;
 
        swap(ask->type, type);
@@ -236,7 +230,7 @@ static int alg_setsockopt(struct socket *sock, int level, int optname,
        int err = -EBUSY;
 
        lock_sock(sk);
-       if (ask->refcnt)
+       if (atomic_read(&ask->refcnt) != atomic_read(&ask->nokey_refcnt))
                goto unlock;
 
        type = ask->type;
@@ -301,12 +295,14 @@ int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern)
        if (err)
                goto unlock;
 
-       if (nokey || !ask->refcnt++)
+       if (atomic_inc_return_relaxed(&ask->refcnt) == 1)
                sock_hold(sk);
-       ask->nokey_refcnt += nokey;
+       if (nokey) {
+               atomic_inc(&ask->nokey_refcnt);
+               atomic_set(&alg_sk(sk2)->nokey_refcnt, 1);
+       }
        alg_sk(sk2)->parent = sk;
        alg_sk(sk2)->type = type;
-       alg_sk(sk2)->nokey_refcnt = nokey;
 
        newsock->ops = type->ops;
        newsock->state = SS_CONNECTED;
index 535f1f8..5ebccbd 100644 (file)
@@ -178,8 +178,6 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval)
        if (IS_ERR(thread))
                goto err_put_larval;
 
-       wait_for_completion_interruptible(&larval->completion);
-
        return NOTIFY_STOP;
 
 err_put_larval:
index eb1910b..0ae000a 100644 (file)
@@ -384,7 +384,7 @@ static int aead_check_key(struct socket *sock)
        struct alg_sock *ask = alg_sk(sk);
 
        lock_sock(sk);
-       if (ask->refcnt)
+       if (!atomic_read(&ask->nokey_refcnt))
                goto unlock_child;
 
        psk = ask->parent;
@@ -396,11 +396,8 @@ static int aead_check_key(struct socket *sock)
        if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY)
                goto unlock;
 
-       if (!pask->refcnt++)
-               sock_hold(psk);
-
-       ask->refcnt = 1;
-       sock_put(psk);
+       atomic_dec(&pask->nokey_refcnt);
+       atomic_set(&ask->nokey_refcnt, 0);
 
        err = 0;
 
index da1ffa4..e71727c 100644 (file)
@@ -301,7 +301,7 @@ static int hash_check_key(struct socket *sock)
        struct alg_sock *ask = alg_sk(sk);
 
        lock_sock(sk);
-       if (ask->refcnt)
+       if (!atomic_read(&ask->nokey_refcnt))
                goto unlock_child;
 
        psk = ask->parent;
@@ -313,11 +313,8 @@ static int hash_check_key(struct socket *sock)
        if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
                goto unlock;
 
-       if (!pask->refcnt++)
-               sock_hold(psk);
-
-       ask->refcnt = 1;
-       sock_put(psk);
+       atomic_dec(&pask->nokey_refcnt);
+       atomic_set(&ask->nokey_refcnt, 0);
 
        err = 0;
 
index e2c8ab4..ec5567c 100644 (file)
@@ -74,14 +74,10 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
                return PTR_ERR(areq);
 
        /* convert iovecs of output buffers into RX SGL */
-       err = af_alg_get_rsgl(sk, msg, flags, areq, -1, &len);
+       err = af_alg_get_rsgl(sk, msg, flags, areq, ctx->used, &len);
        if (err)
                goto free;
 
-       /* Process only as much RX buffers for which we have TX data */
-       if (len > ctx->used)
-               len = ctx->used;
-
        /*
         * If more buffers are to be expected to be processed, process only
         * full block size buffers.
@@ -215,7 +211,7 @@ static int skcipher_check_key(struct socket *sock)
        struct alg_sock *ask = alg_sk(sk);
 
        lock_sock(sk);
-       if (ask->refcnt)
+       if (!atomic_read(&ask->nokey_refcnt))
                goto unlock_child;
 
        psk = ask->parent;
@@ -227,11 +223,8 @@ static int skcipher_check_key(struct socket *sock)
        if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
                goto unlock;
 
-       if (!pask->refcnt++)
-               sock_hold(psk);
-
-       ask->refcnt = 1;
-       sock_put(psk);
+       atomic_dec(&pask->nokey_refcnt);
+       atomic_set(&ask->nokey_refcnt, 0);
 
        err = 0;
 
index d7f43d4..e5fae4e 100644 (file)
@@ -119,6 +119,7 @@ static int software_key_query(const struct kernel_pkey_params *params,
        if (IS_ERR(tfm))
                return PTR_ERR(tfm);
 
+       ret = -ENOMEM;
        key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
                      GFP_KERNEL);
        if (!key)
index 37526eb..8d80d93 100644 (file)
@@ -1631,10 +1631,12 @@ static int drbg_uninstantiate(struct drbg_state *drbg)
        if (drbg->random_ready.func) {
                del_random_ready_callback(&drbg->random_ready);
                cancel_work_sync(&drbg->seed_work);
-               crypto_free_rng(drbg->jent);
-               drbg->jent = NULL;
        }
 
+       if (!IS_ERR_OR_NULL(drbg->jent))
+               crypto_free_rng(drbg->jent);
+       drbg->jent = NULL;
+
        if (drbg->d_ops)
                drbg->d_ops->crypto_fini(drbg);
        drbg_dealloc_state(drbg);
index ece8c1a..88c8af4 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/configfs.h>
 #include <linux/acpi.h>
+#include <linux/security.h>
 
 #include "acpica/accommon.h"
 #include "acpica/actables.h"
@@ -28,7 +29,10 @@ static ssize_t acpi_table_aml_write(struct config_item *cfg,
 {
        const struct acpi_table_header *header = data;
        struct acpi_table *table;
-       int ret;
+       int ret = security_locked_down(LOCKDOWN_ACPI_TABLES);
+
+       if (ret)
+               return ret;
 
        table = container_of(cfg, struct acpi_table, cfg);
 
index 5fab7e3..92b996a 100644 (file)
@@ -228,6 +228,7 @@ static const struct acpi_device_id int3407_device_ids[] = {
        {"INT3407", 0},
        {"INT3532", 0},
        {"INTC1047", 0},
+       {"INTC1050", 0},
        {"", 0},
 };
 MODULE_DEVICE_TABLE(acpi, int3407_device_ids);
index 873e039..6287338 100644 (file)
@@ -25,8 +25,8 @@ static int acpi_fan_remove(struct platform_device *pdev);
 
 static const struct acpi_device_id fan_device_ids[] = {
        {"PNP0C0B", 0},
-       {"INT1044", 0},
        {"INT3404", 0},
+       {"INTC1044", 0},
        {"", 0},
 };
 MODULE_DEVICE_TABLE(acpi, fan_device_ids);
index 3a89909..76c668c 100644 (file)
@@ -938,13 +938,13 @@ static void __exit interrupt_stats_exit(void)
 }
 
 static ssize_t
-acpi_show_profile(struct device *dev, struct device_attribute *attr,
+acpi_show_profile(struct kobject *kobj, struct kobj_attribute *attr,
                  char *buf)
 {
        return sprintf(buf, "%d\n", acpi_gbl_FADT.preferred_profile);
 }
 
-static const struct device_attribute pm_profile_attr =
+static const struct kobj_attribute pm_profile_attr =
        __ATTR(pm_profile, S_IRUGO, acpi_show_profile, NULL);
 
 static ssize_t hotplug_enabled_show(struct kobject *kobj,
index 57d3b2e..0b2c20f 100644 (file)
@@ -120,7 +120,7 @@ static const u32 tegra_ahb_gizmo[] = {
 struct tegra_ahb {
        void __iomem    *regs;
        struct device   *dev;
-       u32             ctx[0];
+       u32             ctx[];
 };
 
 static inline u32 gizmo_readl(struct tegra_ahb *ahb, u32 offset)
index e47c8a4..f50c5f1 100644 (file)
@@ -4686,8 +4686,15 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc)
 
 static void binder_free_proc(struct binder_proc *proc)
 {
+       struct binder_device *device;
+
        BUG_ON(!list_empty(&proc->todo));
        BUG_ON(!list_empty(&proc->delivered_death));
+       device = container_of(proc->context, struct binder_device, context);
+       if (refcount_dec_and_test(&device->ref)) {
+               kfree(proc->context->name);
+               kfree(device);
+       }
        binder_alloc_deferred_release(&proc->alloc);
        put_task_struct(proc->tsk);
        binder_stats_deleted(BINDER_STAT_PROC);
@@ -5406,7 +5413,6 @@ static int binder_node_release(struct binder_node *node, int refs)
 static void binder_deferred_release(struct binder_proc *proc)
 {
        struct binder_context *context = proc->context;
-       struct binder_device *device;
        struct rb_node *n;
        int threads, nodes, incoming_refs, outgoing_refs, active_transactions;
 
@@ -5423,12 +5429,6 @@ static void binder_deferred_release(struct binder_proc *proc)
                context->binder_context_mgr_node = NULL;
        }
        mutex_unlock(&context->context_mgr_node_lock);
-       device = container_of(proc->context, struct binder_device, context);
-       if (refcount_dec_and_test(&device->ref)) {
-               kfree(context->name);
-               kfree(device);
-       }
-       proc->context = NULL;
        binder_inner_proc_lock(proc);
        /*
         * Make sure proc stays alive after we
index 42c672f..cbe6aa7 100644 (file)
@@ -947,7 +947,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
                trace_binder_unmap_user_end(alloc, index);
        }
        mmap_read_unlock(mm);
-       mmput(mm);
+       mmput_async(mm);
 
        trace_binder_unmap_kernel_start(alloc, index);
 
index 69361ec..b1cd4d9 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/workqueue.h>
 #include <linux/scatterlist.h>
 #include <linux/io.h>
-#include <linux/async.h>
 #include <linux/log2.h>
 #include <linux/slab.h>
 #include <linux/glob.h>
@@ -5778,7 +5777,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
        /* perform each probe asynchronously */
        for (i = 0; i < host->n_ports; i++) {
                struct ata_port *ap = host->ports[i];
-               async_schedule(async_port_probe, ap);
+               ap->cookie = async_schedule(async_port_probe, ap);
        }
 
        return 0;
@@ -5920,11 +5919,11 @@ void ata_host_detach(struct ata_host *host)
 {
        int i;
 
-       /* Ensure ata_port probe has completed */
-       async_synchronize_full();
-
-       for (i = 0; i < host->n_ports; i++)
+       for (i = 0; i < host->n_ports; i++) {
+               /* Ensure ata_port probe has completed */
+               async_synchronize_cookie(host->ports[i]->cookie + 1);
                ata_port_detach(host->ports[i]);
+       }
 
        /* the host is dead now, dissociate ACPI */
        ata_acpi_dissociate(host);
index 435781a..4633608 100644 (file)
@@ -3684,12 +3684,13 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc)
 {
        struct scsi_cmnd *scmd = qc->scsicmd;
        const u8 *cdb = scmd->cmnd;
-       const u8 *p;
        u8 pg, spg;
        unsigned six_byte, pg_len, hdr_len, bd_len;
        int len;
        u16 fp = (u16)-1;
        u8 bp = 0xff;
+       u8 buffer[64];
+       const u8 *p = buffer;
 
        VPRINTK("ENTER\n");
 
@@ -3723,12 +3724,14 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc)
        if (!scsi_sg_count(scmd) || scsi_sglist(scmd)->length < len)
                goto invalid_param_len;
 
-       p = page_address(sg_page(scsi_sglist(scmd)));
-
        /* Move past header and block descriptors.  */
        if (len < hdr_len)
                goto invalid_param_len;
 
+       if (!sg_copy_to_buffer(scsi_sglist(scmd), scsi_sg_count(scmd),
+                              buffer, sizeof(buffer)))
+               goto invalid_param_len;
+
        if (six_byte)
                bd_len = p[3];
        else
index 980aacd..141ac60 100644 (file)
@@ -907,7 +907,7 @@ static int sata_rcar_probe(struct platform_device *pdev)
        pm_runtime_enable(dev);
        ret = pm_runtime_get_sync(dev);
        if (ret < 0)
-               goto err_pm_disable;
+               goto err_pm_put;
 
        host = ata_host_alloc(dev, 1);
        if (!host) {
@@ -937,7 +937,6 @@ static int sata_rcar_probe(struct platform_device *pdev)
 
 err_pm_put:
        pm_runtime_put(dev);
-err_pm_disable:
        pm_runtime_disable(dev);
        return ret;
 }
@@ -991,8 +990,10 @@ static int sata_rcar_resume(struct device *dev)
        int ret;
 
        ret = pm_runtime_get_sync(dev);
-       if (ret < 0)
+       if (ret < 0) {
+               pm_runtime_put(dev);
                return ret;
+       }
 
        if (priv->type == RCAR_GEN3_SATA) {
                sata_rcar_init_module(priv);
@@ -1017,8 +1018,10 @@ static int sata_rcar_restore(struct device *dev)
        int ret;
 
        ret = pm_runtime_get_sync(dev);
-       if (ret < 0)
+       if (ret < 0) {
+               pm_runtime_put(dev);
                return ret;
+       }
 
        sata_rcar_setup_port(host);
 
index 95c22c0..40fb069 100644 (file)
@@ -153,7 +153,6 @@ extern char *make_class_name(const char *name, struct kobject *kobj);
 extern int devres_release_all(struct device *dev);
 extern void device_block_probing(void);
 extern void device_unblock_probing(void);
-extern void driver_deferred_probe_force_trigger(void);
 
 /* /sys/devices directory */
 extern struct kset *devices_kset;
index 67d39a9..05d414e 100644 (file)
@@ -50,6 +50,7 @@ static DEFINE_MUTEX(wfs_lock);
 static LIST_HEAD(deferred_sync);
 static unsigned int defer_sync_state_count = 1;
 static unsigned int defer_fw_devlink_count;
+static LIST_HEAD(deferred_fw_devlink);
 static DEFINE_MUTEX(defer_fw_devlink_lock);
 static bool fw_devlink_is_permissive(void);
 
@@ -754,11 +755,11 @@ static void __device_links_queue_sync_state(struct device *dev,
         */
        dev->state_synced = true;
 
-       if (WARN_ON(!list_empty(&dev->links.defer_sync)))
+       if (WARN_ON(!list_empty(&dev->links.defer_hook)))
                return;
 
        get_device(dev);
-       list_add_tail(&dev->links.defer_sync, list);
+       list_add_tail(&dev->links.defer_hook, list);
 }
 
 /**
@@ -776,8 +777,8 @@ static void device_links_flush_sync_list(struct list_head *list,
 {
        struct device *dev, *tmp;
 
-       list_for_each_entry_safe(dev, tmp, list, links.defer_sync) {
-               list_del_init(&dev->links.defer_sync);
+       list_for_each_entry_safe(dev, tmp, list, links.defer_hook) {
+               list_del_init(&dev->links.defer_hook);
 
                if (dev != dont_lock_dev)
                        device_lock(dev);
@@ -815,12 +816,12 @@ void device_links_supplier_sync_state_resume(void)
        if (defer_sync_state_count)
                goto out;
 
-       list_for_each_entry_safe(dev, tmp, &deferred_sync, links.defer_sync) {
+       list_for_each_entry_safe(dev, tmp, &deferred_sync, links.defer_hook) {
                /*
                 * Delete from deferred_sync list before queuing it to
-                * sync_list because defer_sync is used for both lists.
+                * sync_list because defer_hook is used for both lists.
                 */
-               list_del_init(&dev->links.defer_sync);
+               list_del_init(&dev->links.defer_hook);
                __device_links_queue_sync_state(dev, &sync_list);
        }
 out:
@@ -838,8 +839,8 @@ late_initcall(sync_state_resume_initcall);
 
 static void __device_links_supplier_defer_sync(struct device *sup)
 {
-       if (list_empty(&sup->links.defer_sync) && dev_has_sync_state(sup))
-               list_add_tail(&sup->links.defer_sync, &deferred_sync);
+       if (list_empty(&sup->links.defer_hook) && dev_has_sync_state(sup))
+               list_add_tail(&sup->links.defer_hook, &deferred_sync);
 }
 
 static void device_link_drop_managed(struct device_link *link)
@@ -1052,7 +1053,7 @@ void device_links_driver_cleanup(struct device *dev)
                WRITE_ONCE(link->status, DL_STATE_DORMANT);
        }
 
-       list_del_init(&dev->links.defer_sync);
+       list_del_init(&dev->links.defer_hook);
        __device_links_no_driver(dev);
 
        device_links_write_unlock();
@@ -1244,6 +1245,12 @@ static void fw_devlink_link_device(struct device *dev)
                        fw_ret = -EAGAIN;
        } else {
                fw_ret = -ENODEV;
+               /*
+                * defer_hook is not used to add device to deferred_sync list
+                * until device is bound. Since deferred fw devlink also blocks
+                * probing, same list hook can be used for deferred_fw_devlink.
+                */
+               list_add_tail(&dev->links.defer_hook, &deferred_fw_devlink);
        }
 
        if (fw_ret == -ENODEV)
@@ -1312,6 +1319,9 @@ void fw_devlink_pause(void)
  */
 void fw_devlink_resume(void)
 {
+       struct device *dev, *tmp;
+       LIST_HEAD(probe_list);
+
        mutex_lock(&defer_fw_devlink_lock);
        if (!defer_fw_devlink_count) {
                WARN(true, "Unmatched fw_devlink pause/resume!");
@@ -1323,9 +1333,19 @@ void fw_devlink_resume(void)
                goto out;
 
        device_link_add_missing_supplier_links();
-       driver_deferred_probe_force_trigger();
+       list_splice_tail_init(&deferred_fw_devlink, &probe_list);
 out:
        mutex_unlock(&defer_fw_devlink_lock);
+
+       /*
+        * bus_probe_device() can cause new devices to get added and they'll
+        * try to grab defer_fw_devlink_lock. So, this needs to be done outside
+        * the defer_fw_devlink_lock.
+        */
+       list_for_each_entry_safe(dev, tmp, &probe_list, links.defer_hook) {
+               list_del_init(&dev->links.defer_hook);
+               bus_probe_device(dev);
+       }
 }
 /* Device links support end. */
 
@@ -2172,7 +2192,7 @@ void device_initialize(struct device *dev)
        INIT_LIST_HEAD(&dev->links.consumers);
        INIT_LIST_HEAD(&dev->links.suppliers);
        INIT_LIST_HEAD(&dev->links.needs_suppliers);
-       INIT_LIST_HEAD(&dev->links.defer_sync);
+       INIT_LIST_HEAD(&dev->links.defer_hook);
        dev->links.status = DL_DEV_NO_DRIVER;
 }
 EXPORT_SYMBOL_GPL(device_initialize);
index 9a1d940..48ca81c 100644 (file)
@@ -164,11 +164,6 @@ static void driver_deferred_probe_trigger(void)
        if (!driver_deferred_probe_enable)
                return;
 
-       driver_deferred_probe_force_trigger();
-}
-
-void driver_deferred_probe_force_trigger(void)
-{
        /*
         * A successful probe means that all the devices in the pending list
         * should be triggered to be reprobed.  Move all the deferred devices
index 977d27b..a97f33d 100644 (file)
@@ -265,14 +265,14 @@ static struct notifier_block pm_trace_nb = {
        .notifier_call = pm_trace_notify,
 };
 
-static int early_resume_init(void)
+static int __init early_resume_init(void)
 {
        hash_value_early_read = read_magic_time();
        register_pm_notifier(&pm_trace_nb);
        return 0;
 }
 
-static int late_resume_init(void)
+static int __init late_resume_init(void)
 {
        unsigned int val = hash_value_early_read;
        unsigned int user, file, dev;
index 1e6d75e..d58aa98 100644 (file)
@@ -721,7 +721,7 @@ struct fwnode_handle *device_get_next_child_node(struct device *dev,
                return next;
 
        /* When no more children in primary, continue with secondary */
-       if (!IS_ERR_OR_NULL(fwnode->secondary))
+       if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary))
                next = fwnode_get_next_child_node(fwnode->secondary, child);
 
        return next;
index 0fd6f97..1d1d26b 100644 (file)
@@ -4,7 +4,7 @@
 # subsystems should select the appropriate symbols.
 
 config REGMAP
-       default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SCCB || REGMAP_I3C)
+       default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SCCB || REGMAP_I3C)
        select IRQ_DOMAIN if REGMAP_IRQ
        bool
 
index 089e5dc..f58baff 100644 (file)
@@ -463,29 +463,31 @@ static ssize_t regmap_cache_only_write_file(struct file *file,
 {
        struct regmap *map = container_of(file->private_data,
                                          struct regmap, cache_only);
-       ssize_t result;
-       bool was_enabled, require_sync = false;
+       bool new_val, require_sync = false;
        int err;
 
-       map->lock(map->lock_arg);
+       err = kstrtobool_from_user(user_buf, count, &new_val);
+       /* Ignore malforned data like debugfs_write_file_bool() */
+       if (err)
+               return count;
 
-       was_enabled = map->cache_only;
+       err = debugfs_file_get(file->f_path.dentry);
+       if (err)
+               return err;
 
-       result = debugfs_write_file_bool(file, user_buf, count, ppos);
-       if (result < 0) {
-               map->unlock(map->lock_arg);
-               return result;
-       }
+       map->lock(map->lock_arg);
 
-       if (map->cache_only && !was_enabled) {
+       if (new_val && !map->cache_only) {
                dev_warn(map->dev, "debugfs cache_only=Y forced\n");
                add_taint(TAINT_USER, LOCKDEP_STILL_OK);
-       } else if (!map->cache_only && was_enabled) {
+       } else if (!new_val && map->cache_only) {
                dev_warn(map->dev, "debugfs cache_only=N forced: syncing cache\n");
                require_sync = true;
        }
+       map->cache_only = new_val;
 
        map->unlock(map->lock_arg);
+       debugfs_file_put(file->f_path.dentry);
 
        if (require_sync) {
                err = regcache_sync(map);
@@ -493,7 +495,7 @@ static ssize_t regmap_cache_only_write_file(struct file *file,
                        dev_err(map->dev, "Failed to sync cache %d\n", err);
        }
 
-       return result;
+       return count;
 }
 
 static const struct file_operations regmap_cache_only_fops = {
@@ -508,28 +510,32 @@ static ssize_t regmap_cache_bypass_write_file(struct file *file,
 {
        struct regmap *map = container_of(file->private_data,
                                          struct regmap, cache_bypass);
-       ssize_t result;
-       bool was_enabled;
+       bool new_val;
+       int err;
 
-       map->lock(map->lock_arg);
+       err = kstrtobool_from_user(user_buf, count, &new_val);
+       /* Ignore malforned data like debugfs_write_file_bool() */
+       if (err)
+               return count;
 
-       was_enabled = map->cache_bypass;
+       err = debugfs_file_get(file->f_path.dentry);
+       if (err)
+               return err;
 
-       result = debugfs_write_file_bool(file, user_buf, count, ppos);
-       if (result < 0)
-               goto out;
+       map->lock(map->lock_arg);
 
-       if (map->cache_bypass && !was_enabled) {
+       if (new_val && !map->cache_bypass) {
                dev_warn(map->dev, "debugfs cache_bypass=Y forced\n");
                add_taint(TAINT_USER, LOCKDEP_STILL_OK);
-       } else if (!map->cache_bypass && was_enabled) {
+       } else if (!new_val && map->cache_bypass) {
                dev_warn(map->dev, "debugfs cache_bypass=N forced\n");
        }
+       map->cache_bypass = new_val;
 
-out:
        map->unlock(map->lock_arg);
+       debugfs_file_put(file->f_path.dentry);
 
-       return result;
+       return count;
 }
 
 static const struct file_operations regmap_cache_bypass_fops = {
index c472f62..795a62a 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <linux/log2.h>
 #include <linux/hwspinlock.h>
+#include <asm/unaligned.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace.h"
@@ -249,22 +250,20 @@ static void regmap_format_8(void *buf, unsigned int val, unsigned int shift)
 
 static void regmap_format_16_be(void *buf, unsigned int val, unsigned int shift)
 {
-       __be16 *b = buf;
-
-       b[0] = cpu_to_be16(val << shift);
+       put_unaligned_be16(val << shift, buf);
 }
 
 static void regmap_format_16_le(void *buf, unsigned int val, unsigned int shift)
 {
-       __le16 *b = buf;
-
-       b[0] = cpu_to_le16(val << shift);
+       put_unaligned_le16(val << shift, buf);
 }
 
 static void regmap_format_16_native(void *buf, unsigned int val,
                                    unsigned int shift)
 {
-       *(u16 *)buf = val << shift;
+       u16 v = val << shift;
+
+       memcpy(buf, &v, sizeof(v));
 }
 
 static void regmap_format_24(void *buf, unsigned int val, unsigned int shift)
@@ -280,43 +279,39 @@ static void regmap_format_24(void *buf, unsigned int val, unsigned int shift)
 
 static void regmap_format_32_be(void *buf, unsigned int val, unsigned int shift)
 {
-       __be32 *b = buf;
-
-       b[0] = cpu_to_be32(val << shift);
+       put_unaligned_be32(val << shift, buf);
 }
 
 static void regmap_format_32_le(void *buf, unsigned int val, unsigned int shift)
 {
-       __le32 *b = buf;
-
-       b[0] = cpu_to_le32(val << shift);
+       put_unaligned_le32(val << shift, buf);
 }
 
 static void regmap_format_32_native(void *buf, unsigned int val,
                                    unsigned int shift)
 {
-       *(u32 *)buf = val << shift;
+       u32 v = val << shift;
+
+       memcpy(buf, &v, sizeof(v));
 }
 
 #ifdef CONFIG_64BIT
 static void regmap_format_64_be(void *buf, unsigned int val, unsigned int shift)
 {
-       __be64 *b = buf;
-
-       b[0] = cpu_to_be64((u64)val << shift);
+       put_unaligned_be64((u64) val << shift, buf);
 }
 
 static void regmap_format_64_le(void *buf, unsigned int val, unsigned int shift)
 {
-       __le64 *b = buf;
-
-       b[0] = cpu_to_le64((u64)val << shift);
+       put_unaligned_le64((u64) val << shift, buf);
 }
 
 static void regmap_format_64_native(void *buf, unsigned int val,
                                    unsigned int shift)
 {
-       *(u64 *)buf = (u64)val << shift;
+       u64 v = (u64) val << shift;
+
+       memcpy(buf, &v, sizeof(v));
 }
 #endif
 
@@ -333,35 +328,34 @@ static unsigned int regmap_parse_8(const void *buf)
 
 static unsigned int regmap_parse_16_be(const void *buf)
 {
-       const __be16 *b = buf;
-
-       return be16_to_cpu(b[0]);
+       return get_unaligned_be16(buf);
 }
 
 static unsigned int regmap_parse_16_le(const void *buf)
 {
-       const __le16 *b = buf;
-
-       return le16_to_cpu(b[0]);
+       return get_unaligned_le16(buf);
 }
 
 static void regmap_parse_16_be_inplace(void *buf)
 {
-       __be16 *b = buf;
+       u16 v = get_unaligned_be16(buf);
 
-       b[0] = be16_to_cpu(b[0]);
+       memcpy(buf, &v, sizeof(v));
 }
 
 static void regmap_parse_16_le_inplace(void *buf)
 {
-       __le16 *b = buf;
+       u16 v = get_unaligned_le16(buf);
 
-       b[0] = le16_to_cpu(b[0]);
+       memcpy(buf, &v, sizeof(v));
 }
 
 static unsigned int regmap_parse_16_native(const void *buf)
 {
-       return *(u16 *)buf;
+       u16 v;
+
+       memcpy(&v, buf, sizeof(v));
+       return v;
 }
 
 static unsigned int regmap_parse_24(const void *buf)
@@ -376,69 +370,67 @@ static unsigned int regmap_parse_24(const void *buf)
 
 static unsigned int regmap_parse_32_be(const void *buf)
 {
-       const __be32 *b = buf;
-
-       return be32_to_cpu(b[0]);
+       return get_unaligned_be32(buf);
 }
 
 static unsigned int regmap_parse_32_le(const void *buf)
 {
-       const __le32 *b = buf;
-
-       return le32_to_cpu(b[0]);
+       return get_unaligned_le32(buf);
 }
 
 static void regmap_parse_32_be_inplace(void *buf)
 {
-       __be32 *b = buf;
+       u32 v = get_unaligned_be32(buf);
 
-       b[0] = be32_to_cpu(b[0]);
+       memcpy(buf, &v, sizeof(v));
 }
 
 static void regmap_parse_32_le_inplace(void *buf)
 {
-       __le32 *b = buf;
+       u32 v = get_unaligned_le32(buf);
 
-       b[0] = le32_to_cpu(b[0]);
+       memcpy(buf, &v, sizeof(v));
 }
 
 static unsigned int regmap_parse_32_native(const void *buf)
 {
-       return *(u32 *)buf;
+       u32 v;
+
+       memcpy(&v, buf, sizeof(v));
+       return v;
 }
 
 #ifdef CONFIG_64BIT
 static unsigned int regmap_parse_64_be(const void *buf)
 {
-       const __be64 *b = buf;
-
-       return be64_to_cpu(b[0]);
+       return get_unaligned_be64(buf);
 }
 
 static unsigned int regmap_parse_64_le(const void *buf)
 {
-       const __le64 *b = buf;
-
-       return le64_to_cpu(b[0]);
+       return get_unaligned_le64(buf);
 }
 
 static void regmap_parse_64_be_inplace(void *buf)
 {
-       __be64 *b = buf;
+       u64 v =  get_unaligned_be64(buf);
 
-       b[0] = be64_to_cpu(b[0]);
+       memcpy(buf, &v, sizeof(v));
 }
 
 static void regmap_parse_64_le_inplace(void *buf)
 {
-       __le64 *b = buf;
+       u64 v = get_unaligned_le64(buf);
 
-       b[0] = le64_to_cpu(b[0]);
+       memcpy(buf, &v, sizeof(v));
 }
 
 static unsigned int regmap_parse_64_native(const void *buf)
 {
-       return *(u64 *)buf;
+       u64 v;
+
+       memcpy(&v, buf, sizeof(v));
+       return v;
 }
 #endif
 
@@ -1357,6 +1349,7 @@ void regmap_exit(struct regmap *map)
        if (map->hwlock)
                hwspin_lock_free(map->hwlock);
        kfree_const(map->name);
+       kfree(map->patch);
        kfree(map);
 }
 EXPORT_SYMBOL_GPL(regmap_exit);
@@ -1371,7 +1364,7 @@ static int dev_get_regmap_match(struct device *dev, void *res, void *data)
 
        /* If the user didn't specify a name match any */
        if (data)
-               return (*r)->name == data;
+               return !strcmp((*r)->name, data);
        else
                return 1;
 }
@@ -2944,8 +2937,9 @@ EXPORT_SYMBOL_GPL(regmap_update_bits_base);
  * @reg: Register to read from
  * @bits: Bits to test
  *
- * Returns -1 if the underlying regmap_read() fails, 0 if at least one of the
- * tested bits is not set and 1 if all tested bits are set.
+ * Returns 0 if at least one of the tested bits is not set, 1 if all tested
+ * bits are set and a negative error number if the underlying regmap_read()
+ * fails.
  */
 int regmap_test_bits(struct regmap *map, unsigned int reg, unsigned int bits)
 {
index 14345a8..33d0831 100644 (file)
@@ -620,7 +620,7 @@ struct fifo_buffer {
        unsigned int head_index;
        unsigned int size;
        int total; /* sum of all values */
-       int values[0];
+       int values[];
 };
 extern struct fifo_buffer *fifo_alloc(unsigned int fifo_size);
 
index e6fc5ad..dea59c9 100644 (file)
@@ -271,7 +271,7 @@ struct p_rs_param {
        u32 resync_rate;
 
              /* Since protocol version 88 and higher. */
-       char verify_alg[0];
+       char verify_alg[];
 } __packed;
 
 struct p_rs_param_89 {
@@ -305,7 +305,7 @@ struct p_protocol {
        u32 two_primaries;
 
        /* Since protocol version 87 and higher. */
-       char integrity_alg[0];
+       char integrity_alg[];
 
 } __packed;
 
@@ -360,7 +360,7 @@ struct p_sizes {
        u16         dds_flags; /* use enum dds_flags here. */
 
        /* optional queue_limits if (agreed_features & DRBD_FF_WSAME) */
-       struct o_qlim qlim[0];
+       struct o_qlim qlim[];
 } __packed;
 
 struct p_state {
@@ -409,7 +409,7 @@ struct p_compressed_bm {
         */
        u8 encoding;
 
-       u8 code[0];
+       u8 code[];
 } __packed;
 
 struct p_delay_probe93 {
index c33bbbf..475e1a7 100644 (file)
@@ -1368,14 +1368,14 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
            lo->lo_sizelimit != info->lo_sizelimit) {
                size_changed = true;
                sync_blockdev(lo->lo_device);
-               kill_bdev(lo->lo_device);
+               invalidate_bdev(lo->lo_device);
        }
 
        /* I/O need to be drained during transfer transition */
        blk_mq_freeze_queue(lo->lo_queue);
 
        if (size_changed && lo->lo_device->bd_inode->i_mapping->nrpages) {
-               /* If any pages were dirtied after kill_bdev(), try again */
+               /* If any pages were dirtied after invalidate_bdev(), try again */
                err = -EAGAIN;
                pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n",
                        __func__, lo->lo_number, lo->lo_file_name,
@@ -1615,11 +1615,11 @@ static int loop_set_block_size(struct loop_device *lo, unsigned long arg)
                return 0;
 
        sync_blockdev(lo->lo_device);
-       kill_bdev(lo->lo_device);
+       invalidate_bdev(lo->lo_device);
 
        blk_mq_freeze_queue(lo->lo_queue);
 
-       /* kill_bdev should have truncated all the pages */
+       /* invalidate_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",
index 43cff01..ce7e9f2 100644 (file)
@@ -1033,25 +1033,26 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,
             test_bit(NBD_RT_BOUND, &config->runtime_flags))) {
                dev_err(disk_to_dev(nbd->disk),
                        "Device being setup by another task");
-               sockfd_put(sock);
-               return -EBUSY;
+               err = -EBUSY;
+               goto put_socket;
+       }
+
+       nsock = kzalloc(sizeof(*nsock), GFP_KERNEL);
+       if (!nsock) {
+               err = -ENOMEM;
+               goto put_socket;
        }
 
        socks = krealloc(config->socks, (config->num_connections + 1) *
                         sizeof(struct nbd_sock *), GFP_KERNEL);
        if (!socks) {
-               sockfd_put(sock);
-               return -ENOMEM;
+               kfree(nsock);
+               err = -ENOMEM;
+               goto put_socket;
        }
 
        config->socks = socks;
 
-       nsock = kzalloc(sizeof(struct nbd_sock), GFP_KERNEL);
-       if (!nsock) {
-               sockfd_put(sock);
-               return -ENOMEM;
-       }
-
        nsock->fallback_index = -1;
        nsock->dead = false;
        mutex_init(&nsock->tx_lock);
@@ -1063,6 +1064,10 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,
        atomic_inc(&config->live_connections);
 
        return 0;
+
+put_socket:
+       sockfd_put(sock);
+       return err;
 }
 
 static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg)
index 7420648..4f61e92 100644 (file)
@@ -1451,8 +1451,10 @@ static void rbd_osd_req_callback(struct ceph_osd_request *osd_req)
 static void rbd_osd_format_read(struct ceph_osd_request *osd_req)
 {
        struct rbd_obj_request *obj_request = osd_req->r_priv;
+       struct rbd_device *rbd_dev = obj_request->img_request->rbd_dev;
+       struct ceph_options *opt = rbd_dev->rbd_client->client->options;
 
-       osd_req->r_flags = CEPH_OSD_FLAG_READ;
+       osd_req->r_flags = CEPH_OSD_FLAG_READ | opt->read_from_replica;
        osd_req->r_snapid = obj_request->img_request->snap_id;
 }
 
index 9d21bf0..980df85 100644 (file)
@@ -878,6 +878,7 @@ out_put_disk:
        put_disk(vblk->disk);
 out_free_vq:
        vdev->config->del_vqs(vdev);
+       kfree(vblk->vqs);
 out_free_vblk:
        kfree(vblk);
 out_free_index:
index 6e2ad90..270dd81 100644 (file)
@@ -2021,7 +2021,8 @@ static ssize_t hot_add_show(struct class *class,
                return ret;
        return scnprintf(buf, PAGE_SIZE, "%d\n", ret);
 }
-static CLASS_ATTR_RO(hot_add);
+static struct class_attribute class_attr_hot_add =
+       __ATTR(hot_add, 0400, hot_add_show, NULL);
 
 static ssize_t hot_remove_store(struct class *class,
                        struct class_attribute *attr,
index 3affd18..191c97b 100644 (file)
@@ -221,6 +221,34 @@ static u32 sysc_read_sysstatus(struct sysc *ddata)
        return sysc_read(ddata, offset);
 }
 
+/* Poll on reset status */
+static int sysc_wait_softreset(struct sysc *ddata)
+{
+       u32 sysc_mask, syss_done, rstval;
+       int syss_offset, error = 0;
+
+       syss_offset = ddata->offsets[SYSC_SYSSTATUS];
+       sysc_mask = BIT(ddata->cap->regbits->srst_shift);
+
+       if (ddata->cfg.quirks & SYSS_QUIRK_RESETDONE_INVERTED)
+               syss_done = 0;
+       else
+               syss_done = ddata->cfg.syss_mask;
+
+       if (syss_offset >= 0) {
+               error = readx_poll_timeout_atomic(sysc_read_sysstatus, ddata,
+                               rstval, (rstval & ddata->cfg.syss_mask) ==
+                               syss_done, 100, MAX_MODULE_SOFTRESET_WAIT);
+
+       } else if (ddata->cfg.quirks & SYSC_QUIRK_RESET_STATUS) {
+               error = readx_poll_timeout_atomic(sysc_read_sysconfig, ddata,
+                               rstval, !(rstval & sysc_mask),
+                               100, MAX_MODULE_SOFTRESET_WAIT);
+       }
+
+       return error;
+}
+
 static int sysc_add_named_clock_from_child(struct sysc *ddata,
                                           const char *name,
                                           const char *optfck_name)
@@ -925,18 +953,47 @@ static int sysc_enable_module(struct device *dev)
        struct sysc *ddata;
        const struct sysc_regbits *regbits;
        u32 reg, idlemodes, best_mode;
+       int error;
 
        ddata = dev_get_drvdata(dev);
+
+       /*
+        * Some modules like DSS reset automatically on idle. Enable optional
+        * reset clocks and wait for OCP softreset to complete.
+        */
+       if (ddata->cfg.quirks & SYSC_QUIRK_OPT_CLKS_IN_RESET) {
+               error = sysc_enable_opt_clocks(ddata);
+               if (error) {
+                       dev_err(ddata->dev,
+                               "Optional clocks failed for enable: %i\n",
+                               error);
+                       return error;
+               }
+       }
+       error = sysc_wait_softreset(ddata);
+       if (error)
+               dev_warn(ddata->dev, "OCP softreset timed out\n");
+       if (ddata->cfg.quirks & SYSC_QUIRK_OPT_CLKS_IN_RESET)
+               sysc_disable_opt_clocks(ddata);
+
+       /*
+        * Some subsystem private interconnects, like DSS top level module,
+        * need only the automatic OCP softreset handling with no sysconfig
+        * register bits to configure.
+        */
        if (ddata->offsets[SYSC_SYSCONFIG] == -ENODEV)
                return 0;
 
        regbits = ddata->cap->regbits;
        reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]);
 
-       /* Set CLOCKACTIVITY, we only use it for ick */
+       /*
+        * Set CLOCKACTIVITY, we only use it for ick. And we only configure it
+        * based on the SYSC_QUIRK_USE_CLOCKACT flag, not based on the hardware
+        * capabilities. See the old HWMOD_SET_DEFAULT_CLOCKACT flag.
+        */
        if (regbits->clkact_shift >= 0 &&
-           (ddata->cfg.quirks & SYSC_QUIRK_USE_CLOCKACT ||
-            ddata->cfg.sysc_val & BIT(regbits->clkact_shift)))
+           (ddata->cfg.quirks & SYSC_QUIRK_USE_CLOCKACT))
                reg |= SYSC_CLOCACT_ICK << regbits->clkact_shift;
 
        /* Set SIDLE mode */
@@ -991,6 +1048,9 @@ set_autoidle:
                sysc_write_sysconfig(ddata, reg);
        }
 
+       /* Flush posted write */
+       sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]);
+
        if (ddata->module_enable_quirk)
                ddata->module_enable_quirk(ddata);
 
@@ -1071,6 +1131,9 @@ set_sidle:
                reg |= 1 << regbits->autoidle_shift;
        sysc_write_sysconfig(ddata, reg);
 
+       /* Flush posted write */
+       sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]);
+
        return 0;
 }
 
@@ -1215,7 +1278,8 @@ static int __maybe_unused sysc_noirq_suspend(struct device *dev)
 
        ddata = dev_get_drvdata(dev);
 
-       if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE)
+       if (ddata->cfg.quirks &
+           (SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_NO_IDLE))
                return 0;
 
        return pm_runtime_force_suspend(dev);
@@ -1227,7 +1291,8 @@ static int __maybe_unused sysc_noirq_resume(struct device *dev)
 
        ddata = dev_get_drvdata(dev);
 
-       if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE)
+       if (ddata->cfg.quirks &
+           (SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_NO_IDLE))
                return 0;
 
        return pm_runtime_force_resume(dev);
@@ -1488,7 +1553,7 @@ static u32 sysc_quirk_dispc(struct sysc *ddata, int dispc_offset,
        bool lcd_en, digit_en, lcd2_en = false, lcd3_en = false;
        const int lcd_en_mask = BIT(0), digit_en_mask = BIT(1);
        int manager_count;
-       bool framedonetv_irq;
+       bool framedonetv_irq = true;
        u32 val, irq_mask = 0;
 
        switch (sysc_soc->soc) {
@@ -1505,6 +1570,7 @@ static u32 sysc_quirk_dispc(struct sysc *ddata, int dispc_offset,
                break;
        case SOC_AM4:
                manager_count = 1;
+               framedonetv_irq = false;
                break;
        case SOC_UNKNOWN:
        default:
@@ -1663,8 +1729,8 @@ static void sysc_quirk_rtc(struct sysc *ddata, bool lock)
 
        local_irq_save(flags);
        /* RTC_STATUS BUSY bit may stay active for 1/32768 seconds (~30 usec) */
-       error = readl_poll_timeout(ddata->module_va + 0x44, val,
-                                  !(val & BIT(0)), 100, 50);
+       error = readl_poll_timeout_atomic(ddata->module_va + 0x44, val,
+                                         !(val & BIT(0)), 100, 50);
        if (error)
                dev_warn(ddata->dev, "rtc busy timeout\n");
        /* Now we have ~15 microseconds to read/write various registers */
@@ -1822,11 +1888,10 @@ static int sysc_legacy_init(struct sysc *ddata)
  */
 static int sysc_reset(struct sysc *ddata)
 {
-       int sysc_offset, syss_offset, sysc_val, rstval, error = 0;
-       u32 sysc_mask, syss_done;
+       int sysc_offset, sysc_val, error;
+       u32 sysc_mask;
 
        sysc_offset = ddata->offsets[SYSC_SYSCONFIG];
-       syss_offset = ddata->offsets[SYSC_SYSSTATUS];
 
        if (ddata->legacy_mode ||
            ddata->cap->regbits->srst_shift < 0 ||
@@ -1835,11 +1900,6 @@ static int sysc_reset(struct sysc *ddata)
 
        sysc_mask = BIT(ddata->cap->regbits->srst_shift);
 
-       if (ddata->cfg.quirks & SYSS_QUIRK_RESETDONE_INVERTED)
-               syss_done = 0;
-       else
-               syss_done = ddata->cfg.syss_mask;
-
        if (ddata->pre_reset_quirk)
                ddata->pre_reset_quirk(ddata);
 
@@ -1856,18 +1916,9 @@ static int sysc_reset(struct sysc *ddata)
        if (ddata->post_reset_quirk)
                ddata->post_reset_quirk(ddata);
 
-       /* Poll on reset status */
-       if (syss_offset >= 0) {
-               error = readx_poll_timeout(sysc_read_sysstatus, ddata, rstval,
-                                          (rstval & ddata->cfg.syss_mask) ==
-                                          syss_done,
-                                          100, MAX_MODULE_SOFTRESET_WAIT);
-
-       } else if (ddata->cfg.quirks & SYSC_QUIRK_RESET_STATUS) {
-               error = readx_poll_timeout(sysc_read_sysconfig, ddata, rstval,
-                                          !(rstval & sysc_mask),
-                                          100, MAX_MODULE_SOFTRESET_WAIT);
-       }
+       error = sysc_wait_softreset(ddata);
+       if (error)
+               dev_warn(ddata->dev, "OCP softreset timed out\n");
 
        if (ddata->reset_done_quirk)
                ddata->reset_done_quirk(ddata);
@@ -2814,6 +2865,24 @@ static int sysc_check_disabled_devices(struct sysc *ddata)
        return error;
 }
 
+/*
+ * Ignore timers tagged with no-reset and no-idle. These are likely in use,
+ * for example by drivers/clocksource/timer-ti-dm-systimer.c. If more checks
+ * are needed, we could also look at the timer register configuration.
+ */
+static int sysc_check_active_timer(struct sysc *ddata)
+{
+       if (ddata->cap->type != TI_SYSC_OMAP2_TIMER &&
+           ddata->cap->type != TI_SYSC_OMAP4_TIMER)
+               return 0;
+
+       if ((ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT) &&
+           (ddata->cfg.quirks & SYSC_QUIRK_NO_IDLE))
+               return -EBUSY;
+
+       return 0;
+}
+
 static const struct of_device_id sysc_match_table[] = {
        { .compatible = "simple-bus", },
        { /* sentinel */ },
@@ -2870,6 +2939,10 @@ static int sysc_probe(struct platform_device *pdev)
        if (error)
                return error;
 
+       error = sysc_check_active_timer(ddata);
+       if (error)
+               return error;
+
        error = sysc_get_clocks(ddata);
        if (error)
                return error;
index e2330e7..0016170 100644 (file)
@@ -244,6 +244,7 @@ static int ks_sa_rng_probe(struct platform_device *pdev)
        ret = pm_runtime_get_sync(dev);
        if (ret < 0) {
                dev_err(dev, "Failed to enable SA power-domain\n");
+               pm_runtime_put_noidle(dev);
                pm_runtime_disable(dev);
                return ret;
        }
index 31cae88..687d4af 100644 (file)
@@ -171,7 +171,7 @@ static ssize_t read_mem(struct file *file, char __user *buf,
                        if (!ptr)
                                goto failed;
 
-                       probe = probe_kernel_read(bounce, ptr, sz);
+                       probe = copy_from_kernel_nofault(bounce, ptr, sz);
                        unxlate_dev_mem_ptr(p, ptr);
                        if (probe)
                                goto failed;
@@ -814,7 +814,8 @@ static struct inode *devmem_inode;
 #ifdef CONFIG_IO_STRICT_DEVMEM
 void revoke_devmem(struct resource *res)
 {
-       struct inode *inode = READ_ONCE(devmem_inode);
+       /* pairs with smp_store_release() in devmem_init_inode() */
+       struct inode *inode = smp_load_acquire(&devmem_inode);
 
        /*
         * Check that the initialization has completed. Losing the race
@@ -1028,8 +1029,11 @@ static int devmem_init_inode(void)
                return rc;
        }
 
-       /* publish /dev/mem initialized */
-       WRITE_ONCE(devmem_inode, inode);
+       /*
+        * Publish /dev/mem initialized.
+        * Pairs with smp_load_acquire() in revoke_devmem().
+        */
+       smp_store_release(&devmem_inode, inode);
 
        return 0;
 }
index 2a41b21..d20ba1b 100644 (file)
@@ -1277,6 +1277,7 @@ void add_interrupt_randomness(int irq, int irq_flags)
 
        fast_mix(fast_pool);
        add_interrupt_bench(cycles);
+       this_cpu_add(net_rand_state.s1, fast_pool->pool[cycles & 3]);
 
        if (unlikely(crng_init == 0)) {
                if ((fast_pool->count >= 64) &&
index 35333b6..7c617ed 100644 (file)
@@ -210,7 +210,7 @@ static int st33zp24_i2c_request_resources(struct i2c_client *client)
 
 /*
  * st33zp24_i2c_probe initialize the TPM device
- * @param: client, the i2c_client drescription (TPM I2C description).
+ * @param: client, the i2c_client description (TPM I2C description).
  * @param: id, the i2c_device_id struct.
  * @return: 0 in case of success.
  *      -1 in other case.
index 26e09de..a75dafd 100644 (file)
@@ -329,7 +329,7 @@ static int st33zp24_spi_request_resources(struct spi_device *dev)
 
 /*
  * st33zp24_spi_probe initialize the TPM device
- * @param: dev, the spi_device drescription (TPM SPI description).
+ * @param: dev, the spi_device description (TPM SPI description).
  * @return: 0 in case of success.
  *      or a negative value describing the error.
  */
@@ -378,7 +378,7 @@ static int st33zp24_spi_probe(struct spi_device *dev)
 
 /*
  * st33zp24_spi_remove remove the TPM device
- * @param: client, the spi_device drescription (TPM SPI description).
+ * @param: client, the spi_device description (TPM SPI description).
  * @return: 0 in case of success.
  */
 static int st33zp24_spi_remove(struct spi_device *dev)
index 37bb13f..4ec10ab 100644 (file)
@@ -502,7 +502,7 @@ static const struct tpm_class_ops st33zp24_tpm = {
 
 /*
  * st33zp24_probe initialize the TPM device
- * @param: client, the i2c_client drescription (TPM I2C description).
+ * @param: client, the i2c_client description (TPM I2C description).
  * @param: id, the i2c_device_id struct.
  * @return: 0 in case of success.
  *      -1 in other case.
index 87f4493..1784530 100644 (file)
@@ -189,15 +189,6 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf,
                goto out;
        }
 
-       /* atomic tpm command send and result receive. We only hold the ops
-        * lock during this period so that the tpm can be unregistered even if
-        * the char dev is held open.
-        */
-       if (tpm_try_get_ops(priv->chip)) {
-               ret = -EPIPE;
-               goto out;
-       }
-
        priv->response_length = 0;
        priv->response_read = false;
        *off = 0;
@@ -211,11 +202,19 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf,
        if (file->f_flags & O_NONBLOCK) {
                priv->command_enqueued = true;
                queue_work(tpm_dev_wq, &priv->async_work);
-               tpm_put_ops(priv->chip);
                mutex_unlock(&priv->buffer_mutex);
                return size;
        }
 
+       /* atomic tpm command send and result receive. We only hold the ops
+        * lock during this period so that the tpm can be unregistered even if
+        * the char dev is held open.
+        */
+       if (tpm_try_get_ops(priv->chip)) {
+               ret = -EPIPE;
+               goto out;
+       }
+
        ret = tpm_dev_transmit(priv->chip, priv->space, priv->data_buffer,
                               sizeof(priv->data_buffer));
        tpm_put_ops(priv->chip);
index 09fe452..994385b 100644 (file)
@@ -683,13 +683,6 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
        if (rc)
                goto init_irq_cleanup;
 
-       if (!strcmp(id->compat, "IBM,vtpm20")) {
-               chip->flags |= TPM_CHIP_FLAG_TPM2;
-               rc = tpm2_get_cc_attrs_tbl(chip);
-               if (rc)
-                       goto init_irq_cleanup;
-       }
-
        if (!wait_event_timeout(ibmvtpm->crq_queue.wq,
                                ibmvtpm->rtce_buf != NULL,
                                HZ)) {
@@ -697,6 +690,13 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
                goto init_irq_cleanup;
        }
 
+       if (!strcmp(id->compat, "IBM,vtpm20")) {
+               chip->flags |= TPM_CHIP_FLAG_TPM2;
+               rc = tpm2_get_cc_attrs_tbl(chip);
+               if (rc)
+                       goto init_irq_cleanup;
+       }
+
        return tpm_chip_register(chip);
 init_irq_cleanup:
        do {
index e7df342..0b21496 100644 (file)
@@ -235,6 +235,13 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
        return tpm_tis_init(&pnp_dev->dev, &tpm_info);
 }
 
+/*
+ * There is a known bug caused by 93e1b7d42e1e ("[PATCH] tpm: add HID module
+ * parameter"). This commit added IFX0102 device ID, which is also used by
+ * tpm_infineon but ignored to add quirks to probe which driver ought to be
+ * used.
+ */
+
 static struct pnp_device_id tpm_pnp_tbl[] = {
        {"PNP0C31", 0},         /* TPM */
        {"ATM1200", 0},         /* Atmel */
index 2435216..65ab1b0 100644 (file)
@@ -1085,7 +1085,7 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
 
        return 0;
 out_err:
-       if ((chip->ops != NULL) && (chip->ops->clk_enable != NULL))
+       if (chip->ops->clk_enable != NULL)
                chip->ops->clk_enable(chip, false);
 
        tpm_tis_remove(chip);
index d967559..3856f6e 100644 (file)
@@ -53,8 +53,6 @@ static int tpm_tis_spi_flow_control(struct tpm_tis_spi_phy *phy,
 
        if ((phy->iobuf[3] & 0x01) == 0) {
                // handle SPI wait states
-               phy->iobuf[0] = 0;
-
                for (i = 0; i < TPM_RETRY; i++) {
                        spi_xfer->len = 1;
                        spi_message_init(&m);
@@ -104,6 +102,8 @@ int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
                if (ret < 0)
                        goto exit;
 
+               /* Flow control transfers are receive only */
+               spi_xfer.tx_buf = NULL;
                ret = phy->flow_control(phy, &spi_xfer);
                if (ret < 0)
                        goto exit;
@@ -113,9 +113,8 @@ int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
                spi_xfer.delay.value = 5;
                spi_xfer.delay.unit = SPI_DELAY_UNIT_USECS;
 
-               if (in) {
-                       spi_xfer.tx_buf = NULL;
-               } else if (out) {
+               if (out) {
+                       spi_xfer.tx_buf = phy->iobuf;
                        spi_xfer.rx_buf = NULL;
                        memcpy(phy->iobuf, out, transfer_len);
                        out += transfer_len;
@@ -288,6 +287,7 @@ static struct spi_driver tpm_tis_spi_driver = {
                .pm = &tpm_tis_pm,
                .of_match_table = of_match_ptr(of_tis_spi_match),
                .acpi_match_table = ACPI_PTR(acpi_tis_spi_match),
+               .probe_type = PROBE_PREFER_ASYNCHRONOUS,
        },
        .probe = tpm_tis_spi_driver_probe,
        .remove = tpm_tis_spi_remove,
index 00c5e3a..ca691bc 100644 (file)
@@ -2116,6 +2116,7 @@ static struct virtio_device_id id_table[] = {
        { VIRTIO_ID_CONSOLE, VIRTIO_DEV_ANY_ID },
        { 0 },
 };
+MODULE_DEVICE_TABLE(virtio, id_table);
 
 static unsigned int features[] = {
        VIRTIO_CONSOLE_F_SIZE,
@@ -2128,6 +2129,7 @@ static struct virtio_device_id rproc_serial_id_table[] = {
 #endif
        { 0 },
 };
+MODULE_DEVICE_TABLE(virtio, rproc_serial_id_table);
 
 static unsigned int rproc_serial_features[] = {
 };
@@ -2280,6 +2282,5 @@ static void __exit fini(void)
 module_init(init);
 module_exit(fini);
 
-MODULE_DEVICE_TABLE(virtio, id_table);
 MODULE_DESCRIPTION("Virtio console driver");
 MODULE_LICENSE("GPL");
index 69934c0..326f91b 100644 (file)
@@ -50,6 +50,7 @@ source "drivers/clk/versatile/Kconfig"
 config CLK_HSDK
        bool "PLL Driver for HSDK platform"
        depends on OF || COMPILE_TEST
+       depends on IOMEM
        help
          This driver supports the HSDK core, system, ddr, tunnel and hdmi PLLs
          control.
index 99afc94..177368c 100644 (file)
@@ -131,6 +131,18 @@ static const struct clk_div_table ast2600_eclk_div_table[] = {
        { 0 }
 };
 
+static const struct clk_div_table ast2600_emmc_extclk_div_table[] = {
+       { 0x0, 2 },
+       { 0x1, 4 },
+       { 0x2, 6 },
+       { 0x3, 8 },
+       { 0x4, 10 },
+       { 0x5, 12 },
+       { 0x6, 14 },
+       { 0x7, 16 },
+       { 0 }
+};
+
 static const struct clk_div_table ast2600_mac_div_table[] = {
        { 0x0, 4 },
        { 0x1, 4 },
@@ -390,6 +402,11 @@ static struct clk_hw *aspeed_g6_clk_hw_register_gate(struct device *dev,
        return hw;
 }
 
+static const char *const emmc_extclk_parent_names[] = {
+       "emmc_extclk_hpll_in",
+       "mpll",
+};
+
 static const char * const vclk_parent_names[] = {
        "dpll",
        "d1pll",
@@ -459,16 +476,32 @@ static int aspeed_g6_clk_probe(struct platform_device *pdev)
                return PTR_ERR(hw);
        aspeed_g6_clk_data->hws[ASPEED_CLK_UARTX] = hw;
 
-       /* EMMC ext clock divider */
-       hw = clk_hw_register_gate(dev, "emmc_extclk_gate", "hpll", 0,
-                       scu_g6_base + ASPEED_G6_CLK_SELECTION1, 15, 0,
-                       &aspeed_g6_clk_lock);
+       /* EMMC ext clock */
+       hw = clk_hw_register_fixed_factor(dev, "emmc_extclk_hpll_in", "hpll",
+                                         0, 1, 2);
        if (IS_ERR(hw))
                return PTR_ERR(hw);
-       hw = clk_hw_register_divider_table(dev, "emmc_extclk", "emmc_extclk_gate", 0,
-                       scu_g6_base + ASPEED_G6_CLK_SELECTION1, 12, 3, 0,
-                       ast2600_div_table,
-                       &aspeed_g6_clk_lock);
+
+       hw = clk_hw_register_mux(dev, "emmc_extclk_mux",
+                                emmc_extclk_parent_names,
+                                ARRAY_SIZE(emmc_extclk_parent_names), 0,
+                                scu_g6_base + ASPEED_G6_CLK_SELECTION1, 11, 1,
+                                0, &aspeed_g6_clk_lock);
+       if (IS_ERR(hw))
+               return PTR_ERR(hw);
+
+       hw = clk_hw_register_gate(dev, "emmc_extclk_gate", "emmc_extclk_mux",
+                                 0, scu_g6_base + ASPEED_G6_CLK_SELECTION1,
+                                 15, 0, &aspeed_g6_clk_lock);
+       if (IS_ERR(hw))
+               return PTR_ERR(hw);
+
+       hw = clk_hw_register_divider_table(dev, "emmc_extclk",
+                                          "emmc_extclk_gate", 0,
+                                          scu_g6_base +
+                                               ASPEED_G6_CLK_SELECTION1, 12,
+                                          3, 0, ast2600_emmc_extclk_div_table,
+                                          &aspeed_g6_clk_lock);
        if (IS_ERR(hw))
                return PTR_ERR(hw);
        aspeed_g6_clk_data->hws[ASPEED_CLK_EMMC] = hw;
index ded07b0..557d621 100644 (file)
@@ -42,6 +42,7 @@ config ARMADA_AP806_SYSCON
 
 config ARMADA_AP_CPU_CLK
        bool
+       select ARMADA_AP_CP_HELPER
 
 config ARMADA_CP110_SYSCON
        bool
index 6282ee2..a8901f9 100644 (file)
@@ -586,7 +586,10 @@ static int sifive_fu540_prci_probe(struct platform_device *pdev)
        struct __prci_data *pd;
        int r;
 
-       pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+       pd = devm_kzalloc(dev,
+                         struct_size(pd, hw_clks.hws,
+                                     ARRAY_SIZE(__prci_init_clocks)),
+                         GFP_KERNEL);
        if (!pd)
                return -ENOMEM;
 
index ecf7b7d..6c3e841 100644 (file)
@@ -480,6 +480,14 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = {
                .set_next_event_virt = erratum_set_next_event_tval_virt,
        },
 #endif
+#ifdef CONFIG_ARM64_ERRATUM_1418040
+       {
+               .match_type = ate_match_local_cap_id,
+               .id = (void *)ARM64_WORKAROUND_1418040,
+               .desc = "ARM erratum 1418040",
+               .disable_compat_vdso = true,
+       },
+#endif
 };
 
 typedef bool (*ate_match_fn_t)(const struct arch_timer_erratum_workaround *,
@@ -566,6 +574,9 @@ void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa
        if (wa->read_cntvct_el0) {
                clocksource_counter.vdso_clock_mode = VDSO_CLOCKMODE_NONE;
                vdso_default = VDSO_CLOCKMODE_NONE;
+       } else if (wa->disable_compat_vdso && vdso_default != VDSO_CLOCKMODE_NONE) {
+               vdso_default = VDSO_CLOCKMODE_ARCHTIMER_NOCOMPAT;
+               clocksource_counter.vdso_clock_mode = vdso_default;
        }
 }
 
index 6fd1f21..f6fd1c1 100644 (file)
@@ -19,7 +19,7 @@
 /* For type1, set SYSC_OMAP2_CLOCKACTIVITY for fck off on idle, l4 clock on */
 #define DMTIMER_TYPE1_ENABLE   ((1 << 9) | (SYSC_IDLE_SMART << 3) | \
                                 SYSC_OMAP2_ENAWAKEUP | SYSC_OMAP2_AUTOIDLE)
-
+#define DMTIMER_TYPE1_DISABLE  (SYSC_OMAP2_SOFTRESET | SYSC_OMAP2_AUTOIDLE)
 #define DMTIMER_TYPE2_ENABLE   (SYSC_IDLE_SMART_WKUP << 2)
 #define DMTIMER_RESET_WAIT     100000
 
@@ -44,6 +44,8 @@ struct dmtimer_systimer {
        u8 ctrl;
        u8 wakeup;
        u8 ifctrl;
+       struct clk *fck;
+       struct clk *ick;
        unsigned long rate;
 };
 
@@ -298,16 +300,20 @@ static void __init dmtimer_systimer_select_best(void)
 }
 
 /* Interface clocks are only available on some SoCs variants */
-static int __init dmtimer_systimer_init_clock(struct device_node *np,
+static int __init dmtimer_systimer_init_clock(struct dmtimer_systimer *t,
+                                             struct device_node *np,
                                              const char *name,
                                              unsigned long *rate)
 {
        struct clk *clock;
        unsigned long r;
+       bool is_ick = false;
        int error;
 
+       is_ick = !strncmp(name, "ick", 3);
+
        clock = of_clk_get_by_name(np, name);
-       if ((PTR_ERR(clock) == -EINVAL) && !strncmp(name, "ick", 3))
+       if ((PTR_ERR(clock) == -EINVAL) && is_ick)
                return 0;
        else if (IS_ERR(clock))
                return PTR_ERR(clock);
@@ -320,6 +326,11 @@ static int __init dmtimer_systimer_init_clock(struct device_node *np,
        if (!r)
                return -ENODEV;
 
+       if (is_ick)
+               t->ick = clock;
+       else
+               t->fck = clock;
+
        *rate = r;
 
        return 0;
@@ -339,7 +350,10 @@ static void dmtimer_systimer_enable(struct dmtimer_systimer *t)
 
 static void dmtimer_systimer_disable(struct dmtimer_systimer *t)
 {
-       writel_relaxed(0, t->base + t->sysc);
+       if (!dmtimer_systimer_revision1(t))
+               return;
+
+       writel_relaxed(DMTIMER_TYPE1_DISABLE, t->base + t->sysc);
 }
 
 static int __init dmtimer_systimer_setup(struct device_node *np,
@@ -366,13 +380,13 @@ static int __init dmtimer_systimer_setup(struct device_node *np,
                pr_err("%s: clock source init failed: %i\n", __func__, error);
 
        /* For ti-sysc, we have timer clocks at the parent module level */
-       error = dmtimer_systimer_init_clock(np->parent, "fck", &rate);
+       error = dmtimer_systimer_init_clock(t, np->parent, "fck", &rate);
        if (error)
                goto err_unmap;
 
        t->rate = rate;
 
-       error = dmtimer_systimer_init_clock(np->parent, "ick", &rate);
+       error = dmtimer_systimer_init_clock(t, np->parent, "ick", &rate);
        if (error)
                goto err_unmap;
 
@@ -496,12 +510,18 @@ static void omap_clockevent_idle(struct clock_event_device *evt)
        struct dmtimer_systimer *t = &clkevt->t;
 
        dmtimer_systimer_disable(t);
+       clk_disable(t->fck);
 }
 
 static void omap_clockevent_unidle(struct clock_event_device *evt)
 {
        struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt);
        struct dmtimer_systimer *t = &clkevt->t;
+       int error;
+
+       error = clk_enable(t->fck);
+       if (error)
+               pr_err("could not enable timer fck on resume: %i\n", error);
 
        dmtimer_systimer_enable(t);
        writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_ena);
@@ -570,8 +590,8 @@ static int __init dmtimer_clockevent_init(struct device_node *np)
                                        3, /* Timer internal resynch latency */
                                        0xffffffff);
 
-       if (of_device_is_compatible(np, "ti,am33xx") ||
-           of_device_is_compatible(np, "ti,am43")) {
+       if (of_machine_is_compatible("ti,am33xx") ||
+           of_machine_is_compatible("ti,am43")) {
                dev->suspend = omap_clockevent_idle;
                dev->resume = omap_clockevent_unidle;
        }
@@ -616,12 +636,18 @@ static void dmtimer_clocksource_suspend(struct clocksource *cs)
 
        clksrc->loadval = readl_relaxed(t->base + t->counter);
        dmtimer_systimer_disable(t);
+       clk_disable(t->fck);
 }
 
 static void dmtimer_clocksource_resume(struct clocksource *cs)
 {
        struct dmtimer_clocksource *clksrc = to_dmtimer_clocksource(cs);
        struct dmtimer_systimer *t = &clksrc->t;
+       int error;
+
+       error = clk_enable(t->fck);
+       if (error)
+               pr_err("could not enable timer fck on resume: %i\n", error);
 
        dmtimer_systimer_enable(t);
        writel_relaxed(clksrc->loadval, t->base + t->counter);
@@ -653,8 +679,8 @@ static int __init dmtimer_clocksource_init(struct device_node *np)
        dev->mask = CLOCKSOURCE_MASK(32);
        dev->flags = CLOCK_SOURCE_IS_CONTINUOUS;
 
-       if (of_device_is_compatible(np, "ti,am33xx") ||
-           of_device_is_compatible(np, "ti,am43")) {
+       /* Unlike for clockevent, legacy code sets suspend only for am4 */
+       if (of_machine_is_compatible("ti,am43")) {
                dev->suspend = dmtimer_clocksource_suspend;
                dev->resume = dmtimer_clocksource_resume;
        }
index aa13708..d22cfae 100644 (file)
@@ -1274,18 +1274,26 @@ static ssize_t quad8_signal_cable_fault_read(struct counter_device *counter,
                                             struct counter_signal *signal,
                                             void *private, char *buf)
 {
-       const struct quad8_iio *const priv = counter->priv;
+       struct quad8_iio *const priv = counter->priv;
        const size_t channel_id = signal->id / 2;
-       const bool disabled = !(priv->cable_fault_enable & BIT(channel_id));
+       bool disabled;
        unsigned int status;
        unsigned int fault;
 
-       if (disabled)
+       mutex_lock(&priv->lock);
+
+       disabled = !(priv->cable_fault_enable & BIT(channel_id));
+
+       if (disabled) {
+               mutex_unlock(&priv->lock);
                return -EINVAL;
+       }
 
        /* Logic 0 = cable fault */
        status = inb(priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
 
+       mutex_unlock(&priv->lock);
+
        /* Mask respective channel and invert logic */
        fault = !(status & BIT(channel_id));
 
@@ -1317,6 +1325,8 @@ static ssize_t quad8_signal_cable_fault_enable_write(
        if (ret)
                return ret;
 
+       mutex_lock(&priv->lock);
+
        if (enable)
                priv->cable_fault_enable |= BIT(channel_id);
        else
@@ -1327,6 +1337,8 @@ static ssize_t quad8_signal_cable_fault_enable_write(
 
        outb(cable_fault_enable, priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
 
+       mutex_unlock(&priv->lock);
+
        return len;
 }
 
@@ -1353,6 +1365,8 @@ static ssize_t quad8_signal_fck_prescaler_write(struct counter_device *counter,
        if (ret)
                return ret;
 
+       mutex_lock(&priv->lock);
+
        priv->fck_prescaler[channel_id] = prescaler;
 
        /* Reset Byte Pointer */
@@ -1363,6 +1377,8 @@ static ssize_t quad8_signal_fck_prescaler_write(struct counter_device *counter,
        outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
             base_offset + 1);
 
+       mutex_unlock(&priv->lock);
+
        return len;
 }
 
index 8e23a69..7e0f788 100644 (file)
@@ -2464,7 +2464,7 @@ static struct cpufreq_driver intel_cpufreq = {
        .name           = "intel_cpufreq",
 };
 
-static struct cpufreq_driver *default_driver = &intel_pstate;
+static struct cpufreq_driver *default_driver;
 
 static void intel_pstate_driver_cleanup(void)
 {
@@ -2677,6 +2677,8 @@ static struct acpi_platform_list plat_info[] __initdata = {
        { } /* End */
 };
 
+#define BITMASK_OOB    (BIT(8) | BIT(18))
+
 static bool __init intel_pstate_platform_pwr_mgmt_exists(void)
 {
        const struct x86_cpu_id *id;
@@ -2686,8 +2688,9 @@ static bool __init intel_pstate_platform_pwr_mgmt_exists(void)
        id = x86_match_cpu(intel_pstate_cpu_oob_ids);
        if (id) {
                rdmsrl(MSR_MISC_PWR_MGMT, misc_pwr);
-               if (misc_pwr & (1 << 8)) {
-                       pr_debug("Bit 8 in the MISC_PWR_MGMT MSR set\n");
+               if (misc_pwr & BITMASK_OOB) {
+                       pr_debug("Bit 8 or 18 in the MISC_PWR_MGMT MSR set\n");
+                       pr_debug("P states are controlled in Out of Band mode by the firmware/hardware\n");
                        return true;
                }
        }
@@ -2755,6 +2758,7 @@ static int __init intel_pstate_init(void)
                        hwp_active++;
                        hwp_mode_bdw = id->driver_data;
                        intel_pstate.attr = hwp_cpufreq_attrs;
+                       default_driver = &intel_pstate;
                        goto hwp_cpu_matched;
                }
        } else {
@@ -2772,7 +2776,8 @@ static int __init intel_pstate_init(void)
                return -ENODEV;
        }
        /* Without HWP start in the passive mode. */
-       default_driver = &intel_cpufreq;
+       if (!default_driver)
+               default_driver = &intel_cpufreq;
 
 hwp_cpu_matched:
        /*
@@ -2817,6 +2822,8 @@ static int __init intel_pstate_setup(char *str)
 
        if (!strcmp(str, "disable")) {
                no_load = 1;
+       } else if (!strcmp(str, "active")) {
+               default_driver = &intel_pstate;
        } else if (!strcmp(str, "passive")) {
                default_driver = &intel_cpufreq;
                no_hwp = 1;
index c149d9e..8719731 100644 (file)
@@ -186,9 +186,10 @@ int cpuidle_enter_s2idle(struct cpuidle_driver *drv, struct cpuidle_device *dev)
         * be frozen safely.
         */
        index = find_deepest_state(drv, dev, U64_MAX, 0, true);
-       if (index > 0)
+       if (index > 0) {
                enter_s2idle_proper(drv, dev, index);
-
+               local_irq_enable();
+       }
        return index;
 }
 #endif /* CONFIG_SUSPEND */
index a62f228..bc35aa0 100644 (file)
@@ -147,7 +147,7 @@ config CRYPTO_DEV_FSL_CAAM_RNG_API
        select HW_RANDOM
        help
          Selecting this will register the SEC4 hardware rng to
-         the hw_random API for suppying the kernel entropy pool.
+         the hw_random API for supplying the kernel entropy pool.
 
 endif # CRYPTO_DEV_FSL_CAAM_JR
 
index 4fcdd26..f3d20b7 100644 (file)
@@ -54,7 +54,7 @@ static void build_instantiation_desc(u32 *desc, int handle, int do_sk)
 
                /*
                 * load 1 to clear written reg:
-                * resets the done interrrupt and returns the RNG to idle.
+                * resets the done interrupt and returns the RNG to idle.
                 */
                append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
 
@@ -156,7 +156,7 @@ static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc,
                                     DESC_DER_DECO_STAT_SHIFT;
 
                /*
-                * If an error occured in the descriptor, then
+                * If an error occurred in the descriptor, then
                 * the DECO status field will be set to 0x0D
                 */
                if (deco_state == DECO_STAT_HOST_ERR)
@@ -264,7 +264,7 @@ static void devm_deinstantiate_rng(void *data)
  *        - -ENODEV if DECO0 couldn't be acquired
  *        - -EAGAIN if an error occurred when executing the descriptor
  *           f.i. there was a RNG hardware error due to not "good enough"
- *           entropy being aquired.
+ *           entropy being acquired.
  */
 static int instantiate_rng(struct device *ctrldev, int state_handle_mask,
                           int gen_sk)
@@ -733,8 +733,8 @@ static int caam_probe(struct platform_device *pdev)
        handle_imx6_err005766(&ctrl->mcr);
 
        /*
-        *  Read the Compile Time paramters and SCFGR to determine
-        * if Virtualization is enabled for this platform
+        *  Read the Compile Time parameters and SCFGR to determine
+        * if virtualization is enabled for this platform
         */
        scfgr = rd_reg32(&ctrl->scfgr);
 
@@ -863,9 +863,9 @@ static int caam_probe(struct platform_device *pdev)
                        }
                        /*
                         * if instantiate_rng(...) fails, the loop will rerun
-                        * and the kick_trng(...) function will modfiy the
+                        * and the kick_trng(...) function will modify the
                         * upper and lower limits of the entropy sampling
-                        * interval, leading to a sucessful initialization of
+                        * interval, leading to a successful initialization of
                         * the RNG.
                         */
                        ret = instantiate_rng(dev, inst_handles,
@@ -882,8 +882,8 @@ static int caam_probe(struct platform_device *pdev)
                        return ret;
                }
                /*
-                * Set handles init'ed by this module as the complement of the
-                * already initialized ones
+                * Set handles initialized by this module as the complement of
+                * the already initialized ones
                 */
                ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_MASK;
 
index e796d3c..e134709 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 #define SEC4_SG_LEN_EXT                0x80000000      /* Entry points to table */
-#define SEC4_SG_LEN_FIN                0x40000000      /* Last ent in table */
+#define SEC4_SG_LEN_FIN                0x40000000      /* Last entry in table */
 #define SEC4_SG_BPID_MASK      0x000000ff
 #define SEC4_SG_BPID_SHIFT     16
 #define SEC4_SG_LEN_MASK       0x3fffffff      /* Excludes EXT and FINAL */
  */
 #define HDR_REVERSE            0x00000800
 
-/* Propogate DNR property to SharedDesc */
+/* Propagate DNR property to SharedDesc */
 #define HDR_PROP_DNR           0x00000800
 
 /* JobDesc/SharedDesc share property */
index 68c1fd5..8ccc220 100644 (file)
@@ -453,7 +453,7 @@ struct srtp_decap_pdb {
 #define DSA_PDB_N_MASK         0x7f
 
 struct dsa_sign_pdb {
-       u32 sgf_ln; /* Use DSA_PDB_ defintions per above */
+       u32 sgf_ln; /* Use DSA_PDB_ definitions per above */
        u8 *q;
        u8 *r;
        u8 *g;  /* or Gx,y */
index a242633..476113e 100644 (file)
@@ -376,6 +376,7 @@ static int sev_ioctl_do_pek_csr(struct sev_issue_cmd *argp, bool writable)
        struct sev_device *sev = psp_master->sev_data;
        struct sev_user_data_pek_csr input;
        struct sev_data_pek_csr *data;
+       void __user *input_address;
        void *blob = NULL;
        int ret;
 
@@ -394,6 +395,7 @@ static int sev_ioctl_do_pek_csr(struct sev_issue_cmd *argp, bool writable)
                goto cmd;
 
        /* allocate a physically contiguous buffer to store the CSR blob */
+       input_address = (void __user *)input.address;
        if (input.length > SEV_FW_BLOB_MAX_SIZE) {
                ret = -EFAULT;
                goto e_free;
@@ -426,7 +428,7 @@ cmd:
        }
 
        if (blob) {
-               if (copy_to_user((void __user *)input.address, blob, input.length))
+               if (copy_to_user(input_address, blob, input.length))
                        ret = -EFAULT;
        }
 
@@ -437,7 +439,7 @@ e_free:
        return ret;
 }
 
-void *psp_copy_user_blob(u64 __user uaddr, u32 len)
+void *psp_copy_user_blob(u64 uaddr, u32 len)
 {
        if (!uaddr || !len)
                return ERR_PTR(-EINVAL);
@@ -446,7 +448,7 @@ void *psp_copy_user_blob(u64 __user uaddr, u32 len)
        if (len > SEV_FW_BLOB_MAX_SIZE)
                return ERR_PTR(-EINVAL);
 
-       return memdup_user((void __user *)(uintptr_t)uaddr, len);
+       return memdup_user((void __user *)uaddr, len);
 }
 EXPORT_SYMBOL_GPL(psp_copy_user_blob);
 
@@ -621,6 +623,7 @@ static int sev_ioctl_do_get_id2(struct sev_issue_cmd *argp)
 {
        struct sev_user_data_get_id2 input;
        struct sev_data_get_id *data;
+       void __user *input_address;
        void *id_blob = NULL;
        int ret;
 
@@ -631,6 +634,8 @@ static int sev_ioctl_do_get_id2(struct sev_issue_cmd *argp)
        if (copy_from_user(&input, (void __user *)argp->data, sizeof(input)))
                return -EFAULT;
 
+       input_address = (void __user *)input.address;
+
        data = kzalloc(sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
@@ -660,8 +665,7 @@ static int sev_ioctl_do_get_id2(struct sev_issue_cmd *argp)
        }
 
        if (id_blob) {
-               if (copy_to_user((void __user *)input.address,
-                                id_blob, data->len)) {
+               if (copy_to_user(input_address, id_blob, data->len)) {
                        ret = -EFAULT;
                        goto e_free;
                }
@@ -720,6 +724,8 @@ static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp, bool writable)
        struct sev_user_data_pdh_cert_export input;
        void *pdh_blob = NULL, *cert_blob = NULL;
        struct sev_data_pdh_cert_export *data;
+       void __user *input_cert_chain_address;
+       void __user *input_pdh_cert_address;
        int ret;
 
        /* If platform is not in INIT state then transition it to INIT. */
@@ -745,6 +751,9 @@ static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp, bool writable)
            !input.cert_chain_address)
                goto cmd;
 
+       input_pdh_cert_address = (void __user *)input.pdh_cert_address;
+       input_cert_chain_address = (void __user *)input.cert_chain_address;
+
        /* Allocate a physically contiguous buffer to store the PDH blob. */
        if (input.pdh_cert_len > SEV_FW_BLOB_MAX_SIZE) {
                ret = -EFAULT;
@@ -788,7 +797,7 @@ cmd:
        }
 
        if (pdh_blob) {
-               if (copy_to_user((void __user *)input.pdh_cert_address,
+               if (copy_to_user(input_pdh_cert_address,
                                 pdh_blob, input.pdh_cert_len)) {
                        ret = -EFAULT;
                        goto e_free_cert;
@@ -796,7 +805,7 @@ cmd:
        }
 
        if (cert_blob) {
-               if (copy_to_user((void __user *)input.cert_chain_address,
+               if (copy_to_user(input_cert_chain_address,
                                 cert_blob, input.cert_chain_len))
                        ret = -EFAULT;
        }
index b3fdbdc..31e427e 100644 (file)
@@ -223,7 +223,7 @@ struct chcr_authenc_ctx {
 
 struct __aead_ctx {
        struct chcr_gcm_ctx gcm[0];
-       struct chcr_authenc_ctx authenc[0];
+       struct chcr_authenc_ctx authenc[];
 };
 
 struct chcr_aead_ctx {
@@ -235,7 +235,7 @@ struct chcr_aead_ctx {
        u8 nonce[4];
        u16 hmac_ctrl;
        u16 mayverify;
-       struct  __aead_ctx ctx[0];
+       struct  __aead_ctx ctx[];
 };
 
 struct hmac_ctx {
@@ -247,7 +247,7 @@ struct hmac_ctx {
 struct __crypto_ctx {
        struct hmac_ctx hmacctx[0];
        struct ablk_ctx ablkctx[0];
-       struct chcr_aead_ctx aeadctx[0];
+       struct chcr_aead_ctx aeadctx[];
 };
 
 struct chcr_context {
@@ -257,7 +257,7 @@ struct chcr_context {
        unsigned int  ntxq;
        unsigned int  nrxq;
        struct completion cbc_aes_aio_done;
-       struct __crypto_ctx crypto_ctx[0];
+       struct __crypto_ctx crypto_ctx[];
 };
 
 struct chcr_hctx_per_wr {
index f200fae..5409311 100644 (file)
@@ -102,7 +102,7 @@ static struct net_device *chtls_find_netdev(struct chtls_dev *cdev,
        case PF_INET:
                if (likely(!inet_sk(sk)->inet_rcv_saddr))
                        return ndev;
-               ndev = ip_dev_find(&init_net, inet_sk(sk)->inet_rcv_saddr);
+               ndev = __ip_dev_find(&init_net, inet_sk(sk)->inet_rcv_saddr, false);
                break;
 #if IS_ENABLED(CONFIG_IPV6)
        case PF_INET6:
index e1401d9..2e9acae 100644 (file)
@@ -1052,14 +1052,15 @@ int chtls_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
                                                          &record_type);
                                if (err)
                                        goto out_err;
+
+                               /* Avoid appending tls handshake, alert to tls data */
+                               if (skb)
+                                       tx_skb_finalize(skb);
                        }
 
                        recordsz = size;
                        csk->tlshws.txleft = recordsz;
                        csk->tlshws.type = record_type;
-
-                       if (skb)
-                               ULP_SKB_CB(skb)->ulp.tls.type = record_type;
                }
 
                if (!skb || (ULP_SKB_CB(skb)->flags & ULPCB_FLAG_NO_APPEND) ||
index 0e8c7e3..725a739 100644 (file)
@@ -66,7 +66,8 @@ struct hisi_acc_sgl_pool *hisi_acc_create_sgl_pool(struct device *dev,
 
        sgl_size = sizeof(struct acc_hw_sge) * sge_nr +
                   sizeof(struct hisi_acc_hw_sgl);
-       block_size = PAGE_SIZE * (1 << (MAX_ORDER - 1));
+       block_size = 1 << (PAGE_SHIFT + MAX_ORDER <= 32 ?
+                          PAGE_SHIFT + MAX_ORDER - 1 : 31);
        sgl_num_per_block = block_size / sgl_size;
        block_num = count / sgl_num_per_block;
        remain_sgl = count % sgl_num_per_block;
index 60e744f..1e0a1d7 100644 (file)
@@ -118,6 +118,9 @@ static void otx_cpt_aead_callback(int status, void *arg1, void *arg2)
        struct otx_cpt_req_info *cpt_req;
        struct pci_dev *pdev;
 
+       if (!cpt_info)
+               goto complete;
+
        cpt_req = cpt_info->req;
        if (!status) {
                /*
@@ -129,10 +132,10 @@ static void otx_cpt_aead_callback(int status, void *arg1, void *arg2)
                    !cpt_req->is_enc)
                        status = validate_hmac_cipher_null(cpt_req);
        }
-       if (cpt_info) {
-               pdev = cpt_info->pdev;
-               do_request_cleanup(pdev, cpt_info);
-       }
+       pdev = cpt_info->pdev;
+       do_request_cleanup(pdev, cpt_info);
+
+complete:
        if (areq)
                areq->complete(areq, status);
 }
index c9aa15f..193b40e 100644 (file)
@@ -135,7 +135,8 @@ int __init dio_find(int deviceid)
                else
                        va = ioremap(pa, PAGE_SIZE);
 
-                if (probe_kernel_read(&i, (unsigned char *)va + DIO_IDOFF, 1)) {
+               if (copy_from_kernel_nofault(&i,
+                               (unsigned char *)va + DIO_IDOFF, 1)) {
                        if (scode >= DIOII_SCBASE)
                                iounmap(va);
                         continue;             /* no board present at that select code */
@@ -208,7 +209,8 @@ static int __init dio_init(void)
                else
                        va = ioremap(pa, PAGE_SIZE);
 
-                if (probe_kernel_read(&i, (unsigned char *)va + DIO_IDOFF, 1)) {
+               if (copy_from_kernel_nofault(&i,
+                               (unsigned char *)va + DIO_IDOFF, 1)) {
                        if (scode >= DIOII_SCBASE)
                                iounmap(va);
                         continue;              /* no board present at that select code */
index 01ce125..1ca609f 100644 (file)
@@ -45,46 +45,20 @@ static char *dmabuffs_dname(struct dentry *dentry, char *buffer, int buflen)
        size_t ret = 0;
 
        dmabuf = dentry->d_fsdata;
-       dma_resv_lock(dmabuf->resv, NULL);
+       spin_lock(&dmabuf->name_lock);
        if (dmabuf->name)
                ret = strlcpy(name, dmabuf->name, DMA_BUF_NAME_LEN);
-       dma_resv_unlock(dmabuf->resv);
+       spin_unlock(&dmabuf->name_lock);
 
        return dynamic_dname(dentry, buffer, buflen, "/%s:%s",
                             dentry->d_name.name, ret > 0 ? name : "");
 }
 
-static const struct dentry_operations dma_buf_dentry_ops = {
-       .d_dname = dmabuffs_dname,
-};
-
-static struct vfsmount *dma_buf_mnt;
-
-static int dma_buf_fs_init_context(struct fs_context *fc)
-{
-       struct pseudo_fs_context *ctx;
-
-       ctx = init_pseudo(fc, DMA_BUF_MAGIC);
-       if (!ctx)
-               return -ENOMEM;
-       ctx->dops = &dma_buf_dentry_ops;
-       return 0;
-}
-
-static struct file_system_type dma_buf_fs_type = {
-       .name = "dmabuf",
-       .init_fs_context = dma_buf_fs_init_context,
-       .kill_sb = kill_anon_super,
-};
-
-static int dma_buf_release(struct inode *inode, struct file *file)
+static void dma_buf_release(struct dentry *dentry)
 {
        struct dma_buf *dmabuf;
 
-       if (!is_dma_buf_file(file))
-               return -EINVAL;
-
-       dmabuf = file->private_data;
+       dmabuf = dentry->d_fsdata;
 
        BUG_ON(dmabuf->vmapping_counter);
 
@@ -110,9 +84,32 @@ static int dma_buf_release(struct inode *inode, struct file *file)
        module_put(dmabuf->owner);
        kfree(dmabuf->name);
        kfree(dmabuf);
+}
+
+static const struct dentry_operations dma_buf_dentry_ops = {
+       .d_dname = dmabuffs_dname,
+       .d_release = dma_buf_release,
+};
+
+static struct vfsmount *dma_buf_mnt;
+
+static int dma_buf_fs_init_context(struct fs_context *fc)
+{
+       struct pseudo_fs_context *ctx;
+
+       ctx = init_pseudo(fc, DMA_BUF_MAGIC);
+       if (!ctx)
+               return -ENOMEM;
+       ctx->dops = &dma_buf_dentry_ops;
        return 0;
 }
 
+static struct file_system_type dma_buf_fs_type = {
+       .name = "dmabuf",
+       .init_fs_context = dma_buf_fs_init_context,
+       .kill_sb = kill_anon_super,
+};
+
 static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct *vma)
 {
        struct dma_buf *dmabuf;
@@ -341,8 +338,10 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
                kfree(name);
                goto out_unlock;
        }
+       spin_lock(&dmabuf->name_lock);
        kfree(dmabuf->name);
        dmabuf->name = name;
+       spin_unlock(&dmabuf->name_lock);
 
 out_unlock:
        dma_resv_unlock(dmabuf->resv);
@@ -405,14 +404,13 @@ static void dma_buf_show_fdinfo(struct seq_file *m, struct file *file)
        /* Don't count the temporary reference taken inside procfs seq_show */
        seq_printf(m, "count:\t%ld\n", file_count(dmabuf->file) - 1);
        seq_printf(m, "exp_name:\t%s\n", dmabuf->exp_name);
-       dma_resv_lock(dmabuf->resv, NULL);
+       spin_lock(&dmabuf->name_lock);
        if (dmabuf->name)
                seq_printf(m, "name:\t%s\n", dmabuf->name);
-       dma_resv_unlock(dmabuf->resv);
+       spin_unlock(&dmabuf->name_lock);
 }
 
 static const struct file_operations dma_buf_fops = {
-       .release        = dma_buf_release,
        .mmap           = dma_buf_mmap_internal,
        .llseek         = dma_buf_llseek,
        .poll           = dma_buf_poll,
@@ -546,6 +544,7 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
        dmabuf->size = exp_info->size;
        dmabuf->exp_name = exp_info->exp_name;
        dmabuf->owner = exp_info->owner;
+       spin_lock_init(&dmabuf->name_lock);
        init_waitqueue_head(&dmabuf->poll);
        dmabuf->cb_excl.poll = dmabuf->cb_shared.poll = &dmabuf->poll;
        dmabuf->cb_excl.active = dmabuf->cb_shared.active = 0;
index b175229..604f803 100644 (file)
@@ -1176,6 +1176,8 @@ static int dmatest_run_set(const char *val, const struct kernel_param *kp)
        } else if (dmatest_run) {
                if (!is_threaded_test_pending(info)) {
                        pr_info("No channels configured, continue with any\n");
+                       if (!is_threaded_test_run(info))
+                               stop_threaded_test(info);
                        add_threaded_test(info);
                }
                start_threaded_tests(info);
index 21cb2a5..a1b56f5 100644 (file)
@@ -118,16 +118,11 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 {
        struct dw_dma *dw = to_dw_dma(dwc->chan.device);
 
-       if (test_bit(DW_DMA_IS_INITIALIZED, &dwc->flags))
-               return;
-
        dw->initialize_chan(dwc);
 
        /* Enable interrupts */
        channel_set_bit(dw, MASK.XFER, dwc->mask);
        channel_set_bit(dw, MASK.ERROR, dwc->mask);
-
-       set_bit(DW_DMA_IS_INITIALIZED, &dwc->flags);
 }
 
 /*----------------------------------------------------------------------*/
@@ -954,8 +949,6 @@ static void dwc_issue_pending(struct dma_chan *chan)
 
 void do_dw_dma_off(struct dw_dma *dw)
 {
-       unsigned int i;
-
        dma_writel(dw, CFG, 0);
 
        channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
@@ -966,9 +959,6 @@ void do_dw_dma_off(struct dw_dma *dw)
 
        while (dma_readl(dw, CFG) & DW_CFG_DMA_EN)
                cpu_relax();
-
-       for (i = 0; i < dw->dma.chancnt; i++)
-               clear_bit(DW_DMA_IS_INITIALIZED, &dw->chan[i].flags);
 }
 
 void do_dw_dma_on(struct dw_dma *dw)
@@ -1032,8 +1022,6 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
        /* Clear custom channel configuration */
        memset(&dwc->dws, 0, sizeof(struct dw_dma_slave));
 
-       clear_bit(DW_DMA_IS_INITIALIZED, &dwc->flags);
-
        /* Disable interrupts */
        channel_clear_bit(dw, MASK.XFER, dwc->mask);
        channel_clear_bit(dw, MASK.BLOCK, dwc->mask);
index 5697c36..930ae26 100644 (file)
@@ -352,26 +352,28 @@ static void fsl_edma_set_tcd_regs(struct fsl_edma_chan *fsl_chan,
        /*
         * TCD parameters are stored in struct fsl_edma_hw_tcd in little
         * endian format. However, we need to load the TCD registers in
-        * big- or little-endian obeying the eDMA engine model endian.
+        * big- or little-endian obeying the eDMA engine model endian,
+        * and this is performed from specific edma_write functions
         */
        edma_writew(edma, 0,  &regs->tcd[ch].csr);
-       edma_writel(edma, le32_to_cpu(tcd->saddr), &regs->tcd[ch].saddr);
-       edma_writel(edma, le32_to_cpu(tcd->daddr), &regs->tcd[ch].daddr);
 
-       edma_writew(edma, le16_to_cpu(tcd->attr), &regs->tcd[ch].attr);
-       edma_writew(edma, le16_to_cpu(tcd->soff), &regs->tcd[ch].soff);
+       edma_writel(edma, (s32)tcd->saddr, &regs->tcd[ch].saddr);
+       edma_writel(edma, (s32)tcd->daddr, &regs->tcd[ch].daddr);
 
-       edma_writel(edma, le32_to_cpu(tcd->nbytes), &regs->tcd[ch].nbytes);
-       edma_writel(edma, le32_to_cpu(tcd->slast), &regs->tcd[ch].slast);
+       edma_writew(edma, (s16)tcd->attr, &regs->tcd[ch].attr);
+       edma_writew(edma, tcd->soff, &regs->tcd[ch].soff);
 
-       edma_writew(edma, le16_to_cpu(tcd->citer), &regs->tcd[ch].citer);
-       edma_writew(edma, le16_to_cpu(tcd->biter), &regs->tcd[ch].biter);
-       edma_writew(edma, le16_to_cpu(tcd->doff), &regs->tcd[ch].doff);
+       edma_writel(edma, (s32)tcd->nbytes, &regs->tcd[ch].nbytes);
+       edma_writel(edma, (s32)tcd->slast, &regs->tcd[ch].slast);
 
-       edma_writel(edma, le32_to_cpu(tcd->dlast_sga),
+       edma_writew(edma, (s16)tcd->citer, &regs->tcd[ch].citer);
+       edma_writew(edma, (s16)tcd->biter, &regs->tcd[ch].biter);
+       edma_writew(edma, (s16)tcd->doff, &regs->tcd[ch].doff);
+
+       edma_writel(edma, (s32)tcd->dlast_sga,
                        &regs->tcd[ch].dlast_sga);
 
-       edma_writew(edma, le16_to_cpu(tcd->csr), &regs->tcd[ch].csr);
+       edma_writew(edma, (s16)tcd->csr, &regs->tcd[ch].csr);
 }
 
 static inline
@@ -589,6 +591,8 @@ void fsl_edma_xfer_desc(struct fsl_edma_chan *fsl_chan)
 {
        struct virt_dma_desc *vdesc;
 
+       lockdep_assert_held(&fsl_chan->vchan.lock);
+
        vdesc = vchan_next_desc(&fsl_chan->vchan);
        if (!vdesc)
                return;
index 67e4225..ec11697 100644 (file)
@@ -33,7 +33,7 @@
 #define EDMA_TCD_ATTR_DSIZE_16BIT      BIT(0)
 #define EDMA_TCD_ATTR_DSIZE_32BIT      BIT(1)
 #define EDMA_TCD_ATTR_DSIZE_64BIT      (BIT(0) | BIT(1))
-#define EDMA_TCD_ATTR_DSIZE_32BYTE     (BIT(3) | BIT(0))
+#define EDMA_TCD_ATTR_DSIZE_32BYTE     (BIT(2) | BIT(0))
 #define EDMA_TCD_ATTR_SSIZE_8BIT       0
 #define EDMA_TCD_ATTR_SSIZE_16BIT      (EDMA_TCD_ATTR_DSIZE_16BIT << 8)
 #define EDMA_TCD_ATTR_SSIZE_32BIT      (EDMA_TCD_ATTR_DSIZE_32BIT << 8)
index eff7ebd..90bb72a 100644 (file)
@@ -45,6 +45,13 @@ static irqreturn_t fsl_edma_tx_handler(int irq, void *dev_id)
                        fsl_chan = &fsl_edma->chans[ch];
 
                        spin_lock(&fsl_chan->vchan.lock);
+
+                       if (!fsl_chan->edesc) {
+                               /* terminate_all called before */
+                               spin_unlock(&fsl_chan->vchan.lock);
+                               continue;
+                       }
+
                        if (!fsl_chan->edesc->iscyclic) {
                                list_del(&fsl_chan->edesc->vdesc.node);
                                vchan_cookie_complete(&fsl_chan->edesc->vdesc);
index ff49847..cb376cf 100644 (file)
@@ -74,6 +74,7 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
        struct idxd_device *idxd;
        struct idxd_wq *wq;
        struct device *dev;
+       int rc = 0;
 
        wq = inode_wq(inode);
        idxd = wq->idxd;
@@ -81,17 +82,27 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
 
        dev_dbg(dev, "%s called: %d\n", __func__, idxd_wq_refcount(wq));
 
-       if (idxd_wq_refcount(wq) > 0 && wq_dedicated(wq))
-               return -EBUSY;
-
        ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
                return -ENOMEM;
 
+       mutex_lock(&wq->wq_lock);
+
+       if (idxd_wq_refcount(wq) > 0 && wq_dedicated(wq)) {
+               rc = -EBUSY;
+               goto failed;
+       }
+
        ctx->wq = wq;
        filp->private_data = ctx;
        idxd_wq_get(wq);
+       mutex_unlock(&wq->wq_lock);
        return 0;
+
+ failed:
+       mutex_unlock(&wq->wq_lock);
+       kfree(ctx);
+       return rc;
 }
 
 static int idxd_cdev_release(struct inode *node, struct file *filep)
@@ -105,7 +116,9 @@ static int idxd_cdev_release(struct inode *node, struct file *filep)
        filep->private_data = NULL;
 
        kfree(ctx);
+       mutex_lock(&wq->wq_lock);
        idxd_wq_put(wq);
+       mutex_unlock(&wq->wq_lock);
        return 0;
 }
 
index 8d79a87..8d2718c 100644 (file)
@@ -320,6 +320,31 @@ void idxd_wq_unmap_portal(struct idxd_wq *wq)
        devm_iounmap(dev, wq->dportal);
 }
 
+void idxd_wq_disable_cleanup(struct idxd_wq *wq)
+{
+       struct idxd_device *idxd = wq->idxd;
+       struct device *dev = &idxd->pdev->dev;
+       int i, wq_offset;
+
+       lockdep_assert_held(&idxd->dev_lock);
+       memset(&wq->wqcfg, 0, sizeof(wq->wqcfg));
+       wq->type = IDXD_WQT_NONE;
+       wq->size = 0;
+       wq->group = NULL;
+       wq->threshold = 0;
+       wq->priority = 0;
+       clear_bit(WQ_FLAG_DEDICATED, &wq->flags);
+       memset(wq->name, 0, WQ_NAME_SIZE);
+
+       for (i = 0; i < 8; i++) {
+               wq_offset = idxd->wqcfg_offset + wq->id * 32 + i * sizeof(u32);
+               iowrite32(0, idxd->reg_base + wq_offset);
+               dev_dbg(dev, "WQ[%d][%d][%#x]: %#x\n",
+                       wq->id, i, wq_offset,
+                       ioread32(idxd->reg_base + wq_offset));
+       }
+}
+
 /* Device control bits */
 static inline bool idxd_is_enabled(struct idxd_device *idxd)
 {
index b8f8a36..908c8d0 100644 (file)
@@ -290,6 +290,7 @@ int idxd_wq_enable(struct idxd_wq *wq);
 int idxd_wq_disable(struct idxd_wq *wq);
 int idxd_wq_map_portal(struct idxd_wq *wq);
 void idxd_wq_unmap_portal(struct idxd_wq *wq);
+void idxd_wq_disable_cleanup(struct idxd_wq *wq);
 
 /* submission */
 int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc);
index 6510791..8a35f58 100644 (file)
@@ -141,7 +141,7 @@ irqreturn_t idxd_misc_thread(int vec, void *data)
 
        iowrite32(cause, idxd->reg_base + IDXD_INTCAUSE_OFFSET);
        if (!err)
-               return IRQ_HANDLED;
+               goto out;
 
        gensts.bits = ioread32(idxd->reg_base + IDXD_GENSTATS_OFFSET);
        if (gensts.state == IDXD_DEVICE_STATE_HALT) {
@@ -162,6 +162,7 @@ irqreturn_t idxd_misc_thread(int vec, void *data)
                spin_unlock_bh(&idxd->dev_lock);
        }
 
+ out:
        idxd_unmask_msix_vector(idxd, irq_entry->id);
        return IRQ_HANDLED;
 }
index 052dae5..2e2c508 100644 (file)
@@ -315,6 +315,11 @@ static int idxd_config_bus_remove(struct device *dev)
                idxd_unregister_dma_device(idxd);
                spin_lock_irqsave(&idxd->dev_lock, flags);
                rc = idxd_device_disable(idxd);
+               for (i = 0; i < idxd->max_wqs; i++) {
+                       struct idxd_wq *wq = &idxd->wqs[i];
+
+                       idxd_wq_disable_cleanup(wq);
+               }
                spin_unlock_irqrestore(&idxd->dev_lock, flags);
                module_put(THIS_MODULE);
                if (rc < 0)
index 9177403..270992c 100644 (file)
@@ -1331,8 +1331,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
 
        sdma_channel_synchronize(chan);
 
-       if (sdmac->event_id0 >= 0)
-               sdma_event_disable(sdmac, sdmac->event_id0);
+       sdma_event_disable(sdmac, sdmac->event_id0);
        if (sdmac->event_id1)
                sdma_event_disable(sdmac, sdmac->event_id1);
 
@@ -1632,11 +1631,9 @@ static int sdma_config(struct dma_chan *chan,
        memcpy(&sdmac->slave_config, dmaengine_cfg, sizeof(*dmaengine_cfg));
 
        /* Set ENBLn earlier to make sure dma request triggered after that */
-       if (sdmac->event_id0 >= 0) {
-               if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events)
-                       return -EINVAL;
-               sdma_event_enable(sdmac, sdmac->event_id0);
-       }
+       if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events)
+               return -EINVAL;
+       sdma_event_enable(sdmac, sdmac->event_id0);
 
        if (sdmac->event_id1) {
                if (sdmac->event_id1 >= sdmac->sdma->drvdata->num_events)
index 8ad0ad8..fd782ae 100644 (file)
 
 #include "../dmaengine.h"
 
+int completion_timeout = 200;
+module_param(completion_timeout, int, 0644);
+MODULE_PARM_DESC(completion_timeout,
+               "set ioat completion timeout [msec] (default 200 [msec])");
+int idle_timeout = 2000;
+module_param(idle_timeout, int, 0644);
+MODULE_PARM_DESC(idle_timeout,
+               "set ioat idel timeout [msec] (default 2000 [msec])");
+
+#define IDLE_TIMEOUT msecs_to_jiffies(idle_timeout)
+#define COMPLETION_TIMEOUT msecs_to_jiffies(completion_timeout)
+
 static char *chanerr_str[] = {
        "DMA Transfer Source Address Error",
        "DMA Transfer Destination Address Error",
index e6b622e..f7f31fd 100644 (file)
@@ -104,8 +104,6 @@ struct ioatdma_chan {
        #define IOAT_RUN 5
        #define IOAT_CHAN_ACTIVE 6
        struct timer_list timer;
-       #define COMPLETION_TIMEOUT msecs_to_jiffies(100)
-       #define IDLE_TIMEOUT msecs_to_jiffies(2000)
        #define RESET_DELAY msecs_to_jiffies(100)
        struct ioatdma_device *ioat_dma;
        dma_addr_t completion_dma;
index e15bd15..e12b754 100644 (file)
@@ -35,6 +35,13 @@ static irqreturn_t mcf_edma_tx_handler(int irq, void *dev_id)
                        mcf_chan = &mcf_edma->chans[ch];
 
                        spin_lock(&mcf_chan->vchan.lock);
+
+                       if (!mcf_chan->edesc) {
+                               /* terminate_all called before */
+                               spin_unlock(&mcf_chan->vchan.lock);
+                               continue;
+                       }
+
                        if (!mcf_chan->edesc->iscyclic) {
                                list_del(&mcf_chan->edesc->vdesc.node);
                                vchan_cookie_complete(&mcf_chan->edesc->vdesc);
index 8853d44..a8cfb59 100644 (file)
@@ -77,7 +77,7 @@ struct milbeaut_hdmac_device {
        struct dma_device ddev;
        struct clk *clk;
        void __iomem *reg_base;
-       struct milbeaut_hdmac_chan channels[0];
+       struct milbeaut_hdmac_chan channels[];
 };
 
 static struct milbeaut_hdmac_chan *
index ab3d2f3..85a5972 100644 (file)
@@ -74,7 +74,7 @@ struct milbeaut_xdmac_chan {
 struct milbeaut_xdmac_device {
        struct dma_device ddev;
        void __iomem *reg_base;
-       struct milbeaut_xdmac_chan channels[0];
+       struct milbeaut_xdmac_chan channels[];
 };
 
 static struct milbeaut_xdmac_chan *
index 4ab493d..347146a 100644 (file)
@@ -127,7 +127,7 @@ struct moxart_desc {
        unsigned int                    dma_cycles;
        struct virt_dma_desc            vd;
        uint8_t                         es;
-       struct moxart_sg                sg[0];
+       struct moxart_sg                sg[];
 };
 
 struct moxart_chan {
index b218a01..8f7ceb6 100644 (file)
@@ -586,6 +586,8 @@ static void usb_dmac_isr_transfer_end(struct usb_dmac_chan *chan)
                desc->residue = usb_dmac_get_current_residue(chan, desc,
                                                        desc->sg_index - 1);
                desc->done_cookie = desc->vd.tx.cookie;
+               desc->vd.tx_result.result = DMA_TRANS_NOERROR;
+               desc->vd.tx_result.residue = desc->residue;
                vchan_cookie_complete(&desc->vd);
 
                /* Restart the next transfer if this driver has a next desc */
index b9f0d96..55fc740 100644 (file)
@@ -225,7 +225,7 @@ struct tegra_dma {
        u32                             global_pause_count;
 
        /* Last member of the structure */
-       struct tegra_dma_channel channels[0];
+       struct tegra_dma_channel channels[];
 };
 
 static inline void tdma_write(struct tegra_dma *tdma, u32 reg, u32 val)
index db58d7e..c5fa2ef 100644 (file)
@@ -658,6 +658,7 @@ static int tegra_adma_alloc_chan_resources(struct dma_chan *dc)
 
        ret = pm_runtime_get_sync(tdc2dev(tdc));
        if (ret < 0) {
+               pm_runtime_put_noidle(tdc2dev(tdc));
                free_irq(tdc->irq, tdc);
                return ret;
        }
@@ -869,8 +870,10 @@ static int tegra_adma_probe(struct platform_device *pdev)
        pm_runtime_enable(&pdev->dev);
 
        ret = pm_runtime_get_sync(&pdev->dev);
-       if (ret < 0)
+       if (ret < 0) {
+               pm_runtime_put_noidle(&pdev->dev);
                goto rpm_disable;
+       }
 
        ret = tegra_adma_init(tdma);
        if (ret)
index c4a5c17..35d81bd 100644 (file)
@@ -211,7 +211,7 @@ struct edma_desc {
        u32                             residue;
        u32                             residue_stat;
 
-       struct edma_pset                pset[0];
+       struct edma_pset                pset[];
 };
 
 struct edma_cc;
index 0b8f3dd..77e8e67 100644 (file)
@@ -42,6 +42,7 @@ struct udma_dev *of_xudma_dev_get(struct device_node *np, const char *property)
        ud = platform_get_drvdata(pdev);
        if (!ud) {
                pr_debug("UDMA has not been probed\n");
+               put_device(&pdev->dev);
                return ERR_PTR(-EPROBE_DEFER);
        }
 
index 945b7c6..6c879a7 100644 (file)
@@ -170,7 +170,7 @@ struct udma_desc {
        void *metadata; /* pointer to provided metadata buffer (EPIP, PSdata) */
 
        unsigned int hwdesc_count;
-       struct udma_hwdesc hwdesc[0];
+       struct udma_hwdesc hwdesc[];
 };
 
 enum udma_chan_state {
@@ -1753,7 +1753,8 @@ static int udma_alloc_chan_resources(struct dma_chan *chan)
                        dev_err(ud->ddev.dev,
                                "Descriptor pool allocation failed\n");
                        uc->use_dma_pool = false;
-                       return -ENOMEM;
+                       ret = -ENOMEM;
+                       goto err_cleanup;
                }
        }
 
@@ -1773,16 +1774,18 @@ static int udma_alloc_chan_resources(struct dma_chan *chan)
 
                ret = udma_get_chan_pair(uc);
                if (ret)
-                       return ret;
+                       goto err_cleanup;
 
                ret = udma_alloc_tx_resources(uc);
-               if (ret)
-                       return ret;
+               if (ret) {
+                       udma_put_rchan(uc);
+                       goto err_cleanup;
+               }
 
                ret = udma_alloc_rx_resources(uc);
                if (ret) {
                        udma_free_tx_resources(uc);
-                       return ret;
+                       goto err_cleanup;
                }
 
                uc->config.src_thread = ud->psil_base + uc->tchan->id;
@@ -1800,10 +1803,8 @@ static int udma_alloc_chan_resources(struct dma_chan *chan)
                        uc->id);
 
                ret = udma_alloc_tx_resources(uc);
-               if (ret) {
-                       uc->config.remote_thread_id = -1;
-                       return ret;
-               }
+               if (ret)
+                       goto err_cleanup;
 
                uc->config.src_thread = ud->psil_base + uc->tchan->id;
                uc->config.dst_thread = uc->config.remote_thread_id;
@@ -1820,10 +1821,8 @@ static int udma_alloc_chan_resources(struct dma_chan *chan)
                        uc->id);
 
                ret = udma_alloc_rx_resources(uc);
-               if (ret) {
-                       uc->config.remote_thread_id = -1;
-                       return ret;
-               }
+               if (ret)
+                       goto err_cleanup;
 
                uc->config.src_thread = uc->config.remote_thread_id;
                uc->config.dst_thread = (ud->psil_base + uc->rchan->id) |
@@ -1838,7 +1837,9 @@ static int udma_alloc_chan_resources(struct dma_chan *chan)
                /* Can not happen */
                dev_err(uc->ud->dev, "%s: chan%d invalid direction (%u)\n",
                        __func__, uc->id, uc->config.dir);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_cleanup;
+
        }
 
        /* check if the channel configuration was successful */
@@ -1847,7 +1848,7 @@ static int udma_alloc_chan_resources(struct dma_chan *chan)
 
        if (udma_is_chan_running(uc)) {
                dev_warn(ud->dev, "chan%d: is running!\n", uc->id);
-               udma_stop(uc);
+               udma_reset_chan(uc, false);
                if (udma_is_chan_running(uc)) {
                        dev_err(ud->dev, "chan%d: won't stop!\n", uc->id);
                        ret = -EBUSY;
@@ -1906,8 +1907,6 @@ static int udma_alloc_chan_resources(struct dma_chan *chan)
 
        udma_reset_rings(uc);
 
-       INIT_DELAYED_WORK_ONSTACK(&uc->tx_drain.work,
-                                 udma_check_tx_completion);
        return 0;
 
 err_irq_free:
@@ -1919,7 +1918,7 @@ err_psi_free:
 err_res_free:
        udma_free_tx_resources(uc);
        udma_free_rx_resources(uc);
-
+err_cleanup:
        udma_reset_uchan(uc);
 
        if (uc->use_dma_pool) {
@@ -3019,7 +3018,6 @@ static void udma_free_chan_resources(struct dma_chan *chan)
        }
 
        cancel_delayed_work_sync(&uc->tx_drain.work);
-       destroy_delayed_work_on_stack(&uc->tx_drain.work);
 
        if (uc->irq_num_ring > 0) {
                free_irq(uc->irq_num_ring, uc);
@@ -3593,7 +3591,7 @@ static int udma_probe(struct platform_device *pdev)
                return ret;
        }
 
-       ret = of_property_read_u32(navss_node, "ti,udma-atype", &ud->atype);
+       ret = of_property_read_u32(dev->of_node, "ti,udma-atype", &ud->atype);
        if (!ret && ud->atype > 2) {
                dev_err(dev, "Invalid atype: %u\n", ud->atype);
                return -EINVAL;
@@ -3711,6 +3709,7 @@ static int udma_probe(struct platform_device *pdev)
                tasklet_init(&uc->vc.task, udma_vchan_complete,
                             (unsigned long)&uc->vc);
                init_completion(&uc->teardown_completed);
+               INIT_DELAYED_WORK(&uc->tx_drain.work, udma_check_tx_completion);
        }
 
        ret = dma_async_device_register(&ud->ddev);
index 3938269..68e48bf 100644 (file)
@@ -88,7 +88,7 @@ struct timb_dma {
        struct dma_device       dma;
        void __iomem            *membase;
        struct tasklet_struct   tasklet;
-       struct timb_dma_chan    channels[0];
+       struct timb_dma_chan    channels[];
 };
 
 static struct device *chan2dev(struct dma_chan *chan)
index ef90070..6262f63 100644 (file)
@@ -269,6 +269,8 @@ static int get_scrub_rate(struct mem_ctl_info *mci)
 
                if (pvt->model == 0x60)
                        amd64_read_pci_cfg(pvt->F2, F15H_M60H_SCRCTRL, &scrubval);
+               else
+                       amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval);
        } else {
                amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval);
        }
index c7ea4f2..fb6c651 100644 (file)
@@ -117,7 +117,7 @@ struct inbound_transaction_resource {
 struct descriptor_resource {
        struct client_resource resource;
        struct fw_descriptor descriptor;
-       u32 data[0];
+       u32 data[];
 };
 
 struct iso_resource {
index 404a035..439d918 100644 (file)
@@ -620,7 +620,7 @@ struct fw_request {
        u32 request_header[4];
        int ack;
        u32 length;
-       u32 data[0];
+       u32 data[];
 };
 
 static void free_response_callback(struct fw_packet *packet,
index 4b0e4ee..71d5f16 100644 (file)
@@ -191,7 +191,7 @@ struct fw_node {
        /* Upper layer specific data. */
        void *data;
 
-       struct fw_node *ports[0];
+       struct fw_node *ports[];
 };
 
 static inline struct fw_node *fw_node_get(struct fw_node *node)
index 6ca2f5a..5fd6a60 100644 (file)
@@ -52,7 +52,7 @@ struct pcl {
 
 struct packet {
        unsigned int length;
-       char data[0];
+       char data[];
 };
 
 struct packet_buffer {
index 3326931..54fdc39 100644 (file)
@@ -111,7 +111,7 @@ struct descriptor_buffer {
        dma_addr_t buffer_bus;
        size_t buffer_size;
        size_t used;
-       struct descriptor buffer[0];
+       struct descriptor buffer[];
 };
 
 struct context {
index b618002..8b8127f 100644 (file)
@@ -262,7 +262,7 @@ struct dmi_system_event_log {
        u8      header_format;
        u8      type_descriptors_supported_count;
        u8      per_log_type_descriptor_length;
-       u8      supported_log_type_descriptos[0];
+       u8      supported_log_type_descriptos[];
 } __packed;
 
 #define DMI_SYSFS_SEL_FIELD(_field) \
index e6fc022..3939699 100644 (file)
@@ -278,3 +278,14 @@ config EFI_EARLYCON
        depends on SERIAL_EARLYCON && !ARM && !IA64
        select FONT_SUPPORT
        select ARCH_USE_MEMREMAP_PROT
+
+config EFI_CUSTOM_SSDT_OVERLAYS
+       bool "Load custom ACPI SSDT overlay from an EFI variable"
+       depends on EFI_VARS && ACPI
+       default ACPI_TABLE_UPGRADE
+       help
+         Allow loading of an ACPI SSDT overlay from an EFI variable specified
+         by a kernel command line option.
+
+         See Documentation/admin-guide/acpi/ssdt-overlays.rst for more
+         information.
index c697e70..71c445d 100644 (file)
@@ -52,9 +52,11 @@ static phys_addr_t __init efi_to_phys(unsigned long addr)
 }
 
 static __initdata unsigned long screen_info_table = EFI_INVALID_TABLE_ADDR;
+static __initdata unsigned long cpu_state_table = EFI_INVALID_TABLE_ADDR;
 
 static const efi_config_table_type_t arch_tables[] __initconst = {
        {LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, &screen_info_table},
+       {LINUX_EFI_ARM_CPU_STATE_TABLE_GUID, &cpu_state_table},
        {}
 };
 
@@ -62,7 +64,8 @@ static void __init init_screen_info(void)
 {
        struct screen_info *si;
 
-       if (screen_info_table != EFI_INVALID_TABLE_ADDR) {
+       if (IS_ENABLED(CONFIG_ARM) &&
+           screen_info_table != EFI_INVALID_TABLE_ADDR) {
                si = early_memremap_ro(screen_info_table, sizeof(*si));
                if (!si) {
                        pr_err("Could not map screen_info config table\n");
@@ -116,7 +119,8 @@ static int __init uefi_init(u64 efi_system_table)
                goto out;
        }
        retval = efi_config_parse_tables(config_tables, systab->nr_tables,
-                                        arch_tables);
+                                        IS_ENABLED(CONFIG_ARM) ? arch_tables
+                                                               : NULL);
 
        early_memunmap(config_tables, table_size);
 out:
@@ -238,9 +242,37 @@ void __init efi_init(void)
 
        init_screen_info();
 
+#ifdef CONFIG_ARM
        /* ARM does not permit early mappings to persist across paging_init() */
-       if (IS_ENABLED(CONFIG_ARM))
-               efi_memmap_unmap();
+       efi_memmap_unmap();
+
+       if (cpu_state_table != EFI_INVALID_TABLE_ADDR) {
+               struct efi_arm_entry_state *state;
+               bool dump_state = true;
+
+               state = early_memremap_ro(cpu_state_table,
+                                         sizeof(struct efi_arm_entry_state));
+               if (state == NULL) {
+                       pr_warn("Unable to map CPU entry state table.\n");
+                       return;
+               }
+
+               if ((state->sctlr_before_ebs & 1) == 0)
+                       pr_warn(FW_BUG "EFI stub was entered with MMU and Dcache disabled, please fix your firmware!\n");
+               else if ((state->sctlr_after_ebs & 1) == 0)
+                       pr_warn(FW_BUG "ExitBootServices() returned with MMU and Dcache disabled, please fix your firmware!\n");
+               else
+                       dump_state = false;
+
+               if (dump_state || efi_enabled(EFI_DBG)) {
+                       pr_info("CPSR at EFI stub entry        : 0x%08x\n", state->cpsr_before_ebs);
+                       pr_info("SCTLR at EFI stub entry       : 0x%08x\n", state->sctlr_before_ebs);
+                       pr_info("CPSR after ExitBootServices() : 0x%08x\n", state->cpsr_after_ebs);
+                       pr_info("SCTLR after ExitBootServices(): 0x%08x\n", state->sctlr_after_ebs);
+               }
+               early_memunmap(state, sizeof(struct efi_arm_entry_state));
+       }
+#endif
 }
 
 static bool efifb_overlaps_pci_range(const struct of_pci_range *range)
index c2f1d4e..feb7fe6 100644 (file)
@@ -356,10 +356,7 @@ static struct pstore_info efi_pstore_info = {
 
 static __init int efivars_pstore_init(void)
 {
-       if (!efi_rt_services_supported(EFI_RT_SUPPORTED_VARIABLE_SERVICES))
-               return 0;
-
-       if (!efivars_kobject())
+       if (!efivars_kobject() || !efivar_supports_writes())
                return 0;
 
        if (efivars_pstore_disable)
index 7f1657b..fdd1db0 100644 (file)
@@ -176,11 +176,13 @@ static struct efivar_operations generic_ops;
 static int generic_ops_register(void)
 {
        generic_ops.get_variable = efi.get_variable;
-       generic_ops.set_variable = efi.set_variable;
-       generic_ops.set_variable_nonblocking = efi.set_variable_nonblocking;
        generic_ops.get_next_variable = efi.get_next_variable;
        generic_ops.query_variable_store = efi_query_variable_store;
 
+       if (efi_rt_services_supported(EFI_RT_SUPPORTED_SET_VARIABLE)) {
+               generic_ops.set_variable = efi.set_variable;
+               generic_ops.set_variable_nonblocking = efi.set_variable_nonblocking;
+       }
        return efivars_register(&generic_efivars, &generic_ops, efi_kobj);
 }
 
@@ -189,7 +191,7 @@ static void generic_ops_unregister(void)
        efivars_unregister(&generic_efivars);
 }
 
-#if IS_ENABLED(CONFIG_ACPI)
+#ifdef CONFIG_EFI_CUSTOM_SSDT_OVERLAYS
 #define EFIVAR_SSDT_NAME_MAX   16
 static char efivar_ssdt[EFIVAR_SSDT_NAME_MAX] __initdata;
 static int __init efivar_ssdt_setup(char *str)
@@ -382,7 +384,8 @@ static int __init efisubsys_init(void)
                return -ENOMEM;
        }
 
-       if (efi_rt_services_supported(EFI_RT_SUPPORTED_VARIABLE_SERVICES)) {
+       if (efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE |
+                                     EFI_RT_SUPPORTED_GET_NEXT_VARIABLE_NAME)) {
                efivar_ssdt_load();
                error = generic_ops_register();
                if (error)
@@ -416,7 +419,8 @@ static int __init efisubsys_init(void)
 err_remove_group:
        sysfs_remove_group(efi_kobj, &efi_subsys_attr_group);
 err_unregister:
-       if (efi_rt_services_supported(EFI_RT_SUPPORTED_VARIABLE_SERVICES))
+       if (efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE |
+                                     EFI_RT_SUPPORTED_GET_NEXT_VARIABLE_NAME))
                generic_ops_unregister();
 err_put:
        kobject_put(efi_kobj);
@@ -622,7 +626,8 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
                        rsv = (void *)(p + prsv % PAGE_SIZE);
 
                        /* reserve the entry itself */
-                       memblock_reserve(prsv, EFI_MEMRESERVE_SIZE(rsv->size));
+                       memblock_reserve(prsv,
+                                        struct_size(rsv, entry, rsv->size));
 
                        for (i = 0; i < atomic_read(&rsv->count); i++) {
                                memblock_reserve(rsv->entry[i].base,
index 26528a4..dcea137 100644 (file)
@@ -680,11 +680,8 @@ int efivars_sysfs_init(void)
        struct kobject *parent_kobj = efivars_kobject();
        int error = 0;
 
-       if (!efi_rt_services_supported(EFI_RT_SUPPORTED_VARIABLE_SERVICES))
-               return -ENODEV;
-
        /* No efivars has been registered yet */
-       if (!parent_kobj)
+       if (!parent_kobj || !efivar_supports_writes())
                return 0;
 
        printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
index e3d6926..d591527 100644 (file)
@@ -181,7 +181,7 @@ static int esre_create_sysfs_entry(void *esre, int entry_num)
                rc = kobject_init_and_add(&entry->kobj, &esre1_ktype, NULL,
                                          "entry%d", entry_num);
                if (rc) {
-                       kfree(entry);
+                       kobject_put(&entry->kobj);
                        return rc;
                }
        }
index cc89c4d..1de9878 100644 (file)
@@ -44,7 +44,7 @@ efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr,
        *addr = ALIGN((unsigned long)alloc_addr, align);
 
        if (slack > 0) {
-               int l = (alloc_addr % align) / EFI_PAGE_SIZE;
+               int l = (alloc_addr & (align - 1)) / EFI_PAGE_SIZE;
 
                if (l) {
                        efi_bs_call(free_pages, alloc_addr, slack - l + 1);
index 40243f5..d08e5d5 100644 (file)
@@ -7,10 +7,49 @@
 
 #include "efistub.h"
 
+static efi_guid_t cpu_state_guid = LINUX_EFI_ARM_CPU_STATE_TABLE_GUID;
+
+struct efi_arm_entry_state *efi_entry_state;
+
+static void get_cpu_state(u32 *cpsr, u32 *sctlr)
+{
+       asm("mrs %0, cpsr" : "=r"(*cpsr));
+       if ((*cpsr & MODE_MASK) == HYP_MODE)
+               asm("mrc p15, 4, %0, c1, c0, 0" : "=r"(*sctlr));
+       else
+               asm("mrc p15, 0, %0, c1, c0, 0" : "=r"(*sctlr));
+}
+
 efi_status_t check_platform_features(void)
 {
+       efi_status_t status;
+       u32 cpsr, sctlr;
        int block;
 
+       get_cpu_state(&cpsr, &sctlr);
+
+       efi_info("Entering in %s mode with MMU %sabled\n",
+                ((cpsr & MODE_MASK) == HYP_MODE) ? "HYP" : "SVC",
+                (sctlr & 1) ? "en" : "dis");
+
+       status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
+                            sizeof(*efi_entry_state),
+                            (void **)&efi_entry_state);
+       if (status != EFI_SUCCESS) {
+               efi_err("allocate_pool() failed\n");
+               return status;
+       }
+
+       efi_entry_state->cpsr_before_ebs = cpsr;
+       efi_entry_state->sctlr_before_ebs = sctlr;
+
+       status = efi_bs_call(install_configuration_table, &cpu_state_guid,
+                            efi_entry_state);
+       if (status != EFI_SUCCESS) {
+               efi_err("install_configuration_table() failed\n");
+               goto free_state;
+       }
+
        /* non-LPAE kernels can run anywhere */
        if (!IS_ENABLED(CONFIG_ARM_LPAE))
                return EFI_SUCCESS;
@@ -19,9 +58,22 @@ efi_status_t check_platform_features(void)
        block = cpuid_feature_extract(CPUID_EXT_MMFR0, 0);
        if (block < 5) {
                efi_err("This LPAE kernel is not supported by your CPU\n");
-               return EFI_UNSUPPORTED;
+               status = EFI_UNSUPPORTED;
+               goto drop_table;
        }
        return EFI_SUCCESS;
+
+drop_table:
+       efi_bs_call(install_configuration_table, &cpu_state_guid, NULL);
+free_state:
+       efi_bs_call(free_pool, efi_entry_state);
+       return status;
+}
+
+void efi_handle_post_ebs_state(void)
+{
+       get_cpu_state(&efi_entry_state->cpsr_after_ebs,
+                     &efi_entry_state->sctlr_after_ebs);
 }
 
 static efi_guid_t screen_info_guid = LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID;
index 7f6a57d..e5bfac7 100644 (file)
@@ -35,13 +35,16 @@ efi_status_t check_platform_features(void)
 }
 
 /*
- * Relocatable kernels can fix up the misalignment with respect to
- * MIN_KIMG_ALIGN, so they only require a minimum alignment of EFI_KIMG_ALIGN
- * (which accounts for the alignment of statically allocated objects such as
- * the swapper stack.)
+ * Although relocatable kernels can fix up the misalignment with respect to
+ * MIN_KIMG_ALIGN, the resulting virtual text addresses are subtly out of
+ * sync with those recorded in the vmlinux when kaslr is disabled but the
+ * image required relocation anyway. Therefore retain 2M alignment unless
+ * KASLR is in use.
  */
-static const u64 min_kimg_align = IS_ENABLED(CONFIG_RELOCATABLE) ? EFI_KIMG_ALIGN
-                                                                : MIN_KIMG_ALIGN;
+static u64 min_kimg_align(void)
+{
+       return efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN;
+}
 
 efi_status_t handle_kernel_image(unsigned long *image_addr,
                                 unsigned long *image_size,
@@ -74,21 +77,21 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
 
        kernel_size = _edata - _text;
        kernel_memsize = kernel_size + (_end - _edata);
-       *reserve_size = kernel_memsize + TEXT_OFFSET % min_kimg_align;
+       *reserve_size = kernel_memsize + TEXT_OFFSET % min_kimg_align();
 
        if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && phys_seed != 0) {
                /*
                 * If KASLR is enabled, and we have some randomness available,
                 * locate the kernel at a randomized offset in physical memory.
                 */
-               status = efi_random_alloc(*reserve_size, min_kimg_align,
+               status = efi_random_alloc(*reserve_size, min_kimg_align(),
                                          reserve_addr, phys_seed);
        } else {
                status = EFI_OUT_OF_RESOURCES;
        }
 
        if (status != EFI_SUCCESS) {
-               if (IS_ALIGNED((u64)_text - TEXT_OFFSET, min_kimg_align)) {
+               if (IS_ALIGNED((u64)_text - TEXT_OFFSET, min_kimg_align())) {
                        /*
                         * Just execute from wherever we were loaded by the
                         * UEFI PE/COFF loader if the alignment is suitable.
@@ -99,7 +102,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
                }
 
                status = efi_allocate_pages_aligned(*reserve_size, reserve_addr,
-                                                   ULONG_MAX, min_kimg_align);
+                                                   ULONG_MAX, min_kimg_align());
 
                if (status != EFI_SUCCESS) {
                        efi_err("Failed to relocate kernel\n");
@@ -108,7 +111,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
                }
        }
 
-       *image_addr = *reserve_addr + TEXT_OFFSET % min_kimg_align;
+       *image_addr = *reserve_addr + TEXT_OFFSET % min_kimg_align();
        memcpy((void *)*image_addr, _text, kernel_size);
 
        return EFI_SUCCESS;
index 89f0752..6bca70b 100644 (file)
@@ -19,7 +19,7 @@
 #include "efistub.h"
 
 bool efi_nochunk;
-bool efi_nokaslr;
+bool efi_nokaslr = !IS_ENABLED(CONFIG_RANDOMIZE_BASE);
 bool efi_noinitrd;
 int efi_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
 bool efi_novamap;
@@ -32,6 +32,10 @@ bool __pure __efi_soft_reserve_enabled(void)
        return !efi_nosoftreserve;
 }
 
+/**
+ * efi_char16_puts() - Write a UCS-2 encoded string to the console
+ * @str:       UCS-2 encoded string
+ */
 void efi_char16_puts(efi_char16_t *str)
 {
        efi_call_proto(efi_table_attr(efi_system_table, con_out),
@@ -83,6 +87,10 @@ u32 utf8_to_utf32(const u8 **s8)
        return c32;
 }
 
+/**
+ * efi_puts() - Write a UTF-8 encoded string to the console
+ * @str:       UTF-8 encoded string
+ */
 void efi_puts(const char *str)
 {
        efi_char16_t buf[128];
@@ -113,6 +121,16 @@ void efi_puts(const char *str)
        }
 }
 
+/**
+ * efi_printk() - Print a kernel message
+ * @fmt:       format string
+ *
+ * The first letter of the format string is used to determine the logging level
+ * of the message. If the level is less then the current EFI logging level, the
+ * message is suppressed. The message will be truncated to 255 bytes.
+ *
+ * Return:     number of printed characters
+ */
 int efi_printk(const char *fmt, ...)
 {
        char printf_buf[256];
@@ -154,13 +172,18 @@ int efi_printk(const char *fmt, ...)
        return printed;
 }
 
-/*
- * Parse the ASCII string 'cmdline' for EFI options, denoted by the efi=
+/**
+ * efi_parse_options() - Parse EFI command line options
+ * @cmdline:   kernel command line
+ *
+ * Parse the ASCII string @cmdline for EFI options, denoted by the efi=
  * option, e.g. efi=nochunk.
  *
  * It should be noted that efi= is parsed in two very different
  * environments, first in the early boot environment of the EFI boot
  * stub, and subsequently during the kernel boot.
+ *
+ * Return:     status code
  */
 efi_status_t efi_parse_options(char const *cmdline)
 {
@@ -286,13 +309,21 @@ char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len)
        return (char *)cmdline_addr;
 }
 
-/*
+/**
+ * efi_exit_boot_services() - Exit boot services
+ * @handle:    handle of the exiting image
+ * @map:       pointer to receive the memory map
+ * @priv:      argument to be passed to @priv_func
+ * @priv_func: function to process the memory map before exiting boot services
+ *
  * Handle calling ExitBootServices according to the requirements set out by the
  * spec.  Obtains the current memory map, and returns that info after calling
  * ExitBootServices.  The client must specify a function to perform any
  * processing of the memory map data prior to ExitBootServices.  A client
  * specific structure may be passed to the function via priv.  The client
  * function may be called multiple times.
+ *
+ * Return:     status code
  */
 efi_status_t efi_exit_boot_services(void *handle,
                                    struct efi_boot_memmap *map,
@@ -361,6 +392,11 @@ fail:
        return status;
 }
 
+/**
+ * get_efi_config_table() - retrieve UEFI configuration table
+ * @guid:      GUID of the configuration table to be retrieved
+ * Return:     pointer to the configuration table or NULL
+ */
 void *get_efi_config_table(efi_guid_t guid)
 {
        unsigned long tables = efi_table_attr(efi_system_table, tables);
@@ -408,17 +444,18 @@ static const struct {
 };
 
 /**
- * efi_load_initrd_dev_path - load the initrd from the Linux initrd device path
+ * efi_load_initrd_dev_path() - load the initrd from the Linux initrd device path
  * @load_addr: pointer to store the address where the initrd was loaded
  * @load_size: pointer to store the size of the loaded initrd
  * @max:       upper limit for the initrd memory allocation
- * @return:    %EFI_SUCCESS if the initrd was loaded successfully, in which
- *             case @load_addr and @load_size are assigned accordingly
- *             %EFI_NOT_FOUND if no LoadFile2 protocol exists on the initrd
- *             device path
- *             %EFI_INVALID_PARAMETER if load_addr == NULL or load_size == NULL
- *             %EFI_OUT_OF_RESOURCES if memory allocation failed
- *             %EFI_LOAD_ERROR in all other cases
+ *
+ * Return:
+ * * %EFI_SUCCESS if the initrd was loaded successfully, in which
+ *   case @load_addr and @load_size are assigned accordingly
+ * * %EFI_NOT_FOUND if no LoadFile2 protocol exists on the initrd device path
+ * * %EFI_INVALID_PARAMETER if load_addr == NULL or load_size == NULL
+ * * %EFI_OUT_OF_RESOURCES if memory allocation failed
+ * * %EFI_LOAD_ERROR in all other cases
  */
 static
 efi_status_t efi_load_initrd_dev_path(unsigned long *load_addr,
@@ -481,6 +518,16 @@ efi_status_t efi_load_initrd_cmdline(efi_loaded_image_t *image,
                                    load_addr, load_size);
 }
 
+/**
+ * efi_load_initrd() - Load initial RAM disk
+ * @image:     EFI loaded image protocol
+ * @load_addr: pointer to loaded initrd
+ * @load_size: size of loaded initrd
+ * @soft_limit:        preferred size of allocated memory for loading the initrd
+ * @hard_limit:        minimum size of allocated memory
+ *
+ * Return:     status code
+ */
 efi_status_t efi_load_initrd(efi_loaded_image_t *image,
                             unsigned long *load_addr,
                             unsigned long *load_size,
@@ -505,6 +552,15 @@ efi_status_t efi_load_initrd(efi_loaded_image_t *image,
        return status;
 }
 
+/**
+ * efi_wait_for_key() - Wait for key stroke
+ * @usec:      number of microseconds to wait for key stroke
+ * @key:       key entered
+ *
+ * Wait for up to @usec microseconds for a key stroke.
+ *
+ * Return:     status code, EFI_SUCCESS if key received
+ */
 efi_status_t efi_wait_for_key(unsigned long usec, efi_input_key_t *key)
 {
        efi_event_t events[2], timer;
index e97370b..a5a405d 100644 (file)
@@ -121,23 +121,6 @@ static unsigned long get_dram_base(void)
        return membase;
 }
 
-/*
- * This function handles the architcture specific differences between arm and
- * arm64 regarding where the kernel image must be loaded and any memory that
- * must be reserved. On failure it is required to free all
- * all allocations it has made.
- */
-efi_status_t handle_kernel_image(unsigned long *image_addr,
-                                unsigned long *image_size,
-                                unsigned long *reserve_addr,
-                                unsigned long *reserve_size,
-                                unsigned long dram_base,
-                                efi_loaded_image_t *image);
-
-asmlinkage void __noreturn efi_enter_kernel(unsigned long entrypoint,
-                                           unsigned long fdt_addr,
-                                           unsigned long fdt_size);
-
 /*
  * EFI entry point for the arm/arm64 EFI stubs.  This is the entrypoint
  * that is described in the PE/COFF header.  Most of the code is the same
@@ -329,6 +312,9 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
        if (status != EFI_SUCCESS)
                goto fail_free_initrd;
 
+       if (IS_ENABLED(CONFIG_ARM))
+               efi_handle_post_ebs_state();
+
        efi_enter_kernel(image_addr, fdt_addr, fdt_totalsize((void *)fdt_addr));
        /* not reached */
 
index bcd8c0a..85050f5 100644 (file)
@@ -157,8 +157,14 @@ typedef void (__efiapi *efi_event_notify_t)(efi_event_t, void *);
 #define EFI_EVT_NOTIFY_WAIT    0x00000100U
 #define EFI_EVT_NOTIFY_SIGNAL  0x00000200U
 
-/*
- * boottime->wait_for_event takes an array of events as input.
+/**
+ * efi_set_event_at() - add event to events array
+ *
+ * @events:    array of UEFI events
+ * @ids:       index where to put the event in the array
+ * @event:     event to add to the aray
+ *
+ * boottime->wait_for_event() takes an array of events as input.
  * Provide a helper to set it up correctly for mixed mode.
  */
 static inline
@@ -770,5 +776,23 @@ efi_status_t efi_load_initrd(efi_loaded_image_t *image,
                             unsigned long *load_size,
                             unsigned long soft_limit,
                             unsigned long hard_limit);
+/*
+ * This function handles the architcture specific differences between arm and
+ * arm64 regarding where the kernel image must be loaded and any memory that
+ * must be reserved. On failure it is required to free all
+ * all allocations it has made.
+ */
+efi_status_t handle_kernel_image(unsigned long *image_addr,
+                                unsigned long *image_size,
+                                unsigned long *reserve_addr,
+                                unsigned long *reserve_size,
+                                unsigned long dram_base,
+                                efi_loaded_image_t *image);
+
+asmlinkage void __noreturn efi_enter_kernel(unsigned long entrypoint,
+                                           unsigned long fdt_addr,
+                                           unsigned long fdt_size);
+
+void efi_handle_post_ebs_state(void);
 
 #endif
index 2005e33..630caa6 100644 (file)
@@ -102,12 +102,20 @@ static int find_file_option(const efi_char16_t *cmdline, int cmdline_len,
        if (!found)
                return 0;
 
+       /* Skip any leading slashes */
+       while (cmdline[i] == L'/' || cmdline[i] == L'\\')
+               i++;
+
        while (--result_len > 0 && i < cmdline_len) {
-               if (cmdline[i] == L'\0' ||
-                   cmdline[i] == L'\n' ||
-                   cmdline[i] == L' ')
+               efi_char16_t c = cmdline[i++];
+
+               if (c == L'\0' || c == L'\n' || c == L' ')
                        break;
-               *result++ = cmdline[i++];
+               else if (c == L'/')
+                       /* Replace UNIX dir separators with EFI standard ones */
+                       *result++ = L'\\';
+               else
+                       *result++ = c;
        }
        *result = L'\0';
        return i;
index a700b3c..159fb4e 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 
 #include <linux/ctype.h>
+#include <linux/string.h>
 #include <linux/types.h>
 
 char *skip_spaces(const char *str)
index 5a48d99..3672539 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/efi.h>
 #include <linux/pci.h>
+#include <linux/stddef.h>
 
 #include <asm/efi.h>
 #include <asm/e820/types.h>
@@ -361,8 +362,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
        int options_size = 0;
        efi_status_t status;
        char *cmdline_ptr;
-       unsigned long ramdisk_addr;
-       unsigned long ramdisk_size;
 
        efi_system_table = sys_table_arg;
 
@@ -390,8 +389,9 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
 
        hdr = &boot_params->hdr;
 
-       /* Copy the second sector to boot_params */
-       memcpy(&hdr->jump, image_base + 512, 512);
+       /* Copy the setup header from the second sector to boot_params */
+       memcpy(&hdr->jump, image_base + 512,
+              sizeof(struct setup_header) - offsetof(struct setup_header, jump));
 
        /*
         * Fill out some of the header fields ourselves because the
index 5f2a4d1..973eef2 100644 (file)
@@ -1229,3 +1229,9 @@ out:
        return rv;
 }
 EXPORT_SYMBOL_GPL(efivars_unregister);
+
+int efivar_supports_writes(void)
+{
+       return __efivars && __efivars->ops->set_variable;
+}
+EXPORT_SYMBOL_GPL(efivar_supports_writes);
index fd7f0fb..d17e4d6 100644 (file)
@@ -21,7 +21,7 @@
 struct cbmem_cons {
        u32 size_dont_access_after_boot;
        u32 cursor;
-       u8  body[0];
+       u8  body[];
 } __packed;
 
 #define CURSOR_MASK ((1 << 28) - 1)
index db08122..d23c5c6 100644 (file)
@@ -32,7 +32,7 @@ struct vpd_cbmem {
        u32 version;
        u32 ro_size;
        u32 rw_size;
-       u8  blob[0];
+       u8  blob[];
 };
 
 struct vpd_section {
index 96758b7..7127a04 100644 (file)
@@ -104,7 +104,7 @@ struct ibft_control {
        u16 tgt0_off;
        u16 nic1_off;
        u16 tgt1_off;
-       u16 expansion[0];
+       u16 expansion[];
 } __attribute__((__packed__));
 
 struct ibft_initiator {
index ce75d1d..e025405 100644 (file)
@@ -103,6 +103,6 @@ struct pcdp {
        u8                      creator_id[4];
        u32                     creator_rev;
        u32                     num_uarts;
-       struct pcdp_uart        uart[0];        /* actual size is num_uarts */
+       struct pcdp_uart        uart[]; /* actual size is num_uarts */
        /* remainder of table is pcdp_device structures */
 } __attribute__((packed));
index 873841a..3d6ba42 100644 (file)
@@ -157,8 +157,10 @@ static int alloc_init_cpu_groups(cpumask_var_t **pcpu_groups)
 
        cpu_groups = kcalloc(nb_available_cpus, sizeof(cpu_groups),
                             GFP_KERNEL);
-       if (!cpu_groups)
+       if (!cpu_groups) {
+               free_cpumask_var(tmp);
                return -ENOMEM;
+       }
 
        cpumask_copy(tmp, cpu_online_mask);
 
@@ -167,6 +169,7 @@ static int alloc_init_cpu_groups(cpumask_var_t **pcpu_groups)
                        topology_core_cpumask(cpumask_any(tmp));
 
                if (!alloc_cpumask_var(&cpu_groups[num_groups], GFP_KERNEL)) {
+                       free_cpumask_var(tmp);
                        free_cpu_groups(num_groups, &cpu_groups);
                        return -ENOMEM;
                }
@@ -196,13 +199,12 @@ static int hotplug_tests(void)
        if (!page_buf)
                goto out_free_cpu_groups;
 
-       err = 0;
        /*
         * Of course the last CPU cannot be powered down and cpu_down() should
         * refuse doing that.
         */
        pr_info("Trying to turn off and on again all CPUs\n");
-       err += down_and_up_cpus(cpu_online_mask, offlined_cpus);
+       err = down_and_up_cpus(cpu_online_mask, offlined_cpus);
 
        /*
         * Take down CPUs by cpu group this time. When the last CPU is turned
index 039e0f9..6945c3c 100644 (file)
@@ -605,8 +605,10 @@ static int fw_cfg_register_file(const struct fw_cfg_file *f)
        /* register entry under "/sys/firmware/qemu_fw_cfg/by_key/" */
        err = kobject_init_and_add(&entry->kobj, &fw_cfg_sysfs_entry_ktype,
                                   fw_cfg_sel_ko, "%d", entry->select);
-       if (err)
-               goto err_register;
+       if (err) {
+               kobject_put(&entry->kobj);
+               return err;
+       }
 
        /* add raw binary content access */
        err = sysfs_create_bin_file(&entry->kobj, &fw_cfg_sysfs_attr_raw);
@@ -622,7 +624,6 @@ static int fw_cfg_register_file(const struct fw_cfg_file *f)
 
 err_add_raw:
        kobject_del(&entry->kobj);
-err_register:
        kfree(entry);
        return err;
 }
index ef80988..625c8fd 100644 (file)
@@ -181,6 +181,7 @@ EXPORT_SYMBOL_GPL(rpi_firmware_property);
 static void
 rpi_firmware_print_firmware_revision(struct rpi_firmware *fw)
 {
+       time64_t date_and_time;
        u32 packet;
        int ret = rpi_firmware_property(fw,
                                        RPI_FIRMWARE_GET_FIRMWARE_REVISION,
@@ -189,7 +190,9 @@ rpi_firmware_print_firmware_revision(struct rpi_firmware *fw)
        if (ret)
                return;
 
-       dev_info(fw->cl.dev, "Attached to firmware from %ptT\n", &packet);
+       /* This is not compatible with y2038 */
+       date_and_time = packet;
+       dev_info(fw->cl.dev, "Attached to firmware from %ptT\n", &date_and_time);
 }
 
 static void
index b2408a7..7cd5a29 100644 (file)
@@ -208,7 +208,7 @@ config FPGA_DFL_PCI
 
 config FPGA_MGR_ZYNQMP_FPGA
        tristate "Xilinx ZynqMP FPGA"
-       depends on ARCH_ZYNQMP || COMPILE_TEST
+       depends on ZYNQMP_FIRMWARE || (!ZYNQMP_FIRMWARE && COMPILE_TEST)
        help
          FPGA manager driver support for Xilinx ZynqMP FPGAs.
          This driver uses the processor configuration port(PCAP)
index b0c3178..3fa2c59 100644 (file)
@@ -83,7 +83,8 @@ int __afu_port_disable(struct platform_device *pdev)
         * on this port and minimum soft reset pulse width has elapsed.
         * Driver polls port_soft_reset_ack to determine if reset done by HW.
         */
-       if (readq_poll_timeout(base + PORT_HDR_CTRL, v, v & PORT_CTRL_SFTRST,
+       if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
+                              v & PORT_CTRL_SFTRST_ACK,
                               RST_POLL_INVL, RST_POLL_TIMEOUT)) {
                dev_err(&pdev->dev, "timeout, fail to reset device\n");
                return -ETIMEDOUT;
index 5387550..a78c409 100644 (file)
@@ -227,7 +227,6 @@ static int cci_pci_sriov_configure(struct pci_dev *pcidev, int num_vfs)
 {
        struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
        struct dfl_fpga_cdev *cdev = drvdata->cdev;
-       int ret = 0;
 
        if (!num_vfs) {
                /*
@@ -239,6 +238,8 @@ static int cci_pci_sriov_configure(struct pci_dev *pcidev, int num_vfs)
                dfl_fpga_cdev_config_ports_pf(cdev);
 
        } else {
+               int ret;
+
                /*
                 * before enable SRIOV, put released ports into VF access mode
                 * first of all.
index 5640efe..5bda38e 100644 (file)
@@ -64,6 +64,7 @@ static int arizona_gpio_get(struct gpio_chip *chip, unsigned offset)
                ret = pm_runtime_get_sync(chip->parent);
                if (ret < 0) {
                        dev_err(chip->parent, "Failed to resume: %d\n", ret);
+                       pm_runtime_put_autosuspend(chip->parent);
                        return ret;
                }
 
@@ -72,12 +73,15 @@ static int arizona_gpio_get(struct gpio_chip *chip, unsigned offset)
                if (ret < 0) {
                        dev_err(chip->parent, "Failed to drop cache: %d\n",
                                ret);
+                       pm_runtime_put_autosuspend(chip->parent);
                        return ret;
                }
 
                ret = regmap_read(arizona->regmap, reg, &val);
-               if (ret < 0)
+               if (ret < 0) {
+                       pm_runtime_put_autosuspend(chip->parent);
                        return ret;
+               }
 
                pm_runtime_mark_last_busy(chip->parent);
                pm_runtime_put_autosuspend(chip->parent);
@@ -106,6 +110,7 @@ static int arizona_gpio_direction_out(struct gpio_chip *chip,
                ret = pm_runtime_get_sync(chip->parent);
                if (ret < 0) {
                        dev_err(chip->parent, "Failed to resume: %d\n", ret);
+                       pm_runtime_put(chip->parent);
                        return ret;
                }
        }
index 1fca8dd..a3b9bde 100644 (file)
@@ -107,6 +107,84 @@ static const struct i2c_device_id pca953x_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, pca953x_id);
 
+#ifdef CONFIG_GPIO_PCA953X_IRQ
+
+#include <linux/dmi.h>
+#include <linux/gpio.h>
+#include <linux/list.h>
+
+static const struct dmi_system_id pca953x_dmi_acpi_irq_info[] = {
+       {
+               /*
+                * On Intel Galileo Gen 2 board the IRQ pin of one of
+                * the I²C GPIO expanders, which has GpioInt() resource,
+                * is provided as an absolute number instead of being
+                * relative. Since first controller (gpio-sch.c) and
+                * second (gpio-dwapb.c) are at the fixed bases, we may
+                * safely refer to the number in the global space to get
+                * an IRQ out of it.
+                */
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_BOARD_NAME, "GalileoGen2"),
+               },
+       },
+       {}
+};
+
+#ifdef CONFIG_ACPI
+static int pca953x_acpi_get_pin(struct acpi_resource *ares, void *data)
+{
+       struct acpi_resource_gpio *agpio;
+       int *pin = data;
+
+       if (acpi_gpio_get_irq_resource(ares, &agpio))
+               *pin = agpio->pin_table[0];
+       return 1;
+}
+
+static int pca953x_acpi_find_pin(struct device *dev)
+{
+       struct acpi_device *adev = ACPI_COMPANION(dev);
+       int pin = -ENOENT, ret;
+       LIST_HEAD(r);
+
+       ret = acpi_dev_get_resources(adev, &r, pca953x_acpi_get_pin, &pin);
+       acpi_dev_free_resource_list(&r);
+       if (ret < 0)
+               return ret;
+
+       return pin;
+}
+#else
+static inline int pca953x_acpi_find_pin(struct device *dev) { return -ENXIO; }
+#endif
+
+static int pca953x_acpi_get_irq(struct device *dev)
+{
+       int pin, ret;
+
+       pin = pca953x_acpi_find_pin(dev);
+       if (pin < 0)
+               return pin;
+
+       dev_info(dev, "Applying ACPI interrupt quirk (GPIO %d)\n", pin);
+
+       if (!gpio_is_valid(pin))
+               return -EINVAL;
+
+       ret = gpio_request(pin, "pca953x interrupt");
+       if (ret)
+               return ret;
+
+       ret = gpio_to_irq(pin);
+
+       /* When pin is used as an IRQ, no need to keep it requested */
+       gpio_free(pin);
+
+       return ret;
+}
+#endif
+
 static const struct acpi_device_id pca953x_acpi_ids[] = {
        { "INT3491", 16 | PCA953X_TYPE | PCA_LATCH_INT, },
        { }
@@ -322,6 +400,7 @@ static const struct regmap_config pca953x_ai_i2c_regmap = {
        .writeable_reg = pca953x_writeable_register,
        .volatile_reg = pca953x_volatile_register,
 
+       .disable_locking = true,
        .cache_type = REGCACHE_RBTREE,
        .max_register = 0x7f,
 };
@@ -623,8 +702,6 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
        DECLARE_BITMAP(reg_direction, MAX_LINE);
        int level;
 
-       pca953x_read_regs(chip, chip->regs->direction, reg_direction);
-
        if (chip->driver_data & PCA_PCAL) {
                /* Enable latch on interrupt-enabled inputs */
                pca953x_write_regs(chip, PCAL953X_IN_LATCH, chip->irq_mask);
@@ -635,7 +712,11 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
                pca953x_write_regs(chip, PCAL953X_INT_MASK, irq_mask);
        }
 
+       /* Switch direction to input if needed */
+       pca953x_read_regs(chip, chip->regs->direction, reg_direction);
+
        bitmap_or(irq_mask, chip->irq_trig_fall, chip->irq_trig_raise, gc->ngpio);
+       bitmap_complement(reg_direction, reg_direction, gc->ngpio);
        bitmap_and(irq_mask, irq_mask, reg_direction, gc->ngpio);
 
        /* Look for any newly setup interrupt */
@@ -734,14 +815,16 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
        struct gpio_chip *gc = &chip->gpio_chip;
        DECLARE_BITMAP(pending, MAX_LINE);
        int level;
+       bool ret;
 
-       if (!pca953x_irq_pending(chip, pending))
-               return IRQ_NONE;
+       mutex_lock(&chip->i2c_lock);
+       ret = pca953x_irq_pending(chip, pending);
+       mutex_unlock(&chip->i2c_lock);
 
        for_each_set_bit(level, pending, gc->ngpio)
                handle_nested_irq(irq_find_mapping(gc->irq.domain, level));
 
-       return IRQ_HANDLED;
+       return IRQ_RETVAL(ret);
 }
 
 static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base)
@@ -752,6 +835,12 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base)
        DECLARE_BITMAP(irq_stat, MAX_LINE);
        int ret;
 
+       if (dmi_first_match(pca953x_dmi_acpi_irq_info)) {
+               ret = pca953x_acpi_get_irq(&client->dev);
+               if (ret > 0)
+                       client->irq = ret;
+       }
+
        if (!client->irq)
                return 0;
 
index 58f9d8c..44f9276 100644 (file)
@@ -204,6 +204,7 @@ amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
                                (mode_info->atom_context->bios + data_offset);
                        switch (crev) {
                        case 11:
+                       case 12:
                                mem_channel_number = igp_info->v11.umachannelnumber;
                                /* channel width is 64 */
                                if (vram_width)
index d33cb34..a414da2 100644 (file)
@@ -1295,27 +1295,37 @@ static void amdgpu_ib_preempt_job_recovery(struct drm_gpu_scheduler *sched)
 static void amdgpu_ib_preempt_mark_partial_job(struct amdgpu_ring *ring)
 {
        struct amdgpu_job *job;
-       struct drm_sched_job *s_job;
+       struct drm_sched_job *s_job, *tmp;
        uint32_t preempt_seq;
        struct dma_fence *fence, **ptr;
        struct amdgpu_fence_driver *drv = &ring->fence_drv;
        struct drm_gpu_scheduler *sched = &ring->sched;
+       bool preempted = true;
 
        if (ring->funcs->type != AMDGPU_RING_TYPE_GFX)
                return;
 
        preempt_seq = le32_to_cpu(*(drv->cpu_addr + 2));
-       if (preempt_seq <= atomic_read(&drv->last_seq))
-               return;
+       if (preempt_seq <= atomic_read(&drv->last_seq)) {
+               preempted = false;
+               goto no_preempt;
+       }
 
        preempt_seq &= drv->num_fences_mask;
        ptr = &drv->fences[preempt_seq];
        fence = rcu_dereference_protected(*ptr, 1);
 
+no_preempt:
        spin_lock(&sched->job_list_lock);
-       list_for_each_entry(s_job, &sched->ring_mirror_list, node) {
+       list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) {
+               if (dma_fence_is_signaled(&s_job->s_fence->finished)) {
+                       /* remove job from ring_mirror_list */
+                       list_del_init(&s_job->node);
+                       sched->ops->free_job(s_job);
+                       continue;
+               }
                job = to_amdgpu_job(s_job);
-               if (job->fence == fence)
+               if (preempted && job->fence == fence)
                        /* mark the job as preempted */
                        job->preemption_status |= AMDGPU_IB_PREEMPTED;
        }
index 4720718..4fb4c3b 100644 (file)
@@ -37,7 +37,8 @@ static void amdgpu_job_timedout(struct drm_sched_job *s_job)
 
        memset(&ti, 0, sizeof(struct amdgpu_task_info));
 
-       if (amdgpu_ring_soft_recovery(ring, job->vmid, s_job->s_fence->parent)) {
+       if (amdgpu_gpu_recovery &&
+           amdgpu_ring_soft_recovery(ring, job->vmid, s_job->s_fence->parent)) {
                DRM_ERROR("ring %s timeout, but soft recovered\n",
                          s_job->sched->name);
                return;
index d7e17e3..2129209 100644 (file)
@@ -692,9 +692,10 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
                return n ? -EFAULT : 0;
        }
        case AMDGPU_INFO_DEV_INFO: {
-               struct drm_amdgpu_info_device dev_info = {};
+               struct drm_amdgpu_info_device dev_info;
                uint64_t vm_size;
 
+               memset(&dev_info, 0, sizeof(dev_info));
                dev_info.device_id = dev->pdev->device;
                dev_info.chip_rev = adev->rev_id;
                dev_info.external_rev = adev->external_rev_id;
index 775e389..02e6f8c 100644 (file)
@@ -696,7 +696,7 @@ static ssize_t amdgpu_set_pp_table(struct device *dev,
  * default power levels, write "r" (reset) to the file to reset them.
  *
  *
- * < For Vega20 >
+ * < For Vega20 and newer ASICs >
  *
  * Reading the file will display:
  *
@@ -1668,7 +1668,7 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev,
 }
 
 /**
- * DOC: busy_percent
+ * DOC: gpu_busy_percent
  *
  * The amdgpu driver provides a sysfs API for reading how busy the GPU
  * is as a percentage.  The file gpu_busy_percent is used for this.
@@ -2784,7 +2784,7 @@ static ssize_t amdgpu_hwmon_show_sclk(struct device *dev,
        if (r)
                return r;
 
-       return snprintf(buf, PAGE_SIZE, "%d\n", sclk * 10 * 1000);
+       return snprintf(buf, PAGE_SIZE, "%u\n", sclk * 10 * 1000);
 }
 
 static ssize_t amdgpu_hwmon_show_sclk_label(struct device *dev,
@@ -2819,7 +2819,7 @@ static ssize_t amdgpu_hwmon_show_mclk(struct device *dev,
        if (r)
                return r;
 
-       return snprintf(buf, PAGE_SIZE, "%d\n", mclk * 10 * 1000);
+       return snprintf(buf, PAGE_SIZE, "%u\n", mclk * 10 * 1000);
 }
 
 static ssize_t amdgpu_hwmon_show_mclk_label(struct device *dev,
index 7301fdc..ef3269c 100644 (file)
@@ -372,6 +372,52 @@ static int psp_tmr_load(struct psp_context *psp)
        return ret;
 }
 
+static void psp_prep_tmr_unload_cmd_buf(struct psp_context *psp,
+                                       struct psp_gfx_cmd_resp *cmd)
+{
+       if (amdgpu_sriov_vf(psp->adev))
+               cmd->cmd_id = GFX_CMD_ID_DESTROY_VMR;
+       else
+               cmd->cmd_id = GFX_CMD_ID_DESTROY_TMR;
+}
+
+static int psp_tmr_unload(struct psp_context *psp)
+{
+       int ret;
+       struct psp_gfx_cmd_resp *cmd;
+
+       cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
+       if (!cmd)
+               return -ENOMEM;
+
+       psp_prep_tmr_unload_cmd_buf(psp, cmd);
+       DRM_INFO("free PSP TMR buffer\n");
+
+       ret = psp_cmd_submit_buf(psp, NULL, cmd,
+                                psp->fence_buf_mc_addr);
+
+       kfree(cmd);
+
+       return ret;
+}
+
+static int psp_tmr_terminate(struct psp_context *psp)
+{
+       int ret;
+       void *tmr_buf;
+       void **pptr;
+
+       ret = psp_tmr_unload(psp);
+       if (ret)
+               return ret;
+
+       /* free TMR memory buffer */
+       pptr = amdgpu_sriov_vf(psp->adev) ? &tmr_buf : NULL;
+       amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, pptr);
+
+       return 0;
+}
+
 static void psp_prep_asd_load_cmd_buf(struct psp_gfx_cmd_resp *cmd,
                                uint64_t asd_mc, uint32_t size)
 {
@@ -1779,8 +1825,6 @@ static int psp_hw_fini(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        struct psp_context *psp = &adev->psp;
-       void *tmr_buf;
-       void **pptr;
 
        if (psp->adev->psp.ta_fw) {
                psp_ras_terminate(psp);
@@ -1790,10 +1834,9 @@ static int psp_hw_fini(void *handle)
 
        psp_asd_unload(psp);
 
+       psp_tmr_terminate(psp);
        psp_ring_destroy(psp, PSP_RING_TYPE__KM);
 
-       pptr = amdgpu_sriov_vf(psp->adev) ? &tmr_buf : NULL;
-       amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, pptr);
        amdgpu_bo_free_kernel(&psp->fw_pri_bo,
                              &psp->fw_pri_mc_addr, &psp->fw_pri_buf);
        amdgpu_bo_free_kernel(&psp->fence_buf_bo,
@@ -1840,6 +1883,18 @@ static int psp_suspend(void *handle)
                }
        }
 
+       ret = psp_asd_unload(psp);
+       if (ret) {
+               DRM_ERROR("Failed to unload asd\n");
+               return ret;
+       }
+
+       ret = psp_tmr_terminate(psp);
+       if (ret) {
+               DRM_ERROR("Falied to terminate tmr\n");
+               return ret;
+       }
+
        ret = psp_ring_stop(psp, PSP_RING_TYPE__KM);
        if (ret) {
                DRM_ERROR("PSP ring stop failed\n");
index bd5dd4f..fac77a8 100644 (file)
@@ -7513,12 +7513,17 @@ static int gfx_v10_0_ring_preempt_ib(struct amdgpu_ring *ring)
        struct amdgpu_device *adev = ring->adev;
        struct amdgpu_kiq *kiq = &adev->gfx.kiq;
        struct amdgpu_ring *kiq_ring = &kiq->ring;
+       unsigned long flags;
 
        if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
                return -EINVAL;
 
-       if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size))
+       spin_lock_irqsave(&kiq->ring_lock, flags);
+
+       if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size)) {
+               spin_unlock_irqrestore(&kiq->ring_lock, flags);
                return -ENOMEM;
+       }
 
        /* assert preemption condition */
        amdgpu_ring_set_preempt_cond_exec(ring, false);
@@ -7529,6 +7534,8 @@ static int gfx_v10_0_ring_preempt_ib(struct amdgpu_ring *ring)
                                   ++ring->trail_seq);
        amdgpu_ring_commit(kiq_ring);
 
+       spin_unlock_irqrestore(&kiq->ring_lock, flags);
+
        /* poll the trailing fence */
        for (i = 0; i < adev->usec_timeout; i++) {
                if (ring->trail_seq ==
index b544baf..8fb66e5 100644 (file)
@@ -314,30 +314,20 @@ static uint64_t sdma_v5_0_ring_get_rptr(struct amdgpu_ring *ring)
 static uint64_t sdma_v5_0_ring_get_wptr(struct amdgpu_ring *ring)
 {
        struct amdgpu_device *adev = ring->adev;
-       u64 *wptr = NULL;
-       uint64_t local_wptr = 0;
+       u64 wptr;
 
        if (ring->use_doorbell) {
                /* XXX check if swapping is necessary on BE */
-               wptr = ((u64 *)&adev->wb.wb[ring->wptr_offs]);
-               DRM_DEBUG("wptr/doorbell before shift == 0x%016llx\n", *wptr);
-               *wptr = (*wptr) >> 2;
-               DRM_DEBUG("wptr/doorbell after shift == 0x%016llx\n", *wptr);
+               wptr = READ_ONCE(*((u64 *)&adev->wb.wb[ring->wptr_offs]));
+               DRM_DEBUG("wptr/doorbell before shift == 0x%016llx\n", wptr);
        } else {
-               u32 lowbit, highbit;
-
-               wptr = &local_wptr;
-               lowbit = RREG32(sdma_v5_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR)) >> 2;
-               highbit = RREG32(sdma_v5_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR_HI)) >> 2;
-
-               DRM_DEBUG("wptr [%i]high== 0x%08x low==0x%08x\n",
-                               ring->me, highbit, lowbit);
-               *wptr = highbit;
-               *wptr = (*wptr) << 32;
-               *wptr |= lowbit;
+               wptr = RREG32(sdma_v5_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR_HI));
+               wptr = wptr << 32;
+               wptr |= RREG32(sdma_v5_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR));
+               DRM_DEBUG("wptr before shift [%i] wptr == 0x%016llx\n", ring->me, wptr);
        }
 
-       return *wptr;
+       return wptr >> 2;
 }
 
 /**
@@ -1298,8 +1288,12 @@ static int sdma_v5_0_sw_fini(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        int i;
 
-       for (i = 0; i < adev->sdma.num_instances; i++)
+       for (i = 0; i < adev->sdma.num_instances; i++) {
+               if (adev->sdma.instance[i].fw != NULL)
+                       release_firmware(adev->sdma.instance[i].fw);
+
                amdgpu_ring_fini(&adev->sdma.instance[i].ring);
+       }
 
        return 0;
 }
index f0587d9..fee6092 100644 (file)
@@ -40,6 +40,7 @@
 #include <drm/drm_file.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_device.h>
+#include <drm/drm_ioctl.h>
 #include <kgd_kfd_interface.h>
 #include <linux/swap.h>
 
@@ -1076,7 +1077,7 @@ static inline int kfd_devcgroup_check_permission(struct kfd_dev *kfd)
 #if defined(CONFIG_CGROUP_DEVICE) || defined(CONFIG_CGROUP_BPF)
        struct drm_device *ddev = kfd->ddev;
 
-       return devcgroup_check_permission(DEVCG_DEV_CHAR, ddev->driver->major,
+       return devcgroup_check_permission(DEVCG_DEV_CHAR, DRM_MAJOR,
                                          ddev->render->index,
                                          DEVCG_ACC_WRITE | DEVCG_ACC_READ);
 #else
index d27221d..0e0c42e 100644 (file)
@@ -428,6 +428,7 @@ struct kfd_process *kfd_create_process(struct file *filep)
                                           (int)process->lead_thread->pid);
                if (ret) {
                        pr_warn("Creating procfs pid directory failed");
+                       kobject_put(process->kobj);
                        goto out;
                }
 
index 7ced9f8..710edc7 100644 (file)
@@ -974,6 +974,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
        /* Update the actual used number of crtc */
        adev->mode_info.num_crtc = adev->dm.display_indexes_num;
 
+       /* create fake encoders for MST */
+       dm_dp_create_fake_mst_encoders(adev);
+
        /* TODO: Add_display_info? */
 
        /* TODO use dynamic cursor width */
@@ -997,6 +1000,12 @@ error:
 
 static void amdgpu_dm_fini(struct amdgpu_device *adev)
 {
+       int i;
+
+       for (i = 0; i < adev->dm.display_indexes_num; i++) {
+               drm_encoder_cleanup(&adev->dm.mst_encoders[i].base);
+       }
+
        amdgpu_dm_audio_fini(adev);
 
        amdgpu_dm_destroy_drm_device(&adev->dm);
@@ -1358,7 +1367,7 @@ static int dm_late_init(void *handle)
        struct dmcu *dmcu = NULL;
        bool ret;
 
-       if (!adev->dm.fw_dmcu)
+       if (!adev->dm.fw_dmcu && !adev->dm.dmub_fw)
                return detect_mst_link_for_all_connectors(adev->ddev);
 
        dmcu = adev->dm.dc->res_pool->dmcu;
@@ -2010,6 +2019,7 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
        struct amdgpu_display_manager *dm;
        struct drm_connector *conn_base;
        struct amdgpu_device *adev;
+       struct dc_link *link = NULL;
        static const u8 pre_computed_values[] = {
                50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69,
                71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98};
@@ -2017,6 +2027,10 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
        if (!aconnector || !aconnector->dc_link)
                return;
 
+       link = aconnector->dc_link;
+       if (link->connector_signal != SIGNAL_TYPE_EDP)
+               return;
+
        conn_base = &aconnector->base;
        adev = conn_base->dev->dev_private;
        dm = &adev->dm;
@@ -5024,7 +5038,8 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
        struct drm_connector *connector = &aconnector->base;
        struct amdgpu_device *adev = connector->dev->dev_private;
        struct dc_stream_state *stream;
-       int requested_bpc = connector->state ? connector->state->max_requested_bpc : 8;
+       const struct drm_connector_state *drm_state = dm_state ? &dm_state->base : NULL;
+       int requested_bpc = drm_state ? drm_state->max_requested_bpc : 8;
        enum dc_status dc_result = DC_OK;
 
        do {
@@ -8702,20 +8717,38 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
                 * the same resource. If we have a new DC context as part of
                 * the DM atomic state from validation we need to free it and
                 * retain the existing one instead.
+                *
+                * Furthermore, since the DM atomic state only contains the DC
+                * context and can safely be annulled, we can free the state
+                * and clear the associated private object now to free
+                * some memory and avoid a possible use-after-free later.
                 */
-               struct dm_atomic_state *new_dm_state, *old_dm_state;
 
-               new_dm_state = dm_atomic_get_new_state(state);
-               old_dm_state = dm_atomic_get_old_state(state);
+               for (i = 0; i < state->num_private_objs; i++) {
+                       struct drm_private_obj *obj = state->private_objs[i].ptr;
 
-               if (new_dm_state && old_dm_state) {
-                       if (new_dm_state->context)
-                               dc_release_state(new_dm_state->context);
+                       if (obj->funcs == adev->dm.atomic_obj.funcs) {
+                               int j = state->num_private_objs-1;
 
-                       new_dm_state->context = old_dm_state->context;
+                               dm_atomic_destroy_state(obj,
+                                               state->private_objs[i].state);
+
+                               /* If i is not at the end of the array then the
+                                * last element needs to be moved to where i was
+                                * before the array can safely be truncated.
+                                */
+                               if (i != j)
+                                       state->private_objs[i] =
+                                               state->private_objs[j];
 
-                       if (old_dm_state->context)
-                               dc_retain_state(old_dm_state->context);
+                               state->private_objs[j].ptr = NULL;
+                               state->private_objs[j].state = NULL;
+                               state->private_objs[j].old_state = NULL;
+                               state->private_objs[j].new_state = NULL;
+
+                               state->num_private_objs = j;
+                               break;
+                       }
                }
        }
 
index d61186f..648180c 100644 (file)
@@ -43,6 +43,9 @@
  */
 
 #define AMDGPU_DM_MAX_DISPLAY_INDEX 31
+
+#define AMDGPU_DM_MAX_CRTC 6
+
 /*
 #include "include/amdgpu_dal_power_if.h"
 #include "amdgpu_dm_irq.h"
@@ -328,6 +331,13 @@ struct amdgpu_display_manager {
         * available in FW
         */
        const struct gpu_info_soc_bounding_box_v1_0 *soc_bounding_box;
+
+       /**
+        * @mst_encoders:
+        *
+        * fake encoders used for DP MST.
+        */
+       struct amdgpu_encoder mst_encoders[AMDGPU_DM_MAX_CRTC];
 };
 
 struct amdgpu_dm_connector {
@@ -356,7 +366,6 @@ struct amdgpu_dm_connector {
        struct amdgpu_dm_dp_aux dm_dp_aux;
        struct drm_dp_mst_port *port;
        struct amdgpu_dm_connector *mst_port;
-       struct amdgpu_encoder *mst_encoder;
        struct drm_dp_aux *dsc_aux;
 
        /* TODO see if we can merge with ddc_bus or make a dm_connector */
index 076af26..1d692f4 100644 (file)
@@ -1058,7 +1058,6 @@ static const struct {
                {"link_settings", &dp_link_settings_debugfs_fops},
                {"phy_settings", &dp_phy_settings_debugfs_fop},
                {"test_pattern", &dp_phy_test_pattern_fops},
-               {"output_bpc", &output_bpc_fops},
                {"vrr_range", &vrr_range_fops},
 #ifdef CONFIG_DRM_AMD_DC_HDCP
                {"hdcp_sink_capability", &hdcp_sink_capability_fops},
@@ -1142,6 +1141,9 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector)
        debugfs_create_file_unsafe("force_yuv420_output", 0644, dir, connector,
                                   &force_yuv420_output_fops);
 
+       debugfs_create_file("output_bpc", 0644, dir, connector,
+                           &output_bpc_fops);
+
        connector->debugfs_dpcd_address = 0;
        connector->debugfs_dpcd_size = 0;
 
index dcf84a6..949d10e 100644 (file)
@@ -510,8 +510,10 @@ static ssize_t srm_data_read(struct file *filp, struct kobject *kobj, struct bin
 
        srm = psp_get_srm(work->hdcp.config.psp.handle, &srm_version, &srm_size);
 
-       if (!srm)
-               return -EINVAL;
+       if (!srm) {
+               ret = -EINVAL;
+               goto ret;
+       }
 
        if (pos >= srm_size)
                ret = 0;
index ae0a7ef..e5ecc5a 100644 (file)
@@ -95,7 +95,6 @@ dm_dp_mst_connector_destroy(struct drm_connector *connector)
 {
        struct amdgpu_dm_connector *aconnector =
                to_amdgpu_dm_connector(connector);
-       struct amdgpu_encoder *amdgpu_encoder = aconnector->mst_encoder;
 
        if (aconnector->dc_sink) {
                dc_link_remove_remote_sink(aconnector->dc_link,
@@ -105,8 +104,6 @@ dm_dp_mst_connector_destroy(struct drm_connector *connector)
 
        kfree(aconnector->edid);
 
-       drm_encoder_cleanup(&amdgpu_encoder->base);
-       kfree(amdgpu_encoder);
        drm_connector_cleanup(connector);
        drm_dp_mst_put_port_malloc(aconnector->port);
        kfree(aconnector);
@@ -243,7 +240,11 @@ static struct drm_encoder *
 dm_mst_atomic_best_encoder(struct drm_connector *connector,
                           struct drm_connector_state *connector_state)
 {
-       return &to_amdgpu_dm_connector(connector)->mst_encoder->base;
+       struct drm_device *dev = connector->dev;
+       struct amdgpu_device *adev = dev->dev_private;
+       struct amdgpu_crtc *acrtc = to_amdgpu_crtc(connector_state->crtc);
+
+       return &adev->dm.mst_encoders[acrtc->crtc_id].base;
 }
 
 static int
@@ -306,31 +307,27 @@ static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = {
        .destroy = amdgpu_dm_encoder_destroy,
 };
 
-static struct amdgpu_encoder *
-dm_dp_create_fake_mst_encoder(struct amdgpu_dm_connector *connector)
+void
+dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev)
 {
-       struct drm_device *dev = connector->base.dev;
-       struct amdgpu_device *adev = dev->dev_private;
-       struct amdgpu_encoder *amdgpu_encoder;
-       struct drm_encoder *encoder;
-
-       amdgpu_encoder = kzalloc(sizeof(*amdgpu_encoder), GFP_KERNEL);
-       if (!amdgpu_encoder)
-               return NULL;
+       struct drm_device *dev = adev->ddev;
+       int i;
 
-       encoder = &amdgpu_encoder->base;
-       encoder->possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev);
+       for (i = 0; i < adev->dm.display_indexes_num; i++) {
+               struct amdgpu_encoder *amdgpu_encoder = &adev->dm.mst_encoders[i];
+               struct drm_encoder *encoder = &amdgpu_encoder->base;
 
-       drm_encoder_init(
-               dev,
-               &amdgpu_encoder->base,
-               &amdgpu_dm_encoder_funcs,
-               DRM_MODE_ENCODER_DPMST,
-               NULL);
+               encoder->possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev);
 
-       drm_encoder_helper_add(encoder, &amdgpu_dm_encoder_helper_funcs);
+               drm_encoder_init(
+                       dev,
+                       &amdgpu_encoder->base,
+                       &amdgpu_dm_encoder_funcs,
+                       DRM_MODE_ENCODER_DPMST,
+                       NULL);
 
-       return amdgpu_encoder;
+               drm_encoder_helper_add(encoder, &amdgpu_dm_encoder_helper_funcs);
+       }
 }
 
 static struct drm_connector *
@@ -343,6 +340,7 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
        struct amdgpu_device *adev = dev->dev_private;
        struct amdgpu_dm_connector *aconnector;
        struct drm_connector *connector;
+       int i;
 
        aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL);
        if (!aconnector)
@@ -369,9 +367,10 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
                master->dc_link,
                master->connector_id);
 
-       aconnector->mst_encoder = dm_dp_create_fake_mst_encoder(master);
-       drm_connector_attach_encoder(&aconnector->base,
-                                    &aconnector->mst_encoder->base);
+       for (i = 0; i < adev->dm.display_indexes_num; i++) {
+               drm_connector_attach_encoder(&aconnector->base,
+                                            &adev->dm.mst_encoders[i].base);
+       }
 
        connector->max_bpc_property = master->base.max_bpc_property;
        if (connector->max_bpc_property)
index d2c5657..b38bd68 100644 (file)
@@ -35,6 +35,9 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
                                       struct amdgpu_dm_connector *aconnector,
                                       int link_index);
 
+void
+dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev);
+
 #if defined(CONFIG_DRM_AMD_DC_DCN)
 bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
                                       struct dc_state *dc_state);
index 6f93a6c..d016f50 100644 (file)
@@ -2538,10 +2538,12 @@ void dc_commit_updates_for_stream(struct dc *dc,
 
        copy_stream_update_to_stream(dc, context, stream, stream_update);
 
-       if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) {
-               DC_ERROR("Mode validation failed for stream update!\n");
-               dc_release_state(context);
-               return;
+       if (update_type > UPDATE_TYPE_FAST) {
+               if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) {
+                       DC_ERROR("Mode validation failed for stream update!\n");
+                       dc_release_state(context);
+                       return;
+               }
        }
 
        commit_planes_for_stream(
index 4f0e720..470c827 100644 (file)
@@ -56,7 +56,7 @@ void update_stream_signal(struct dc_stream_state *stream, struct dc_sink *sink)
        }
 }
 
-static void dc_stream_construct(struct dc_stream_state *stream,
+static bool dc_stream_construct(struct dc_stream_state *stream,
        struct dc_sink *dc_sink_data)
 {
        uint32_t i = 0;
@@ -118,11 +118,17 @@ static void dc_stream_construct(struct dc_stream_state *stream,
        update_stream_signal(stream, dc_sink_data);
 
        stream->out_transfer_func = dc_create_transfer_func();
+       if (stream->out_transfer_func == NULL) {
+               dc_sink_release(dc_sink_data);
+               return false;
+       }
        stream->out_transfer_func->type = TF_TYPE_BYPASS;
        stream->out_transfer_func->ctx = stream->ctx;
 
        stream->stream_id = stream->ctx->dc_stream_id_count;
        stream->ctx->dc_stream_id_count++;
+
+       return true;
 }
 
 static void dc_stream_destruct(struct dc_stream_state *stream)
@@ -164,13 +170,20 @@ struct dc_stream_state *dc_create_stream_for_sink(
 
        stream = kzalloc(sizeof(struct dc_stream_state), GFP_KERNEL);
        if (stream == NULL)
-               return NULL;
+               goto alloc_fail;
 
-       dc_stream_construct(stream, sink);
+       if (dc_stream_construct(stream, sink) == false)
+               goto construct_fail;
 
        kref_init(&stream->refcount);
 
        return stream;
+
+construct_fail:
+       kfree(stream);
+
+alloc_fail:
+       return NULL;
 }
 
 struct dc_stream_state *dc_copy_stream(const struct dc_stream_state *stream)
index 3f66868..ea29cf9 100644 (file)
@@ -28,8 +28,6 @@ endif
 endif
 
 CFLAGS_$(AMDDALPATH)/dc/dsc/rc_calc.o := $(dsc_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dsc/rc_calc_dpi.o := $(dsc_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dsc/dc_dsc.o := $(dsc_ccflags)
 
 DSC = dc_dsc.o rc_calc.o rc_calc_dpi.o
 
index 0ea6662..0c7f247 100644 (file)
  * Author: AMD
  */
 
+#include <drm/drm_dsc.h>
 #include "dc_hw_types.h"
 #include "dsc.h"
 #include <drm/drm_dp_helper.h>
 #include "dc.h"
+#include "rc_calc.h"
 
 /* This module's internal functions */
 
@@ -304,22 +306,6 @@ static inline uint32_t dsc_div_by_10_round_up(uint32_t value)
        return (value + 9) / 10;
 }
 
-static inline uint32_t calc_dsc_bpp_x16(uint32_t stream_bandwidth_kbps, uint32_t pix_clk_100hz, uint32_t bpp_increment_div)
-{
-       uint32_t dsc_target_bpp_x16;
-       float f_dsc_target_bpp;
-       float f_stream_bandwidth_100bps = stream_bandwidth_kbps * 10.0f;
-       uint32_t precision = bpp_increment_div; // bpp_increment_div is actually precision
-
-       f_dsc_target_bpp = f_stream_bandwidth_100bps / pix_clk_100hz;
-
-       // Round down to the nearest precision stop to bring it into DSC spec range
-       dsc_target_bpp_x16 = (uint32_t)(f_dsc_target_bpp * precision);
-       dsc_target_bpp_x16 = (dsc_target_bpp_x16 * 16) / precision;
-
-       return dsc_target_bpp_x16;
-}
-
 /* Get DSC bandwidth range based on [min_bpp, max_bpp] target bitrate range, and timing's pixel clock
  * and uncompressed bandwidth.
  */
index 03ae159..667afbc 100644 (file)
@@ -23,6 +23,7 @@
  * Authors: AMD
  *
  */
+#include <drm/drm_dsc.h>
 
 #include "os_types.h"
 #include "rc_calc.h"
@@ -40,7 +41,8 @@
        break
 
 
-void get_qp_set(qp_set qps, enum colour_mode cm, enum bits_per_comp bpc, enum max_min max_min, float bpp)
+static void get_qp_set(qp_set qps, enum colour_mode cm, enum bits_per_comp bpc,
+                      enum max_min max_min, float bpp)
 {
        int mode = MODE_SELECT(444, 422, 420);
        int sel = table_hash(mode, bpc, max_min);
@@ -85,7 +87,7 @@ void get_qp_set(qp_set qps, enum colour_mode cm, enum bits_per_comp bpc, enum ma
        memcpy(qps, table[index].qps, sizeof(qp_set));
 }
 
-double dsc_roundf(double num)
+static double dsc_roundf(double num)
 {
        if (num < 0.0)
                num = num - 0.5;
@@ -95,7 +97,7 @@ double dsc_roundf(double num)
        return (int)(num);
 }
 
-double dsc_ceil(double num)
+static double dsc_ceil(double num)
 {
        double retval = (int)num;
 
@@ -105,7 +107,7 @@ double dsc_ceil(double num)
        return (int)retval;
 }
 
-void get_ofs_set(qp_set ofs, enum colour_mode mode, float bpp)
+static void get_ofs_set(qp_set ofs, enum colour_mode mode, float bpp)
 {
        int   *p = ofs;
 
@@ -160,7 +162,7 @@ void get_ofs_set(qp_set ofs, enum colour_mode mode, float bpp)
        }
 }
 
-int median3(int a, int b, int c)
+static int median3(int a, int b, int c)
 {
        if (a > b)
                swap(a, b);
@@ -172,13 +174,25 @@ int median3(int a, int b, int c)
        return b;
 }
 
-void calc_rc_params(struct rc_params *rc, enum colour_mode cm, enum bits_per_comp bpc, float bpp, int slice_width, int slice_height, int minor_version)
+static void _do_calc_rc_params(struct rc_params *rc, enum colour_mode cm,
+                              enum bits_per_comp bpc, u8 drm_bpp,
+                              bool is_navite_422_or_420,
+                              int slice_width, int slice_height,
+                              int minor_version)
 {
+       float bpp;
        float bpp_group;
        float initial_xmit_delay_factor;
        int padding_pixels;
        int i;
 
+       bpp = ((float)drm_bpp / 16.0);
+       /* in native_422 or native_420 modes, the bits_per_pixel is double the
+        * target bpp (the latter is what calc_rc_params expects)
+        */
+       if (is_navite_422_or_420)
+               bpp /= 2.0;
+
        rc->rc_quant_incr_limit0 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
        rc->rc_quant_incr_limit1 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
 
@@ -251,3 +265,128 @@ void calc_rc_params(struct rc_params *rc, enum colour_mode cm, enum bits_per_com
        rc->rc_buf_thresh[13] = 8064;
 }
 
+static u32 _do_bytes_per_pixel_calc(int slice_width, u8 drm_bpp,
+                                   bool is_navite_422_or_420)
+{
+       float bpp;
+       u32 bytes_per_pixel;
+       double d_bytes_per_pixel;
+
+       bpp = ((float)drm_bpp / 16.0);
+       d_bytes_per_pixel = dsc_ceil(bpp * slice_width / 8.0) / slice_width;
+       // TODO: Make sure the formula for calculating this is precise (ceiling
+       // vs. floor, and at what point they should be applied)
+       if (is_navite_422_or_420)
+               d_bytes_per_pixel /= 2;
+
+       bytes_per_pixel = (u32)dsc_ceil(d_bytes_per_pixel * 0x10000000);
+
+       return bytes_per_pixel;
+}
+
+static u32 _do_calc_dsc_bpp_x16(u32 stream_bandwidth_kbps, u32 pix_clk_100hz,
+                               u32 bpp_increment_div)
+{
+       u32 dsc_target_bpp_x16;
+       float f_dsc_target_bpp;
+       float f_stream_bandwidth_100bps;
+       // bpp_increment_div is actually precision
+       u32 precision = bpp_increment_div;
+
+       f_stream_bandwidth_100bps = stream_bandwidth_kbps * 10.0f;
+       f_dsc_target_bpp = f_stream_bandwidth_100bps / pix_clk_100hz;
+
+       // Round down to the nearest precision stop to bring it into DSC spec
+       // range
+       dsc_target_bpp_x16 = (u32)(f_dsc_target_bpp * precision);
+       dsc_target_bpp_x16 = (dsc_target_bpp_x16 * 16) / precision;
+
+       return dsc_target_bpp_x16;
+}
+
+/**
+ * calc_rc_params - reads the user's cmdline mode
+ * @rc: DC internal DSC parameters
+ * @pps: DRM struct with all required DSC values
+ *
+ * This function expects a drm_dsc_config data struct with all the required DSC
+ * values previously filled out by our driver and based on this information it
+ * computes some of the DSC values.
+ *
+ * @note This calculation requires float point operation, most of it executes
+ * under kernel_fpu_{begin,end}.
+ */
+void calc_rc_params(struct rc_params *rc, const struct drm_dsc_config *pps)
+{
+       enum colour_mode mode;
+       enum bits_per_comp bpc;
+       bool is_navite_422_or_420;
+       u8 drm_bpp = pps->bits_per_pixel;
+       int slice_width  = pps->slice_width;
+       int slice_height = pps->slice_height;
+
+       mode = pps->convert_rgb ? CM_RGB : (pps->simple_422  ? CM_444 :
+                                          (pps->native_422  ? CM_422 :
+                                           pps->native_420  ? CM_420 : CM_444));
+       bpc = (pps->bits_per_component == 8) ? BPC_8 : (pps->bits_per_component == 10)
+                                            ? BPC_10 : BPC_12;
+
+       is_navite_422_or_420 = pps->native_422 || pps->native_420;
+
+       DC_FP_START();
+       _do_calc_rc_params(rc, mode, bpc, drm_bpp, is_navite_422_or_420,
+                          slice_width, slice_height,
+                          pps->dsc_version_minor);
+       DC_FP_END();
+}
+
+/**
+ * calc_dsc_bytes_per_pixel - calculate bytes per pixel
+ * @pps: DRM struct with all required DSC values
+ *
+ * Based on the information inside drm_dsc_config, this function calculates the
+ * total of bytes per pixel.
+ *
+ * @note This calculation requires float point operation, most of it executes
+ * under kernel_fpu_{begin,end}.
+ *
+ * Return:
+ * Return the number of bytes per pixel
+ */
+u32 calc_dsc_bytes_per_pixel(const struct drm_dsc_config *pps)
+
+{
+       u32 ret;
+       u8 drm_bpp = pps->bits_per_pixel;
+       int slice_width  = pps->slice_width;
+       bool is_navite_422_or_420 = pps->native_422 || pps->native_420;
+
+       DC_FP_START();
+       ret = _do_bytes_per_pixel_calc(slice_width, drm_bpp,
+                                      is_navite_422_or_420);
+       DC_FP_END();
+       return ret;
+}
+
+/**
+ * calc_dsc_bpp_x16 - retrieve the dsc bits per pixel
+ * @stream_bandwidth_kbps:
+ * @pix_clk_100hz:
+ * @bpp_increment_div:
+ *
+ * Calculate the total of bits per pixel for DSC configuration.
+ *
+ * @note This calculation requires float point operation, most of it executes
+ * under kernel_fpu_{begin,end}.
+ */
+u32 calc_dsc_bpp_x16(u32 stream_bandwidth_kbps, u32 pix_clk_100hz,
+                    u32 bpp_increment_div)
+{
+       u32 dsc_bpp;
+
+       DC_FP_START();
+       dsc_bpp =  _do_calc_dsc_bpp_x16(stream_bandwidth_kbps, pix_clk_100hz,
+                                       bpp_increment_div);
+       DC_FP_END();
+       return dsc_bpp;
+}
index b6b1f09..21723fa 100644 (file)
@@ -77,7 +77,10 @@ struct qp_entry {
 
 typedef struct qp_entry qp_table[];
 
-void calc_rc_params(struct rc_params *rc, enum colour_mode cm, enum bits_per_comp bpc, float bpp, int slice_width, int slice_height, int minor_version);
+void calc_rc_params(struct rc_params *rc, const struct drm_dsc_config *pps);
+u32 calc_dsc_bytes_per_pixel(const struct drm_dsc_config *pps);
+u32 calc_dsc_bpp_x16(u32 stream_bandwidth_kbps, u32 pix_clk_100hz,
+                    u32 bpp_increment_div);
 
 #endif
 
index 1f6e63b..ef830ad 100644 (file)
@@ -27,8 +27,6 @@
 #include "dscc_types.h"
 #include "rc_calc.h"
 
-double dsc_ceil(double num);
-
 static void copy_pps_fields(struct drm_dsc_config *to, const struct drm_dsc_config *from)
 {
        to->line_buf_depth           = from->line_buf_depth;
@@ -100,34 +98,13 @@ static void copy_rc_to_cfg(struct drm_dsc_config *dsc_cfg, const struct rc_param
 
 int dscc_compute_dsc_parameters(const struct drm_dsc_config *pps, struct dsc_parameters *dsc_params)
 {
-       enum colour_mode  mode = pps->convert_rgb ? CM_RGB :
-                                                       (pps->simple_422  ? CM_444 :
-                                                       (pps->native_422  ? CM_422 :
-                                                       pps->native_420  ? CM_420 : CM_444));
-       enum bits_per_comp bpc = (pps->bits_per_component == 8) ? BPC_8 :
-                                                       (pps->bits_per_component == 10) ? BPC_10 : BPC_12;
-       float            bpp = ((float) pps->bits_per_pixel / 16.0);
-       int              slice_width  = pps->slice_width;
-       int              slice_height = pps->slice_height;
        int              ret;
        struct rc_params rc;
        struct drm_dsc_config   dsc_cfg;
 
-       double d_bytes_per_pixel = dsc_ceil(bpp * slice_width / 8.0) / slice_width;
-
-       // TODO: Make sure the formula for calculating this is precise (ceiling vs. floor, and at what point they should be applied)
-       if (pps->native_422 || pps->native_420)
-               d_bytes_per_pixel /= 2;
-
-       dsc_params->bytes_per_pixel = (uint32_t)dsc_ceil(d_bytes_per_pixel * 0x10000000);
-
-       /* in native_422 or native_420 modes, the bits_per_pixel is double the target bpp
-        * (the latter is what calc_rc_params expects)
-        */
-       if (pps->native_422 || pps->native_420)
-               bpp /= 2.0;
+       dsc_params->bytes_per_pixel = calc_dsc_bytes_per_pixel(pps);
 
-       calc_rc_params(&rc, mode, bpc, bpp, slice_width, slice_height, pps->dsc_version_minor);
+       calc_rc_params(&rc, pps);
        dsc_params->pps = *pps;
        dsc_params->pps.initial_scale_value = 8 * rc.rc_model_size / (rc.rc_model_size - rc.initial_fullness_offset);
 
index 9431b48..bcfe34e 100644 (file)
@@ -843,7 +843,7 @@ static bool build_regamma(struct pwl_float_data_ex *rgb_regamma,
        pow_buffer_ptr = -1; // reset back to no optimize
        ret = true;
 release:
-       kfree(coeff);
+       kvfree(coeff);
        return ret;
 }
 
@@ -1777,7 +1777,7 @@ bool calculate_user_regamma_ramp(struct dc_transfer_func *output_tf,
 
        kfree(rgb_regamma);
 rgb_regamma_alloc_fail:
-       kvfree(rgb_user);
+       kfree(rgb_user);
 rgb_user_alloc_fail:
        return ret;
 }
index 6747604..fbb3f3a 100644 (file)
@@ -689,7 +689,7 @@ static int renoir_set_power_profile_mode(struct smu_context *smu, long *input, u
                return -EINVAL;
        }
 
-       ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
+       ret = smu_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
                                    1 << workload_type,
                                    NULL);
        if (ret) {
index 85e5b1e..56923a9 100644 (file)
@@ -239,7 +239,7 @@ static void ci_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
 
        switch (dev_id) {
        case 0x67BA:
-       case 0x66B1:
+       case 0x67B1:
                smu_data->power_tune_defaults = &defaults_hawaii_pro;
                break;
        case 0x67B8:
index 2fb9755..c2e0fbb 100644 (file)
@@ -522,9 +522,11 @@ static int vega20_smu_init(struct pp_hwmgr *hwmgr)
        priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].version = 0x01;
        priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].size = sizeof(DpmActivityMonitorCoeffInt_t);
 
-       ret = smu_v11_0_i2c_eeprom_control_init(&adev->pm.smu_i2c);
-       if (ret)
-               goto err4;
+       if (adev->psp.ras.ras) {
+               ret = smu_v11_0_i2c_eeprom_control_init(&adev->pm.smu_i2c);
+               if (ret)
+                       goto err4;
+       }
 
        return 0;
 
@@ -560,7 +562,8 @@ static int vega20_smu_fini(struct pp_hwmgr *hwmgr)
                        (struct vega20_smumgr *)(hwmgr->smu_backend);
        struct amdgpu_device *adev = hwmgr->adev;
 
-       smu_v11_0_i2c_eeprom_control_fini(&adev->pm.smu_i2c);
+       if (adev->psp.ras.ras)
+               smu_v11_0_i2c_eeprom_control_fini(&adev->pm.smu_i2c);
 
        if (priv) {
                amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle,
index 3da71a0..0ecc18b 100644 (file)
@@ -644,9 +644,6 @@ static int vegam_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr,
 
        /* sclk is bigger than max sclk in the dependence table */
        *voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT;
-       vddci = phm_find_closest_vddci(&(data->vddci_voltage_table),
-                       (dep_table->entries[i - 1].vddc -
-                                       (uint16_t)VDDC_VDDCI_DELTA));
 
        if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control)
                *voltage |= (data->vbios_boot_state.vddci_bootup_value *
@@ -654,8 +651,13 @@ static int vegam_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr,
        else if (dep_table->entries[i - 1].vddci)
                *voltage |= (dep_table->entries[i - 1].vddci *
                                VOLTAGE_SCALE) << VDDC_SHIFT;
-       else
+       else {
+               vddci = phm_find_closest_vddci(&(data->vddci_voltage_table),
+                               (dep_table->entries[i - 1].vddc -
+                                               (uint16_t)VDDC_VDDCI_DELTA));
+
                *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
+       }
 
        if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control)
                *mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE;
index 6b27242..bca3fcf 100644 (file)
@@ -173,8 +173,6 @@ static int aspeed_gfx_load(struct drm_device *drm)
 
        drm_mode_config_reset(drm);
 
-       drm_fbdev_generic_setup(drm, 32);
-
        return 0;
 }
 
@@ -225,6 +223,7 @@ static int aspeed_gfx_probe(struct platform_device *pdev)
        if (ret)
                goto err_unload;
 
+       drm_fbdev_generic_setup(&priv->drm, 32);
        return 0;
 
 err_unload:
index 05d8373..079f46f 100644 (file)
@@ -146,6 +146,7 @@ int bochs_kms_init(struct bochs_device *bochs)
        bochs->dev->mode_config.preferred_depth = 24;
        bochs->dev->mode_config.prefer_shadow = 0;
        bochs->dev->mode_config.prefer_shadow_fbdev = 1;
+       bochs->dev->mode_config.fbdev_use_iomem = true;
        bochs->dev->mode_config.quirk_addfb_prefer_host_byte_order = true;
 
        bochs->dev->mode_config.funcs = &bochs_mode_funcs;
index 87b58c1..648eb23 100644 (file)
@@ -1224,6 +1224,7 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
 
        adv7511->bridge.funcs = &adv7511_bridge_funcs;
        adv7511->bridge.of_node = dev->of_node;
+       adv7511->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
 
        drm_bridge_add(&adv7511->bridge);
 
index b14d725..c7bc194 100644 (file)
@@ -917,11 +917,6 @@ static int nwl_dsi_bridge_attach(struct drm_bridge *bridge,
        struct drm_panel *panel;
        int ret;
 
-       if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
-               DRM_ERROR("Fix bridge driver to make connector optional!");
-               return -EINVAL;
-       }
-
        ret = drm_of_find_panel_or_bridge(dsi->dev->of_node, 1, 0, &panel,
                                          &panel_bridge);
        if (ret)
index cf80438..e464429 100644 (file)
@@ -61,13 +61,8 @@ int drm_i2c_encoder_init(struct drm_device *dev,
 
        request_module("%s%s", I2C_MODULE_PREFIX, info->type);
 
-       client = i2c_new_device(adap, info);
-       if (!client) {
-               err = -ENOMEM;
-               goto fail;
-       }
-
-       if (!client->dev.driver) {
+       client = i2c_new_client_device(adap, info);
+       if (!i2c_client_has_driver(client)) {
                err = -ENODEV;
                goto fail_unregister;
        }
@@ -84,7 +79,7 @@ int drm_i2c_encoder_init(struct drm_device *dev,
 
        err = encoder_drv->encoder_init(client, dev, encoder);
        if (err)
-               goto fail_unregister;
+               goto fail_module_put;
 
        if (info->platform_data)
                encoder->slave_funcs->set_config(&encoder->base,
@@ -92,10 +87,10 @@ int drm_i2c_encoder_init(struct drm_device *dev,
 
        return 0;
 
+fail_module_put:
+       module_put(module);
 fail_unregister:
        i2c_unregister_device(client);
-       module_put(module);
-fail:
        return err;
 }
 EXPORT_SYMBOL(drm_i2c_encoder_init);
index 170aa76..89cfd68 100644 (file)
@@ -227,18 +227,9 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
 }
 EXPORT_SYMBOL(drm_fb_helper_debug_leave);
 
-/**
- * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
- * @fb_helper: driver-allocated fbdev helper, can be NULL
- *
- * This should be called from driver's drm &drm_driver.lastclose callback
- * when implementing an fbcon on top of kms using this helper. This ensures that
- * the user isn't greeted with a black screen when e.g. X dies.
- *
- * RETURNS:
- * Zero if everything went ok, negative error code otherwise.
- */
-int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
+static int
+__drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper,
+                                           bool force)
 {
        bool do_delayed;
        int ret;
@@ -250,7 +241,16 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
                return 0;
 
        mutex_lock(&fb_helper->lock);
-       ret = drm_client_modeset_commit(&fb_helper->client);
+       if (force) {
+               /*
+                * Yes this is the _locked version which expects the master lock
+                * to be held. But for forced restores we're intentionally
+                * racing here, see drm_fb_helper_set_par().
+                */
+               ret = drm_client_modeset_commit_locked(&fb_helper->client);
+       } else {
+               ret = drm_client_modeset_commit(&fb_helper->client);
+       }
 
        do_delayed = fb_helper->delayed_hotplug;
        if (do_delayed)
@@ -262,6 +262,22 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
 
        return ret;
 }
+
+/**
+ * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
+ *
+ * This should be called from driver's drm &drm_driver.lastclose callback
+ * when implementing an fbcon on top of kms using this helper. This ensures that
+ * the user isn't greeted with a black screen when e.g. X dies.
+ *
+ * RETURNS:
+ * Zero if everything went ok, negative error code otherwise.
+ */
+int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
+{
+       return __drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper, false);
+}
 EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked);
 
 #ifdef CONFIG_MAGIC_SYSRQ
@@ -383,7 +399,11 @@ static void drm_fb_helper_dirty_blit_real(struct drm_fb_helper *fb_helper,
        unsigned int y;
 
        for (y = clip->y1; y < clip->y2; y++) {
-               memcpy(dst, src, len);
+               if (!fb_helper->dev->mode_config.fbdev_use_iomem)
+                       memcpy(dst, src, len);
+               else
+                       memcpy_toio((void __iomem *)dst, src, len);
+
                src += fb->pitches[0];
                dst += fb->pitches[0];
        }
@@ -1318,6 +1338,7 @@ int drm_fb_helper_set_par(struct fb_info *info)
 {
        struct drm_fb_helper *fb_helper = info->par;
        struct fb_var_screeninfo *var = &info->var;
+       bool force;
 
        if (oops_in_progress)
                return -EBUSY;
@@ -1327,7 +1348,25 @@ int drm_fb_helper_set_par(struct fb_info *info)
                return -EINVAL;
        }
 
-       drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
+       /*
+        * Normally we want to make sure that a kms master takes precedence over
+        * fbdev, to avoid fbdev flickering and occasionally stealing the
+        * display status. But Xorg first sets the vt back to text mode using
+        * the KDSET IOCTL with KD_TEXT, and only after that drops the master
+        * status when exiting.
+        *
+        * In the past this was caught by drm_fb_helper_lastclose(), but on
+        * modern systems where logind always keeps a drm fd open to orchestrate
+        * the vt switching, this doesn't work.
+        *
+        * To not break the userspace ABI we have this special case here, which
+        * is only used for the above case. Everything else uses the normal
+        * commit function, which ensures that we never steal the display from
+        * an active drm master.
+        */
+       force = var->activate & FB_ACTIVATE_KD_TEXT;
+
+       __drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper, force);
 
        return 0;
 }
index 7bf628e..ee2058a 100644 (file)
@@ -871,9 +871,6 @@ err:
  * @file_priv: drm file-private structure
  *
  * Open an object using the global name, returning a handle and the size.
- *
- * This handle (of course) holds a reference to the object, so the object
- * will not go away until the handle is deleted.
  */
 int
 drm_gem_open_ioctl(struct drm_device *dev, void *data,
@@ -898,14 +895,15 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data,
 
        /* drm_gem_handle_create_tail unlocks dev->object_name_lock. */
        ret = drm_gem_handle_create_tail(file_priv, obj, &handle);
-       drm_gem_object_put_unlocked(obj);
        if (ret)
-               return ret;
+               goto err;
 
        args->handle = handle;
        args->size = obj->size;
 
-       return 0;
+err:
+       drm_gem_object_put_unlocked(obj);
+       return ret;
 }
 
 /**
index bb27c82..bf7888a 100644 (file)
@@ -923,7 +923,7 @@ static int mipi_dbi_spi1_transfer(struct mipi_dbi *dbi, int dc,
                        }
                }
 
-               tr.len = chunk;
+               tr.len = chunk * 2;
                len -= chunk;
 
                ret = spi_sync(spi, &m);
index b50b44e..8fc3f67 100644 (file)
@@ -322,10 +322,8 @@ static int drm_of_lvds_get_remote_pixels_type(
                 * configurations by passing the endpoints explicitly to
                 * drm_of_lvds_get_dual_link_pixel_order().
                 */
-               if (!current_pt || pixels_type != current_pt) {
-                       of_node_put(remote_port);
+               if (!current_pt || pixels_type != current_pt)
                        return -EINVAL;
-               }
        }
 
        return pixels_type;
index ffd95bf..d00ea38 100644 (file)
@@ -30,12 +30,6 @@ struct drm_dmi_panel_orientation_data {
        int orientation;
 };
 
-static const struct drm_dmi_panel_orientation_data acer_s1003 = {
-       .width = 800,
-       .height = 1280,
-       .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
-};
-
 static const struct drm_dmi_panel_orientation_data asus_t100ha = {
        .width = 800,
        .height = 1280,
@@ -114,13 +108,19 @@ static const struct dmi_system_id orientation_data[] = {
                  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"),
                  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "One S1003"),
                },
-               .driver_data = (void *)&acer_s1003,
+               .driver_data = (void *)&lcd800x1280_rightside_up,
        }, {    /* Asus T100HA */
                .matches = {
                  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
                  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100HAN"),
                },
                .driver_data = (void *)&asus_t100ha,
+       }, {    /* Asus T101HA */
+               .matches = {
+                 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T101HA"),
+               },
+               .driver_data = (void *)&lcd800x1280_rightside_up,
        }, {    /* GPD MicroPC (generic strings, also match on bios date) */
                .matches = {
                  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"),
index 619f814..58b89ec 100644 (file)
@@ -61,7 +61,7 @@ static int drm_iommu_attach_device(struct drm_device *drm_dev,
                                struct device *subdrv_dev, void **dma_priv)
 {
        struct exynos_drm_private *priv = drm_dev->dev_private;
-       int ret;
+       int ret = 0;
 
        if (get_dma_ops(priv->dma_dev) != get_dma_ops(subdrv_dev)) {
                DRM_DEV_ERROR(subdrv_dev, "Device %s lacks support for IOMMU\n",
@@ -92,7 +92,7 @@ static int drm_iommu_attach_device(struct drm_device *drm_dev,
        if (ret)
                clear_dma_max_seg_size(subdrv_dev);
 
-       return 0;
+       return ret;
 }
 
 /*
index fcee33a..03be314 100644 (file)
@@ -1498,7 +1498,6 @@ static int g2d_probe(struct platform_device *pdev)
 
        g2d->irq = platform_get_irq(pdev, 0);
        if (g2d->irq < 0) {
-               dev_err(dev, "failed to get irq\n");
                ret = g2d->irq;
                goto err_put_clk;
        }
index a86abc1..3821ea7 100644 (file)
@@ -269,8 +269,10 @@ static void mic_pre_enable(struct drm_bridge *bridge)
                goto unlock;
 
        ret = pm_runtime_get_sync(mic->dev);
-       if (ret < 0)
+       if (ret < 0) {
+               pm_runtime_put_noidle(mic->dev);
                goto unlock;
+       }
 
        mic_set_path(mic, 1);
 
index a6fd0c2..544b999 100644 (file)
@@ -307,8 +307,6 @@ static int hibmc_load(struct drm_device *dev)
        /* reset all the states of crtc/plane/encoder/connector */
        drm_mode_config_reset(dev);
 
-       drm_fbdev_generic_setup(dev, dev->mode_config.preferred_depth);
-
        return 0;
 
 err:
@@ -355,6 +353,9 @@ static int hibmc_pci_probe(struct pci_dev *pdev,
                          ret);
                goto err_unload;
        }
+
+       drm_fbdev_generic_setup(dev, dev->mode_config.preferred_depth);
+
        return 0;
 
 err_unload:
index aa22465..0575a1e 100644 (file)
@@ -2579,14 +2579,14 @@ static void icl_ddi_vswing_sequence(struct intel_encoder *encoder,
 
 static void
 tgl_dkl_phy_ddi_vswing_sequence(struct intel_encoder *encoder, int link_clock,
-                               u32 level)
+                               u32 level, enum intel_output_type type)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port);
        const struct tgl_dkl_phy_ddi_buf_trans *ddi_translations;
        u32 n_entries, val, ln, dpcnt_mask, dpcnt_val;
 
-       if (encoder->type == INTEL_OUTPUT_HDMI) {
+       if (type == INTEL_OUTPUT_HDMI) {
                n_entries = ARRAY_SIZE(tgl_dkl_phy_hdmi_ddi_trans);
                ddi_translations = tgl_dkl_phy_hdmi_ddi_trans;
        } else {
@@ -2638,7 +2638,7 @@ static void tgl_ddi_vswing_sequence(struct intel_encoder *encoder,
        if (intel_phy_is_combo(dev_priv, phy))
                icl_combo_phy_ddi_vswing_sequence(encoder, level, type);
        else
-               tgl_dkl_phy_ddi_vswing_sequence(encoder, link_clock, level);
+               tgl_dkl_phy_ddi_vswing_sequence(encoder, link_clock, level, type);
 }
 
 static u32 translate_signal_level(struct intel_dp *intel_dp, int signal_levels)
@@ -2987,7 +2987,7 @@ icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port,
                ln1 = intel_de_read(dev_priv, MG_DP_MODE(1, tc_port));
        }
 
-       ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X1_MODE);
+       ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
        ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
 
        /* DPPATC */
@@ -3472,7 +3472,9 @@ static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
                                          INTEL_OUTPUT_DP_MST);
        enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
 
-       intel_dp_set_infoframes(encoder, false, old_crtc_state, old_conn_state);
+       if (!is_mst)
+               intel_dp_set_infoframes(encoder, false,
+                                       old_crtc_state, old_conn_state);
 
        /*
         * Power down sink before disabling the port, otherwise we end
index 9ea1a39..26996e1 100644 (file)
@@ -3822,6 +3822,17 @@ skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
        return true;
 }
 
+unsigned int
+intel_plane_fence_y_offset(const struct intel_plane_state *plane_state)
+{
+       int x = 0, y = 0;
+
+       intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0,
+                                         plane_state->color_plane[0].offset, 0);
+
+       return y;
+}
+
 static int skl_check_main_surface(struct intel_plane_state *plane_state)
 {
        struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
index efb4da2..3a06f72 100644 (file)
@@ -608,6 +608,7 @@ unsigned int i9xx_plane_max_stride(struct intel_plane *plane,
                                   u32 pixel_format, u64 modifier,
                                   unsigned int rotation);
 int bdw_get_pipemisc_bpp(struct intel_crtc *crtc);
+unsigned int intel_plane_fence_y_offset(const struct intel_plane_state *plane_state);
 
 struct intel_display_error_state *
 intel_display_capture_error_state(struct drm_i915_private *dev_priv);
index d18b406..f29e51c 100644 (file)
@@ -397,6 +397,14 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
         */
        drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port,
                                     false);
+
+       /*
+        * BSpec 4287: disable DIP after the transcoder is disabled and before
+        * the transcoder clock select is set to none.
+        */
+       if (last_mst_stream)
+               intel_dp_set_infoframes(&intel_dig_port->base, false,
+                                       old_crtc_state, NULL);
        /*
         * From TGL spec: "If multi-stream slave transcoder: Configure
         * Transcoder Clock Select to direct no clock to the transcoder"
index 1c26673..412572f 100644 (file)
 #include "intel_fbc.h"
 #include "intel_frontbuffer.h"
 
-/*
- * In some platforms where the CRTC's x:0/y:0 coordinates doesn't match the
- * frontbuffer's x:0/y:0 coordinates we lie to the hardware about the plane's
- * origin so the x and y offsets can actually fit the registers. As a
- * consequence, the fence doesn't really start exactly at the display plane
- * address we program because it starts at the real start of the buffer, so we
- * have to take this into consideration here.
- */
-static unsigned int get_crtc_fence_y_offset(struct intel_fbc *fbc)
-{
-       return fbc->state_cache.plane.y - fbc->state_cache.plane.adjusted_y;
-}
-
 /*
  * For SKL+, the plane source size used by the hardware is based on the value we
  * write to the PLANE_SIZE register. For BDW-, the hardware looks at the value
@@ -141,7 +128,7 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv)
                        fbc_ctl2 |= FBC_CTL_CPU_FENCE;
                intel_de_write(dev_priv, FBC_CONTROL2, fbc_ctl2);
                intel_de_write(dev_priv, FBC_FENCE_OFF,
-                              params->crtc.fence_y_offset);
+                              params->fence_y_offset);
        }
 
        /* enable it... */
@@ -175,7 +162,7 @@ static void g4x_fbc_activate(struct drm_i915_private *dev_priv)
        if (params->fence_id >= 0) {
                dpfc_ctl |= DPFC_CTL_FENCE_EN | params->fence_id;
                intel_de_write(dev_priv, DPFC_FENCE_YOFF,
-                              params->crtc.fence_y_offset);
+                              params->fence_y_offset);
        } else {
                intel_de_write(dev_priv, DPFC_FENCE_YOFF, 0);
        }
@@ -243,7 +230,7 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv)
                        intel_de_write(dev_priv, SNB_DPFC_CTL_SA,
                                       SNB_CPU_FENCE_ENABLE | params->fence_id);
                        intel_de_write(dev_priv, DPFC_CPU_FENCE_OFFSET,
-                                      params->crtc.fence_y_offset);
+                                      params->fence_y_offset);
                }
        } else {
                if (IS_GEN(dev_priv, 6)) {
@@ -253,7 +240,7 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv)
        }
 
        intel_de_write(dev_priv, ILK_DPFC_FENCE_YOFF,
-                      params->crtc.fence_y_offset);
+                      params->fence_y_offset);
        /* enable it... */
        intel_de_write(dev_priv, ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
 
@@ -320,7 +307,7 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
                intel_de_write(dev_priv, SNB_DPFC_CTL_SA,
                               SNB_CPU_FENCE_ENABLE | params->fence_id);
                intel_de_write(dev_priv, DPFC_CPU_FENCE_OFFSET,
-                              params->crtc.fence_y_offset);
+                              params->fence_y_offset);
        } else if (dev_priv->ggtt.num_fences) {
                intel_de_write(dev_priv, SNB_DPFC_CTL_SA, 0);
                intel_de_write(dev_priv, DPFC_CPU_FENCE_OFFSET, 0);
@@ -631,8 +618,8 @@ static bool rotation_is_valid(struct drm_i915_private *dev_priv,
 /*
  * For some reason, the hardware tracking starts looking at whatever we
  * programmed as the display plane base address register. It does not look at
- * the X and Y offset registers. That's why we look at the crtc->adjusted{x,y}
- * variables instead of just looking at the pipe/plane size.
+ * the X and Y offset registers. That's why we include the src x/y offsets
+ * instead of just looking at the plane size.
  */
 static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
 {
@@ -705,7 +692,6 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
        cache->plane.src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
        cache->plane.adjusted_x = plane_state->color_plane[0].x;
        cache->plane.adjusted_y = plane_state->color_plane[0].y;
-       cache->plane.y = plane_state->uapi.src.y1 >> 16;
 
        cache->plane.pixel_blend_mode = plane_state->hw.pixel_blend_mode;
 
@@ -713,6 +699,8 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
        cache->fb.stride = fb->pitches[0];
        cache->fb.modifier = fb->modifier;
 
+       cache->fence_y_offset = intel_plane_fence_y_offset(plane_state);
+
        drm_WARN_ON(&dev_priv->drm, plane_state->flags & PLANE_HAS_FENCE &&
                    !plane_state->vma->fence);
 
@@ -731,6 +719,25 @@ static bool intel_fbc_cfb_size_changed(struct drm_i915_private *dev_priv)
                fbc->compressed_fb.size * fbc->threshold;
 }
 
+static u16 intel_fbc_gen9_wa_cfb_stride(struct drm_i915_private *dev_priv)
+{
+       struct intel_fbc *fbc = &dev_priv->fbc;
+       struct intel_fbc_state_cache *cache = &fbc->state_cache;
+
+       if ((IS_GEN9_BC(dev_priv) || IS_BROXTON(dev_priv)) &&
+           cache->fb.modifier != I915_FORMAT_MOD_X_TILED)
+               return DIV_ROUND_UP(cache->plane.src_w, 32 * fbc->threshold) * 8;
+       else
+               return 0;
+}
+
+static bool intel_fbc_gen9_wa_cfb_stride_changed(struct drm_i915_private *dev_priv)
+{
+       struct intel_fbc *fbc = &dev_priv->fbc;
+
+       return fbc->params.gen9_wa_cfb_stride != intel_fbc_gen9_wa_cfb_stride(dev_priv);
+}
+
 static bool intel_fbc_can_enable(struct drm_i915_private *dev_priv)
 {
        struct intel_fbc *fbc = &dev_priv->fbc;
@@ -883,12 +890,13 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc,
        memset(params, 0, sizeof(*params));
 
        params->fence_id = cache->fence_id;
+       params->fence_y_offset = cache->fence_y_offset;
 
        params->crtc.pipe = crtc->pipe;
        params->crtc.i9xx_plane = to_intel_plane(crtc->base.primary)->i9xx_plane;
-       params->crtc.fence_y_offset = get_crtc_fence_y_offset(fbc);
 
        params->fb.format = cache->fb.format;
+       params->fb.modifier = cache->fb.modifier;
        params->fb.stride = cache->fb.stride;
 
        params->cfb_size = intel_fbc_calculate_cfb_size(dev_priv, cache);
@@ -918,6 +926,9 @@ static bool intel_fbc_can_flip_nuke(const struct intel_crtc_state *crtc_state)
        if (params->fb.format != cache->fb.format)
                return false;
 
+       if (params->fb.modifier != cache->fb.modifier)
+               return false;
+
        if (params->fb.stride != cache->fb.stride)
                return false;
 
@@ -1197,7 +1208,8 @@ void intel_fbc_enable(struct intel_atomic_state *state,
 
        if (fbc->crtc) {
                if (fbc->crtc != crtc ||
-                   !intel_fbc_cfb_size_changed(dev_priv))
+                   (!intel_fbc_cfb_size_changed(dev_priv) &&
+                    !intel_fbc_gen9_wa_cfb_stride_changed(dev_priv)))
                        goto out;
 
                __intel_fbc_disable(dev_priv);
@@ -1219,12 +1231,7 @@ void intel_fbc_enable(struct intel_atomic_state *state,
                goto out;
        }
 
-       if ((IS_GEN9_BC(dev_priv) || IS_BROXTON(dev_priv)) &&
-           plane_state->hw.fb->modifier != I915_FORMAT_MOD_X_TILED)
-               cache->gen9_wa_cfb_stride =
-                       DIV_ROUND_UP(cache->plane.src_w, 32 * fbc->threshold) * 8;
-       else
-               cache->gen9_wa_cfb_stride = 0;
+       cache->gen9_wa_cfb_stride = intel_fbc_gen9_wa_cfb_stride(dev_priv);
 
        drm_dbg_kms(&dev_priv->drm, "Enabling FBC on pipe %c\n",
                    pipe_name(crtc->pipe));
index 010f372..95b6d94 100644 (file)
@@ -2867,19 +2867,13 @@ intel_hdmi_connector_register(struct drm_connector *connector)
        return ret;
 }
 
-static void intel_hdmi_destroy(struct drm_connector *connector)
+static void intel_hdmi_connector_unregister(struct drm_connector *connector)
 {
        struct cec_notifier *n = intel_attached_hdmi(to_intel_connector(connector))->cec_notifier;
 
        cec_notifier_conn_unregister(n);
 
-       intel_connector_destroy(connector);
-}
-
-static void intel_hdmi_connector_unregister(struct drm_connector *connector)
-{
        intel_hdmi_remove_i2c_symlink(connector);
-
        intel_connector_unregister(connector);
 }
 
@@ -2891,7 +2885,7 @@ static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
        .atomic_set_property = intel_digital_connector_atomic_set_property,
        .late_register = intel_hdmi_connector_register,
        .early_unregister = intel_hdmi_connector_unregister,
-       .destroy = intel_hdmi_destroy,
+       .destroy = intel_connector_destroy,
        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
        .atomic_duplicate_state = intel_digital_connector_duplicate_state,
 };
index e4aece2..52db2bd 100644 (file)
@@ -204,25 +204,25 @@ static int __ring_active(struct intel_ring *ring)
 {
        int err;
 
-       err = i915_active_acquire(&ring->vma->active);
+       err = intel_ring_pin(ring);
        if (err)
                return err;
 
-       err = intel_ring_pin(ring);
+       err = i915_active_acquire(&ring->vma->active);
        if (err)
-               goto err_active;
+               goto err_pin;
 
        return 0;
 
-err_active:
-       i915_active_release(&ring->vma->active);
+err_pin:
+       intel_ring_unpin(ring);
        return err;
 }
 
 static void __ring_retire(struct intel_ring *ring)
 {
-       intel_ring_unpin(ring);
        i915_active_release(&ring->vma->active);
+       intel_ring_unpin(ring);
 }
 
 __i915_active_call
index da5b610..8691eb6 100644 (file)
@@ -646,7 +646,7 @@ static int engine_setup_common(struct intel_engine_cs *engine)
 struct measure_breadcrumb {
        struct i915_request rq;
        struct intel_ring ring;
-       u32 cs[1024];
+       u32 cs[2048];
 };
 
 static int measure_breadcrumb_dw(struct intel_context *ce)
@@ -668,6 +668,8 @@ static int measure_breadcrumb_dw(struct intel_context *ce)
 
        frame->ring.vaddr = frame->cs;
        frame->ring.size = sizeof(frame->cs);
+       frame->ring.wrap =
+               BITS_PER_TYPE(frame->ring.size) - ilog2(frame->ring.size);
        frame->ring.effective_size = frame->ring.size;
        intel_ring_update_space(&frame->ring);
        frame->rq.ring = &frame->ring;
index 87e6c5b..cb07e1d 100644 (file)
@@ -1134,6 +1134,13 @@ __unwind_incomplete_requests(struct intel_engine_cs *engine)
                        list_move(&rq->sched.link, pl);
                        set_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags);
 
+                       /* Check in case we rollback so far we wrap [size/2] */
+                       if (intel_ring_direction(rq->ring,
+                                                intel_ring_wrap(rq->ring,
+                                                                rq->tail),
+                                                rq->ring->tail) > 0)
+                               rq->context->lrc.desc |= CTX_DESC_FORCE_RESTORE;
+
                        active = rq;
                } else {
                        struct intel_engine_cs *owner = rq->context->engine;
@@ -1498,8 +1505,9 @@ static u64 execlists_update_context(struct i915_request *rq)
         * HW has a tendency to ignore us rewinding the TAIL to the end of
         * an earlier request.
         */
+       GEM_BUG_ON(ce->lrc_reg_state[CTX_RING_TAIL] != rq->ring->tail);
+       prev = rq->ring->tail;
        tail = intel_ring_set_tail(rq->ring, rq->tail);
-       prev = ce->lrc_reg_state[CTX_RING_TAIL];
        if (unlikely(intel_ring_direction(rq->ring, tail, prev) <= 0))
                desc |= CTX_DESC_FORCE_RESTORE;
        ce->lrc_reg_state[CTX_RING_TAIL] = tail;
@@ -1895,7 +1903,8 @@ static void defer_active(struct intel_engine_cs *engine)
 
 static bool
 need_timeslice(const struct intel_engine_cs *engine,
-              const struct i915_request *rq)
+              const struct i915_request *rq,
+              const struct rb_node *rb)
 {
        int hint;
 
@@ -1903,9 +1912,28 @@ need_timeslice(const struct intel_engine_cs *engine,
                return false;
 
        hint = engine->execlists.queue_priority_hint;
+
+       if (rb) {
+               const struct virtual_engine *ve =
+                       rb_entry(rb, typeof(*ve), nodes[engine->id].rb);
+               const struct intel_engine_cs *inflight =
+                       intel_context_inflight(&ve->context);
+
+               if (!inflight || inflight == engine) {
+                       struct i915_request *next;
+
+                       rcu_read_lock();
+                       next = READ_ONCE(ve->request);
+                       if (next)
+                               hint = max(hint, rq_prio(next));
+                       rcu_read_unlock();
+               }
+       }
+
        if (!list_is_last(&rq->sched.link, &engine->active.requests))
                hint = max(hint, rq_prio(list_next_entry(rq, sched.link)));
 
+       GEM_BUG_ON(hint >= I915_PRIORITY_UNPREEMPTABLE);
        return hint >= effective_prio(rq);
 }
 
@@ -1977,10 +2005,9 @@ static void set_timeslice(struct intel_engine_cs *engine)
        set_timer_ms(&engine->execlists.timer, duration);
 }
 
-static void start_timeslice(struct intel_engine_cs *engine)
+static void start_timeslice(struct intel_engine_cs *engine, int prio)
 {
        struct intel_engine_execlists *execlists = &engine->execlists;
-       const int prio = queue_prio(execlists);
        unsigned long duration;
 
        if (!intel_engine_has_timeslices(engine))
@@ -2140,7 +2167,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
                        __unwind_incomplete_requests(engine);
 
                        last = NULL;
-               } else if (need_timeslice(engine, last) &&
+               } else if (need_timeslice(engine, last, rb) &&
                           timeslice_expired(execlists, last)) {
                        if (i915_request_completed(last)) {
                                tasklet_hi_schedule(&execlists->tasklet);
@@ -2188,7 +2215,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
                                 * Even if ELSP[1] is occupied and not worthy
                                 * of timeslices, our queue might be.
                                 */
-                               start_timeslice(engine);
+                               start_timeslice(engine, queue_prio(execlists));
                                return;
                        }
                }
@@ -2223,7 +2250,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
 
                        if (last && !can_merge_rq(last, rq)) {
                                spin_unlock(&ve->base.active.lock);
-                               start_timeslice(engine);
+                               start_timeslice(engine, rq_prio(rq));
                                return; /* leave this for another sibling */
                        }
 
@@ -4739,6 +4766,14 @@ static int gen12_emit_flush(struct i915_request *request, u32 mode)
        return 0;
 }
 
+static void assert_request_valid(struct i915_request *rq)
+{
+       struct intel_ring *ring __maybe_unused = rq->ring;
+
+       /* Can we unwind this request without appearing to go forwards? */
+       GEM_BUG_ON(intel_ring_direction(ring, rq->wa_tail, rq->head) <= 0);
+}
+
 /*
  * Reserve space for 2 NOOPs at the end of each request to be
  * used as a workaround for not being allowed to do lite
@@ -4751,6 +4786,9 @@ static u32 *gen8_emit_wa_tail(struct i915_request *request, u32 *cs)
        *cs++ = MI_NOOP;
        request->wa_tail = intel_ring_offset(request, cs);
 
+       /* Check that entire request is less than half the ring */
+       assert_request_valid(request);
+
        return cs;
 }
 
@@ -5358,13 +5396,8 @@ static void virtual_engine_initial_hint(struct virtual_engine *ve)
         * typically be the first we inspect for submission.
         */
        swp = prandom_u32_max(ve->num_siblings);
-       if (!swp)
-               return;
-
-       swap(ve->siblings[swp], ve->siblings[0]);
-       if (!intel_engine_has_relative_mmio(ve->siblings[0]))
-               virtual_update_register_offsets(ve->context.lrc_reg_state,
-                                               ve->siblings[0]);
+       if (swp)
+               swap(ve->siblings[swp], ve->siblings[0]);
 }
 
 static int virtual_context_alloc(struct intel_context *ce)
@@ -5377,15 +5410,9 @@ static int virtual_context_alloc(struct intel_context *ce)
 static int virtual_context_pin(struct intel_context *ce)
 {
        struct virtual_engine *ve = container_of(ce, typeof(*ve), context);
-       int err;
 
        /* Note: we must use a real engine class for setting up reg state */
-       err = __execlists_context_pin(ce, ve->siblings[0]);
-       if (err)
-               return err;
-
-       virtual_engine_initial_hint(ve);
-       return 0;
+       return __execlists_context_pin(ce, ve->siblings[0]);
 }
 
 static void virtual_context_enter(struct intel_context *ce)
@@ -5650,6 +5677,7 @@ intel_execlists_create_virtual(struct intel_engine_cs **siblings,
        intel_engine_init_active(&ve->base, ENGINE_VIRTUAL);
        intel_engine_init_breadcrumbs(&ve->base);
        intel_engine_init_execlists(&ve->base);
+       ve->base.breadcrumbs.irq_armed = true; /* fake HW, used for irq_work */
 
        ve->base.cops = &virtual_context_ops;
        ve->base.request_alloc = execlists_request_alloc;
@@ -5731,6 +5759,7 @@ intel_execlists_create_virtual(struct intel_engine_cs **siblings,
 
        ve->base.flags |= I915_ENGINE_IS_VIRTUAL;
 
+       virtual_engine_initial_hint(ve);
        return &ve->context;
 
 err_put:
index 8cda1b7..bdb3241 100644 (file)
@@ -315,3 +315,7 @@ int intel_ring_cacheline_align(struct i915_request *rq)
        GEM_BUG_ON(rq->ring->emit & (CACHELINE_BYTES - 1));
        return 0;
 }
+
+#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
+#include "selftest_ring.c"
+#endif
index 90a2b9e..85d2bef 100644 (file)
@@ -178,6 +178,12 @@ wa_write_or(struct i915_wa_list *wal, i915_reg_t reg, u32 set)
        wa_write_masked_or(wal, reg, set, set);
 }
 
+static void
+wa_write_clr(struct i915_wa_list *wal, i915_reg_t reg, u32 clr)
+{
+       wa_write_masked_or(wal, reg, clr, 0);
+}
+
 static void
 wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
 {
@@ -686,6 +692,227 @@ int intel_engine_emit_ctx_wa(struct i915_request *rq)
        return 0;
 }
 
+static void
+gen4_gt_workarounds_init(struct drm_i915_private *i915,
+                        struct i915_wa_list *wal)
+{
+       /* WaDisable_RenderCache_OperationalFlush:gen4,ilk */
+       wa_masked_dis(wal, CACHE_MODE_0, RC_OP_FLUSH_ENABLE);
+}
+
+static void
+g4x_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
+{
+       gen4_gt_workarounds_init(i915, wal);
+
+       /* WaDisableRenderCachePipelinedFlush:g4x,ilk */
+       wa_masked_en(wal, CACHE_MODE_0, CM0_PIPELINED_RENDER_FLUSH_DISABLE);
+}
+
+static void
+ilk_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
+{
+       g4x_gt_workarounds_init(i915, wal);
+
+       wa_masked_en(wal, _3D_CHICKEN2, _3D_CHICKEN2_WM_READ_PIPELINED);
+}
+
+static void
+snb_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
+{
+       /* WaDisableHiZPlanesWhenMSAAEnabled:snb */
+       wa_masked_en(wal,
+                    _3D_CHICKEN,
+                    _3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB);
+
+       /* WaDisable_RenderCache_OperationalFlush:snb */
+       wa_masked_dis(wal, CACHE_MODE_0, RC_OP_FLUSH_ENABLE);
+
+       /*
+        * BSpec recommends 8x4 when MSAA is used,
+        * however in practice 16x4 seems fastest.
+        *
+        * Note that PS/WM thread counts depend on the WIZ hashing
+        * disable bit, which we don't touch here, but it's good
+        * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
+        */
+       wa_add(wal,
+              GEN6_GT_MODE, 0,
+              _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4),
+              GEN6_WIZ_HASHING_16x4);
+
+       wa_masked_dis(wal, CACHE_MODE_0, CM0_STC_EVICT_DISABLE_LRA_SNB);
+
+       wa_masked_en(wal,
+                    _3D_CHICKEN3,
+                    /* WaStripsFansDisableFastClipPerformanceFix:snb */
+                    _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL |
+                    /*
+                     * Bspec says:
+                     * "This bit must be set if 3DSTATE_CLIP clip mode is set
+                     * to normal and 3DSTATE_SF number of SF output attributes
+                     * is more than 16."
+                     */
+                  _3D_CHICKEN3_SF_DISABLE_PIPELINED_ATTR_FETCH);
+}
+
+static void
+ivb_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
+{
+       /* WaDisableEarlyCull:ivb */
+       wa_masked_en(wal, _3D_CHICKEN3, _3D_CHICKEN_SF_DISABLE_OBJEND_CULL);
+
+       /* WaDisablePSDDualDispatchEnable:ivb */
+       if (IS_IVB_GT1(i915))
+               wa_masked_en(wal,
+                            GEN7_HALF_SLICE_CHICKEN1,
+                            GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE);
+
+       /* WaDisable_RenderCache_OperationalFlush:ivb */
+       wa_masked_dis(wal, CACHE_MODE_0_GEN7, RC_OP_FLUSH_ENABLE);
+
+       /* Apply the WaDisableRHWOOptimizationForRenderHang:ivb workaround. */
+       wa_masked_dis(wal,
+                     GEN7_COMMON_SLICE_CHICKEN1,
+                     GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
+
+       /* WaApplyL3ControlAndL3ChickenMode:ivb */
+       wa_write(wal, GEN7_L3CNTLREG1, GEN7_WA_FOR_GEN7_L3_CONTROL);
+       wa_write(wal, GEN7_L3_CHICKEN_MODE_REGISTER, GEN7_WA_L3_CHICKEN_MODE);
+
+       /* WaForceL3Serialization:ivb */
+       wa_write_clr(wal, GEN7_L3SQCREG4, L3SQ_URB_READ_CAM_MATCH_DISABLE);
+
+       /*
+        * WaVSThreadDispatchOverride:ivb,vlv
+        *
+        * This actually overrides the dispatch
+        * mode for all thread types.
+        */
+       wa_write_masked_or(wal, GEN7_FF_THREAD_MODE,
+                          GEN7_FF_SCHED_MASK,
+                          GEN7_FF_TS_SCHED_HW |
+                          GEN7_FF_VS_SCHED_HW |
+                          GEN7_FF_DS_SCHED_HW);
+
+       if (0) { /* causes HiZ corruption on ivb:gt1 */
+               /* enable HiZ Raw Stall Optimization */
+               wa_masked_dis(wal, CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE);
+       }
+
+       /* WaDisable4x2SubspanOptimization:ivb */
+       wa_masked_en(wal, CACHE_MODE_1, PIXEL_SUBSPAN_COLLECT_OPT_DISABLE);
+
+       /*
+        * BSpec recommends 8x4 when MSAA is used,
+        * however in practice 16x4 seems fastest.
+        *
+        * Note that PS/WM thread counts depend on the WIZ hashing
+        * disable bit, which we don't touch here, but it's good
+        * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
+        */
+       wa_add(wal, GEN7_GT_MODE, 0,
+              _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4),
+              GEN6_WIZ_HASHING_16x4);
+}
+
+static void
+vlv_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
+{
+       /* WaDisableEarlyCull:vlv */
+       wa_masked_en(wal, _3D_CHICKEN3, _3D_CHICKEN_SF_DISABLE_OBJEND_CULL);
+
+       /* WaPsdDispatchEnable:vlv */
+       /* WaDisablePSDDualDispatchEnable:vlv */
+       wa_masked_en(wal,
+                    GEN7_HALF_SLICE_CHICKEN1,
+                    GEN7_MAX_PS_THREAD_DEP |
+                    GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE);
+
+       /* WaDisable_RenderCache_OperationalFlush:vlv */
+       wa_masked_dis(wal, CACHE_MODE_0_GEN7, RC_OP_FLUSH_ENABLE);
+
+       /* WaForceL3Serialization:vlv */
+       wa_write_clr(wal, GEN7_L3SQCREG4, L3SQ_URB_READ_CAM_MATCH_DISABLE);
+
+       /*
+        * WaVSThreadDispatchOverride:ivb,vlv
+        *
+        * This actually overrides the dispatch
+        * mode for all thread types.
+        */
+       wa_write_masked_or(wal,
+                          GEN7_FF_THREAD_MODE,
+                          GEN7_FF_SCHED_MASK,
+                          GEN7_FF_TS_SCHED_HW |
+                          GEN7_FF_VS_SCHED_HW |
+                          GEN7_FF_DS_SCHED_HW);
+
+       /*
+        * BSpec says this must be set, even though
+        * WaDisable4x2SubspanOptimization isn't listed for VLV.
+        */
+       wa_masked_en(wal, CACHE_MODE_1, PIXEL_SUBSPAN_COLLECT_OPT_DISABLE);
+
+       /*
+        * BSpec recommends 8x4 when MSAA is used,
+        * however in practice 16x4 seems fastest.
+        *
+        * Note that PS/WM thread counts depend on the WIZ hashing
+        * disable bit, which we don't touch here, but it's good
+        * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
+        */
+       wa_add(wal, GEN7_GT_MODE, 0,
+              _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4),
+              GEN6_WIZ_HASHING_16x4);
+
+       /*
+        * WaIncreaseL3CreditsForVLVB0:vlv
+        * This is the hardware default actually.
+        */
+       wa_write(wal, GEN7_L3SQCREG1, VLV_B0_WA_L3SQCREG1_VALUE);
+}
+
+static void
+hsw_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
+{
+       /* L3 caching of data atomics doesn't work -- disable it. */
+       wa_write(wal, HSW_SCRATCH1, HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE);
+
+       wa_add(wal,
+              HSW_ROW_CHICKEN3, 0,
+              _MASKED_BIT_ENABLE(HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE),
+               0 /* XXX does this reg exist? */);
+
+       /* WaVSRefCountFullforceMissDisable:hsw */
+       wa_write_clr(wal, GEN7_FF_THREAD_MODE, GEN7_FF_VS_REF_CNT_FFME);
+
+       wa_masked_dis(wal,
+                     CACHE_MODE_0_GEN7,
+                     /* WaDisable_RenderCache_OperationalFlush:hsw */
+                     RC_OP_FLUSH_ENABLE |
+                     /* enable HiZ Raw Stall Optimization */
+                     HIZ_RAW_STALL_OPT_DISABLE);
+
+       /* WaDisable4x2SubspanOptimization:hsw */
+       wa_masked_en(wal, CACHE_MODE_1, PIXEL_SUBSPAN_COLLECT_OPT_DISABLE);
+
+       /*
+        * BSpec recommends 8x4 when MSAA is used,
+        * however in practice 16x4 seems fastest.
+        *
+        * Note that PS/WM thread counts depend on the WIZ hashing
+        * disable bit, which we don't touch here, but it's good
+        * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
+        */
+       wa_add(wal, GEN7_GT_MODE, 0,
+              _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4),
+              GEN6_WIZ_HASHING_16x4);
+
+       /* WaSampleCChickenBitEnable:hsw */
+       wa_masked_en(wal, HALF_SLICE_CHICKEN3, HSW_SAMPLE_C_PERFORMANCE);
+}
+
 static void
 gen9_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
 {
@@ -963,6 +1190,20 @@ gt_init_workarounds(struct drm_i915_private *i915, struct i915_wa_list *wal)
                bxt_gt_workarounds_init(i915, wal);
        else if (IS_SKYLAKE(i915))
                skl_gt_workarounds_init(i915, wal);
+       else if (IS_HASWELL(i915))
+               hsw_gt_workarounds_init(i915, wal);
+       else if (IS_VALLEYVIEW(i915))
+               vlv_gt_workarounds_init(i915, wal);
+       else if (IS_IVYBRIDGE(i915))
+               ivb_gt_workarounds_init(i915, wal);
+       else if (IS_GEN(i915, 6))
+               snb_gt_workarounds_init(i915, wal);
+       else if (IS_GEN(i915, 5))
+               ilk_gt_workarounds_init(i915, wal);
+       else if (IS_G4X(i915))
+               g4x_gt_workarounds_init(i915, wal);
+       else if (IS_GEN(i915, 4))
+               gen4_gt_workarounds_init(i915, wal);
        else if (INTEL_GEN(i915) <= 8)
                return;
        else
index 2b2efff..4aa4cc9 100644 (file)
@@ -310,22 +310,20 @@ static bool wait_until_running(struct hang *h, struct i915_request *rq)
                          1000));
 }
 
-static void engine_heartbeat_disable(struct intel_engine_cs *engine,
-                                    unsigned long *saved)
+static void engine_heartbeat_disable(struct intel_engine_cs *engine)
 {
-       *saved = engine->props.heartbeat_interval_ms;
        engine->props.heartbeat_interval_ms = 0;
 
        intel_engine_pm_get(engine);
        intel_engine_park_heartbeat(engine);
 }
 
-static void engine_heartbeat_enable(struct intel_engine_cs *engine,
-                                   unsigned long saved)
+static void engine_heartbeat_enable(struct intel_engine_cs *engine)
 {
        intel_engine_pm_put(engine);
 
-       engine->props.heartbeat_interval_ms = saved;
+       engine->props.heartbeat_interval_ms =
+               engine->defaults.heartbeat_interval_ms;
 }
 
 static int igt_hang_sanitycheck(void *arg)
@@ -473,7 +471,6 @@ static int igt_reset_nop_engine(void *arg)
        for_each_engine(engine, gt, id) {
                unsigned int reset_count, reset_engine_count, count;
                struct intel_context *ce;
-               unsigned long heartbeat;
                IGT_TIMEOUT(end_time);
                int err;
 
@@ -485,7 +482,7 @@ static int igt_reset_nop_engine(void *arg)
                reset_engine_count = i915_reset_engine_count(global, engine);
                count = 0;
 
-               engine_heartbeat_disable(engine, &heartbeat);
+               engine_heartbeat_disable(engine);
                set_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
                do {
                        int i;
@@ -529,7 +526,7 @@ static int igt_reset_nop_engine(void *arg)
                        }
                } while (time_before(jiffies, end_time));
                clear_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
-               engine_heartbeat_enable(engine, heartbeat);
+               engine_heartbeat_enable(engine);
 
                pr_info("%s(%s): %d resets\n", __func__, engine->name, count);
 
@@ -564,7 +561,6 @@ static int __igt_reset_engine(struct intel_gt *gt, bool active)
 
        for_each_engine(engine, gt, id) {
                unsigned int reset_count, reset_engine_count;
-               unsigned long heartbeat;
                IGT_TIMEOUT(end_time);
 
                if (active && !intel_engine_can_store_dword(engine))
@@ -580,7 +576,7 @@ static int __igt_reset_engine(struct intel_gt *gt, bool active)
                reset_count = i915_reset_count(global);
                reset_engine_count = i915_reset_engine_count(global, engine);
 
-               engine_heartbeat_disable(engine, &heartbeat);
+               engine_heartbeat_disable(engine);
                set_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
                do {
                        if (active) {
@@ -632,7 +628,7 @@ static int __igt_reset_engine(struct intel_gt *gt, bool active)
                        }
                } while (time_before(jiffies, end_time));
                clear_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
-               engine_heartbeat_enable(engine, heartbeat);
+               engine_heartbeat_enable(engine);
 
                if (err)
                        break;
@@ -789,7 +785,6 @@ static int __igt_reset_engines(struct intel_gt *gt,
                struct active_engine threads[I915_NUM_ENGINES] = {};
                unsigned long device = i915_reset_count(global);
                unsigned long count = 0, reported;
-               unsigned long heartbeat;
                IGT_TIMEOUT(end_time);
 
                if (flags & TEST_ACTIVE &&
@@ -832,7 +827,7 @@ static int __igt_reset_engines(struct intel_gt *gt,
 
                yield(); /* start all threads before we begin */
 
-               engine_heartbeat_disable(engine, &heartbeat);
+               engine_heartbeat_disable(engine);
                set_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
                do {
                        struct i915_request *rq = NULL;
@@ -906,7 +901,7 @@ static int __igt_reset_engines(struct intel_gt *gt,
                        }
                } while (time_before(jiffies, end_time));
                clear_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
-               engine_heartbeat_enable(engine, heartbeat);
+               engine_heartbeat_enable(engine);
 
                pr_info("i915_reset_engine(%s:%s): %lu resets\n",
                        engine->name, test_name, count);
index 824f99c..924bc01 100644 (file)
@@ -51,22 +51,20 @@ static struct i915_vma *create_scratch(struct intel_gt *gt)
        return vma;
 }
 
-static void engine_heartbeat_disable(struct intel_engine_cs *engine,
-                                    unsigned long *saved)
+static void engine_heartbeat_disable(struct intel_engine_cs *engine)
 {
-       *saved = engine->props.heartbeat_interval_ms;
        engine->props.heartbeat_interval_ms = 0;
 
        intel_engine_pm_get(engine);
        intel_engine_park_heartbeat(engine);
 }
 
-static void engine_heartbeat_enable(struct intel_engine_cs *engine,
-                                   unsigned long saved)
+static void engine_heartbeat_enable(struct intel_engine_cs *engine)
 {
        intel_engine_pm_put(engine);
 
-       engine->props.heartbeat_interval_ms = saved;
+       engine->props.heartbeat_interval_ms =
+               engine->defaults.heartbeat_interval_ms;
 }
 
 static bool is_active(struct i915_request *rq)
@@ -224,7 +222,6 @@ static int live_unlite_restore(struct intel_gt *gt, int prio)
                struct intel_context *ce[2] = {};
                struct i915_request *rq[2];
                struct igt_live_test t;
-               unsigned long saved;
                int n;
 
                if (prio && !intel_engine_has_preemption(engine))
@@ -237,7 +234,7 @@ static int live_unlite_restore(struct intel_gt *gt, int prio)
                        err = -EIO;
                        break;
                }
-               engine_heartbeat_disable(engine, &saved);
+               engine_heartbeat_disable(engine);
 
                for (n = 0; n < ARRAY_SIZE(ce); n++) {
                        struct intel_context *tmp;
@@ -345,7 +342,7 @@ err_ce:
                        intel_context_put(ce[n]);
                }
 
-               engine_heartbeat_enable(engine, saved);
+               engine_heartbeat_enable(engine);
                if (igt_live_test_end(&t))
                        err = -EIO;
                if (err)
@@ -466,7 +463,6 @@ static int live_hold_reset(void *arg)
 
        for_each_engine(engine, gt, id) {
                struct intel_context *ce;
-               unsigned long heartbeat;
                struct i915_request *rq;
 
                ce = intel_context_create(engine);
@@ -475,7 +471,7 @@ static int live_hold_reset(void *arg)
                        break;
                }
 
-               engine_heartbeat_disable(engine, &heartbeat);
+               engine_heartbeat_disable(engine);
 
                rq = igt_spinner_create_request(&spin, ce, MI_ARB_CHECK);
                if (IS_ERR(rq)) {
@@ -535,7 +531,7 @@ static int live_hold_reset(void *arg)
                i915_request_put(rq);
 
 out:
-               engine_heartbeat_enable(engine, heartbeat);
+               engine_heartbeat_enable(engine);
                intel_context_put(ce);
                if (err)
                        break;
@@ -580,10 +576,9 @@ static int live_error_interrupt(void *arg)
 
        for_each_engine(engine, gt, id) {
                const struct error_phase *p;
-               unsigned long heartbeat;
                int err = 0;
 
-               engine_heartbeat_disable(engine, &heartbeat);
+               engine_heartbeat_disable(engine);
 
                for (p = phases; p->error[0] != GOOD; p++) {
                        struct i915_request *client[ARRAY_SIZE(phases->error)];
@@ -682,7 +677,7 @@ out:
                        }
                }
 
-               engine_heartbeat_enable(engine, heartbeat);
+               engine_heartbeat_enable(engine);
                if (err) {
                        intel_gt_set_wedged(gt);
                        return err;
@@ -828,7 +823,7 @@ slice_semaphore_queue(struct intel_engine_cs *outer,
                }
        }
 
-       err = release_queue(outer, vma, n, INT_MAX);
+       err = release_queue(outer, vma, n, I915_PRIORITY_BARRIER);
        if (err)
                goto out;
 
@@ -895,16 +890,14 @@ static int live_timeslice_preempt(void *arg)
                enum intel_engine_id id;
 
                for_each_engine(engine, gt, id) {
-                       unsigned long saved;
-
                        if (!intel_engine_has_preemption(engine))
                                continue;
 
                        memset(vaddr, 0, PAGE_SIZE);
 
-                       engine_heartbeat_disable(engine, &saved);
+                       engine_heartbeat_disable(engine);
                        err = slice_semaphore_queue(engine, vma, count);
-                       engine_heartbeat_enable(engine, saved);
+                       engine_heartbeat_enable(engine);
                        if (err)
                                goto err_pin;
 
@@ -1009,7 +1002,6 @@ static int live_timeslice_rewind(void *arg)
                enum { X = 1, Z, Y };
                struct i915_request *rq[3] = {};
                struct intel_context *ce;
-               unsigned long heartbeat;
                unsigned long timeslice;
                int i, err = 0;
                u32 *slot;
@@ -1028,7 +1020,7 @@ static int live_timeslice_rewind(void *arg)
                 * Expect execution/evaluation order XZY
                 */
 
-               engine_heartbeat_disable(engine, &heartbeat);
+               engine_heartbeat_disable(engine);
                timeslice = xchg(&engine->props.timeslice_duration_ms, 1);
 
                slot = memset32(engine->status_page.addr + 1000, 0, 4);
@@ -1122,7 +1114,7 @@ err:
                wmb();
 
                engine->props.timeslice_duration_ms = timeslice;
-               engine_heartbeat_enable(engine, heartbeat);
+               engine_heartbeat_enable(engine);
                for (i = 0; i < 3; i++)
                        i915_request_put(rq[i]);
                if (igt_flush_test(gt->i915))
@@ -1202,12 +1194,11 @@ static int live_timeslice_queue(void *arg)
                        .priority = I915_USER_PRIORITY(I915_PRIORITY_MAX),
                };
                struct i915_request *rq, *nop;
-               unsigned long saved;
 
                if (!intel_engine_has_preemption(engine))
                        continue;
 
-               engine_heartbeat_disable(engine, &saved);
+               engine_heartbeat_disable(engine);
                memset(vaddr, 0, PAGE_SIZE);
 
                /* ELSP[0]: semaphore wait */
@@ -1284,7 +1275,7 @@ static int live_timeslice_queue(void *arg)
 err_rq:
                i915_request_put(rq);
 err_heartbeat:
-               engine_heartbeat_enable(engine, saved);
+               engine_heartbeat_enable(engine);
                if (err)
                        break;
        }
@@ -1298,6 +1289,121 @@ err_obj:
        return err;
 }
 
+static int live_timeslice_nopreempt(void *arg)
+{
+       struct intel_gt *gt = arg;
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
+       struct igt_spinner spin;
+       int err = 0;
+
+       /*
+        * We should not timeslice into a request that is marked with
+        * I915_REQUEST_NOPREEMPT.
+        */
+       if (!IS_ACTIVE(CONFIG_DRM_I915_TIMESLICE_DURATION))
+               return 0;
+
+       if (igt_spinner_init(&spin, gt))
+               return -ENOMEM;
+
+       for_each_engine(engine, gt, id) {
+               struct intel_context *ce;
+               struct i915_request *rq;
+               unsigned long timeslice;
+
+               if (!intel_engine_has_preemption(engine))
+                       continue;
+
+               ce = intel_context_create(engine);
+               if (IS_ERR(ce)) {
+                       err = PTR_ERR(ce);
+                       break;
+               }
+
+               engine_heartbeat_disable(engine);
+               timeslice = xchg(&engine->props.timeslice_duration_ms, 1);
+
+               /* Create an unpreemptible spinner */
+
+               rq = igt_spinner_create_request(&spin, ce, MI_ARB_CHECK);
+               intel_context_put(ce);
+               if (IS_ERR(rq)) {
+                       err = PTR_ERR(rq);
+                       goto out_heartbeat;
+               }
+
+               i915_request_get(rq);
+               i915_request_add(rq);
+
+               if (!igt_wait_for_spinner(&spin, rq)) {
+                       i915_request_put(rq);
+                       err = -ETIME;
+                       goto out_spin;
+               }
+
+               set_bit(I915_FENCE_FLAG_NOPREEMPT, &rq->fence.flags);
+               i915_request_put(rq);
+
+               /* Followed by a maximum priority barrier (heartbeat) */
+
+               ce = intel_context_create(engine);
+               if (IS_ERR(ce)) {
+                       err = PTR_ERR(rq);
+                       goto out_spin;
+               }
+
+               rq = intel_context_create_request(ce);
+               intel_context_put(ce);
+               if (IS_ERR(rq)) {
+                       err = PTR_ERR(rq);
+                       goto out_spin;
+               }
+
+               rq->sched.attr.priority = I915_PRIORITY_BARRIER;
+               i915_request_get(rq);
+               i915_request_add(rq);
+
+               /*
+                * Wait until the barrier is in ELSP, and we know timeslicing
+                * will have been activated.
+                */
+               if (wait_for_submit(engine, rq, HZ / 2)) {
+                       i915_request_put(rq);
+                       err = -ETIME;
+                       goto out_spin;
+               }
+
+               /*
+                * Since the ELSP[0] request is unpreemptible, it should not
+                * allow the maximum priority barrier through. Wait long
+                * enough to see if it is timesliced in by mistake.
+                */
+               if (i915_request_wait(rq, 0, timeslice_threshold(engine)) >= 0) {
+                       pr_err("%s: I915_PRIORITY_BARRIER request completed, bypassing no-preempt request\n",
+                              engine->name);
+                       err = -EINVAL;
+               }
+               i915_request_put(rq);
+
+out_spin:
+               igt_spinner_end(&spin);
+out_heartbeat:
+               xchg(&engine->props.timeslice_duration_ms, timeslice);
+               engine_heartbeat_enable(engine);
+               if (err)
+                       break;
+
+               if (igt_flush_test(gt->i915)) {
+                       err = -EIO;
+                       break;
+               }
+       }
+
+       igt_spinner_fini(&spin);
+       return err;
+}
+
 static int live_busywait_preempt(void *arg)
 {
        struct intel_gt *gt = arg;
@@ -4153,7 +4259,6 @@ static int reset_virtual_engine(struct intel_gt *gt,
 {
        struct intel_engine_cs *engine;
        struct intel_context *ve;
-       unsigned long *heartbeat;
        struct igt_spinner spin;
        struct i915_request *rq;
        unsigned int n;
@@ -4165,15 +4270,9 @@ static int reset_virtual_engine(struct intel_gt *gt,
         * descendents are not executed while the capture is in progress.
         */
 
-       heartbeat = kmalloc_array(nsibling, sizeof(*heartbeat), GFP_KERNEL);
-       if (!heartbeat)
+       if (igt_spinner_init(&spin, gt))
                return -ENOMEM;
 
-       if (igt_spinner_init(&spin, gt)) {
-               err = -ENOMEM;
-               goto out_free;
-       }
-
        ve = intel_execlists_create_virtual(siblings, nsibling);
        if (IS_ERR(ve)) {
                err = PTR_ERR(ve);
@@ -4181,7 +4280,7 @@ static int reset_virtual_engine(struct intel_gt *gt,
        }
 
        for (n = 0; n < nsibling; n++)
-               engine_heartbeat_disable(siblings[n], &heartbeat[n]);
+               engine_heartbeat_disable(siblings[n]);
 
        rq = igt_spinner_create_request(&spin, ve, MI_ARB_CHECK);
        if (IS_ERR(rq)) {
@@ -4252,13 +4351,11 @@ out_rq:
        i915_request_put(rq);
 out_heartbeat:
        for (n = 0; n < nsibling; n++)
-               engine_heartbeat_enable(siblings[n], heartbeat[n]);
+               engine_heartbeat_enable(siblings[n]);
 
        intel_context_put(ve);
 out_spin:
        igt_spinner_fini(&spin);
-out_free:
-       kfree(heartbeat);
        return err;
 }
 
@@ -4314,6 +4411,7 @@ int intel_execlists_live_selftests(struct drm_i915_private *i915)
                SUBTEST(live_timeslice_preempt),
                SUBTEST(live_timeslice_rewind),
                SUBTEST(live_timeslice_queue),
+               SUBTEST(live_timeslice_nopreempt),
                SUBTEST(live_busywait_preempt),
                SUBTEST(live_preempt),
                SUBTEST(live_late_preempt),
@@ -4932,9 +5030,7 @@ static int live_lrc_gpr(void *arg)
                return PTR_ERR(scratch);
 
        for_each_engine(engine, gt, id) {
-               unsigned long heartbeat;
-
-               engine_heartbeat_disable(engine, &heartbeat);
+               engine_heartbeat_disable(engine);
 
                err = __live_lrc_gpr(engine, scratch, false);
                if (err)
@@ -4945,7 +5041,7 @@ static int live_lrc_gpr(void *arg)
                        goto err;
 
 err:
-               engine_heartbeat_enable(engine, heartbeat);
+               engine_heartbeat_enable(engine);
                if (igt_flush_test(gt->i915))
                        err = -EIO;
                if (err)
@@ -5092,10 +5188,9 @@ static int live_lrc_timestamp(void *arg)
         */
 
        for_each_engine(data.engine, gt, id) {
-               unsigned long heartbeat;
                int i, err = 0;
 
-               engine_heartbeat_disable(data.engine, &heartbeat);
+               engine_heartbeat_disable(data.engine);
 
                for (i = 0; i < ARRAY_SIZE(data.ce); i++) {
                        struct intel_context *tmp;
@@ -5128,7 +5223,7 @@ static int live_lrc_timestamp(void *arg)
                }
 
 err:
-               engine_heartbeat_enable(data.engine, heartbeat);
+               engine_heartbeat_enable(data.engine);
                for (i = 0; i < ARRAY_SIZE(data.ce); i++) {
                        if (!data.ce[i])
                                break;
index 8831ffe..63f87d8 100644 (file)
@@ -18,6 +18,20 @@ struct live_mocs {
        void *vaddr;
 };
 
+static struct intel_context *mocs_context_create(struct intel_engine_cs *engine)
+{
+       struct intel_context *ce;
+
+       ce = intel_context_create(engine);
+       if (IS_ERR(ce))
+               return ce;
+
+       /* We build large requests to read the registers from the ring */
+       ce->ring = __intel_context_ring_size(SZ_16K);
+
+       return ce;
+}
+
 static int request_add_sync(struct i915_request *rq, int err)
 {
        i915_request_get(rq);
@@ -301,7 +315,7 @@ static int live_mocs_clean(void *arg)
        for_each_engine(engine, gt, id) {
                struct intel_context *ce;
 
-               ce = intel_context_create(engine);
+               ce = mocs_context_create(engine);
                if (IS_ERR(ce)) {
                        err = PTR_ERR(ce);
                        break;
@@ -395,7 +409,7 @@ static int live_mocs_reset(void *arg)
        for_each_engine(engine, gt, id) {
                struct intel_context *ce;
 
-               ce = intel_context_create(engine);
+               ce = mocs_context_create(engine);
                if (IS_ERR(ce)) {
                        err = PTR_ERR(ce);
                        break;
diff --git a/drivers/gpu/drm/i915/gt/selftest_ring.c b/drivers/gpu/drm/i915/gt/selftest_ring.c
new file mode 100644 (file)
index 0000000..2a8c534
--- /dev/null
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright Â© 2020 Intel Corporation
+ */
+
+static struct intel_ring *mock_ring(unsigned long sz)
+{
+       struct intel_ring *ring;
+
+       ring = kzalloc(sizeof(*ring) + sz, GFP_KERNEL);
+       if (!ring)
+               return NULL;
+
+       kref_init(&ring->ref);
+       ring->size = sz;
+       ring->wrap = BITS_PER_TYPE(ring->size) - ilog2(sz);
+       ring->effective_size = sz;
+       ring->vaddr = (void *)(ring + 1);
+       atomic_set(&ring->pin_count, 1);
+
+       intel_ring_update_space(ring);
+
+       return ring;
+}
+
+static void mock_ring_free(struct intel_ring *ring)
+{
+       kfree(ring);
+}
+
+static int check_ring_direction(struct intel_ring *ring,
+                               u32 next, u32 prev,
+                               int expected)
+{
+       int result;
+
+       result = intel_ring_direction(ring, next, prev);
+       if (result < 0)
+               result = -1;
+       else if (result > 0)
+               result = 1;
+
+       if (result != expected) {
+               pr_err("intel_ring_direction(%u, %u):%d != %d\n",
+                      next, prev, result, expected);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int check_ring_step(struct intel_ring *ring, u32 x, u32 step)
+{
+       u32 prev = x, next = intel_ring_wrap(ring, x + step);
+       int err = 0;
+
+       err |= check_ring_direction(ring, next, next,  0);
+       err |= check_ring_direction(ring, prev, prev,  0);
+       err |= check_ring_direction(ring, next, prev,  1);
+       err |= check_ring_direction(ring, prev, next, -1);
+
+       return err;
+}
+
+static int check_ring_offset(struct intel_ring *ring, u32 x, u32 step)
+{
+       int err = 0;
+
+       err |= check_ring_step(ring, x, step);
+       err |= check_ring_step(ring, intel_ring_wrap(ring, x + 1), step);
+       err |= check_ring_step(ring, intel_ring_wrap(ring, x - 1), step);
+
+       return err;
+}
+
+static int igt_ring_direction(void *dummy)
+{
+       struct intel_ring *ring;
+       unsigned int half = 2048;
+       int step, err = 0;
+
+       ring = mock_ring(2 * half);
+       if (!ring)
+               return -ENOMEM;
+
+       GEM_BUG_ON(ring->size != 2 * half);
+
+       /* Precision of wrap detection is limited to ring->size / 2 */
+       for (step = 1; step < half; step <<= 1) {
+               err |= check_ring_offset(ring, 0, step);
+               err |= check_ring_offset(ring, half, step);
+       }
+       err |= check_ring_step(ring, 0, half - 64);
+
+       /* And check unwrapped handling for good measure */
+       err |= check_ring_offset(ring, 0, 2 * half + 64);
+       err |= check_ring_offset(ring, 3 * half, 1);
+
+       mock_ring_free(ring);
+       return err;
+}
+
+int intel_ring_mock_selftests(void)
+{
+       static const struct i915_subtest tests[] = {
+               SUBTEST(igt_ring_direction),
+       };
+
+       return i915_subtests(tests, NULL);
+}
index 6275d69..c91981e 100644 (file)
 /* Try to isolate the impact of cstates from determing frequency response */
 #define CPU_LATENCY 0 /* -1 to disable pm_qos, 0 to disable cstates */
 
-static unsigned long engine_heartbeat_disable(struct intel_engine_cs *engine)
+static void engine_heartbeat_disable(struct intel_engine_cs *engine)
 {
-       unsigned long old;
-
-       old = fetch_and_zero(&engine->props.heartbeat_interval_ms);
+       engine->props.heartbeat_interval_ms = 0;
 
        intel_engine_pm_get(engine);
        intel_engine_park_heartbeat(engine);
-
-       return old;
 }
 
-static void engine_heartbeat_enable(struct intel_engine_cs *engine,
-                                   unsigned long saved)
+static void engine_heartbeat_enable(struct intel_engine_cs *engine)
 {
        intel_engine_pm_put(engine);
 
-       engine->props.heartbeat_interval_ms = saved;
+       engine->props.heartbeat_interval_ms =
+               engine->defaults.heartbeat_interval_ms;
 }
 
 static void dummy_rps_work(struct work_struct *wrk)
@@ -48,9 +44,9 @@ static int cmp_u64(const void *A, const void *B)
 {
        const u64 *a = A, *b = B;
 
-       if (a < b)
+       if (*a < *b)
                return -1;
-       else if (a > b)
+       else if (*a > *b)
                return 1;
        else
                return 0;
@@ -60,9 +56,9 @@ static int cmp_u32(const void *A, const void *B)
 {
        const u32 *a = A, *b = B;
 
-       if (a < b)
+       if (*a < *b)
                return -1;
-       else if (a > b)
+       else if (*a > *b)
                return 1;
        else
                return 0;
@@ -246,7 +242,6 @@ int live_rps_clock_interval(void *arg)
        intel_gt_check_clock_frequency(gt);
 
        for_each_engine(engine, gt, id) {
-               unsigned long saved_heartbeat;
                struct i915_request *rq;
                u32 cycles;
                u64 dt;
@@ -254,13 +249,13 @@ int live_rps_clock_interval(void *arg)
                if (!intel_engine_can_store_dword(engine))
                        continue;
 
-               saved_heartbeat = engine_heartbeat_disable(engine);
+               engine_heartbeat_disable(engine);
 
                rq = igt_spinner_create_request(&spin,
                                                engine->kernel_context,
                                                MI_NOOP);
                if (IS_ERR(rq)) {
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        err = PTR_ERR(rq);
                        break;
                }
@@ -271,7 +266,7 @@ int live_rps_clock_interval(void *arg)
                        pr_err("%s: RPS spinner did not start\n",
                               engine->name);
                        igt_spinner_end(&spin);
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        intel_gt_set_wedged(engine->gt);
                        err = -EIO;
                        break;
@@ -327,7 +322,7 @@ int live_rps_clock_interval(void *arg)
                intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL);
 
                igt_spinner_end(&spin);
-               engine_heartbeat_enable(engine, saved_heartbeat);
+               engine_heartbeat_enable(engine);
 
                if (err == 0) {
                        u64 time = intel_gt_pm_interval_to_ns(gt, cycles);
@@ -405,7 +400,6 @@ int live_rps_control(void *arg)
 
        intel_gt_pm_get(gt);
        for_each_engine(engine, gt, id) {
-               unsigned long saved_heartbeat;
                struct i915_request *rq;
                ktime_t min_dt, max_dt;
                int f, limit;
@@ -414,7 +408,7 @@ int live_rps_control(void *arg)
                if (!intel_engine_can_store_dword(engine))
                        continue;
 
-               saved_heartbeat = engine_heartbeat_disable(engine);
+               engine_heartbeat_disable(engine);
 
                rq = igt_spinner_create_request(&spin,
                                                engine->kernel_context,
@@ -430,7 +424,7 @@ int live_rps_control(void *arg)
                        pr_err("%s: RPS spinner did not start\n",
                               engine->name);
                        igt_spinner_end(&spin);
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        intel_gt_set_wedged(engine->gt);
                        err = -EIO;
                        break;
@@ -440,7 +434,7 @@ int live_rps_control(void *arg)
                        pr_err("%s: could not set minimum frequency [%x], only %x!\n",
                               engine->name, rps->min_freq, read_cagf(rps));
                        igt_spinner_end(&spin);
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        show_pstate_limits(rps);
                        err = -EINVAL;
                        break;
@@ -457,7 +451,7 @@ int live_rps_control(void *arg)
                        pr_err("%s: could not restore minimum frequency [%x], only %x!\n",
                               engine->name, rps->min_freq, read_cagf(rps));
                        igt_spinner_end(&spin);
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        show_pstate_limits(rps);
                        err = -EINVAL;
                        break;
@@ -472,7 +466,7 @@ int live_rps_control(void *arg)
                min_dt = ktime_sub(ktime_get(), min_dt);
 
                igt_spinner_end(&spin);
-               engine_heartbeat_enable(engine, saved_heartbeat);
+               engine_heartbeat_enable(engine);
 
                pr_info("%s: range:[%x:%uMHz, %x:%uMHz] limit:[%x:%uMHz], %x:%x response %lluns:%lluns\n",
                        engine->name,
@@ -635,7 +629,6 @@ int live_rps_frequency_cs(void *arg)
        rps->work.func = dummy_rps_work;
 
        for_each_engine(engine, gt, id) {
-               unsigned long saved_heartbeat;
                struct i915_request *rq;
                struct i915_vma *vma;
                u32 *cancel, *cntr;
@@ -644,14 +637,14 @@ int live_rps_frequency_cs(void *arg)
                        int freq;
                } min, max;
 
-               saved_heartbeat = engine_heartbeat_disable(engine);
+               engine_heartbeat_disable(engine);
 
                vma = create_spin_counter(engine,
                                          engine->kernel_context->vm, false,
                                          &cancel, &cntr);
                if (IS_ERR(vma)) {
                        err = PTR_ERR(vma);
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        break;
                }
 
@@ -732,7 +725,7 @@ err_vma:
                i915_vma_unpin(vma);
                i915_vma_put(vma);
 
-               engine_heartbeat_enable(engine, saved_heartbeat);
+               engine_heartbeat_enable(engine);
                if (igt_flush_test(gt->i915))
                        err = -EIO;
                if (err)
@@ -778,7 +771,6 @@ int live_rps_frequency_srm(void *arg)
        rps->work.func = dummy_rps_work;
 
        for_each_engine(engine, gt, id) {
-               unsigned long saved_heartbeat;
                struct i915_request *rq;
                struct i915_vma *vma;
                u32 *cancel, *cntr;
@@ -787,14 +779,14 @@ int live_rps_frequency_srm(void *arg)
                        int freq;
                } min, max;
 
-               saved_heartbeat = engine_heartbeat_disable(engine);
+               engine_heartbeat_disable(engine);
 
                vma = create_spin_counter(engine,
                                          engine->kernel_context->vm, true,
                                          &cancel, &cntr);
                if (IS_ERR(vma)) {
                        err = PTR_ERR(vma);
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        break;
                }
 
@@ -874,7 +866,7 @@ err_vma:
                i915_vma_unpin(vma);
                i915_vma_put(vma);
 
-               engine_heartbeat_enable(engine, saved_heartbeat);
+               engine_heartbeat_enable(engine);
                if (igt_flush_test(gt->i915))
                        err = -EIO;
                if (err)
@@ -1066,16 +1058,14 @@ int live_rps_interrupt(void *arg)
        for_each_engine(engine, gt, id) {
                /* Keep the engine busy with a spinner; expect an UP! */
                if (pm_events & GEN6_PM_RP_UP_THRESHOLD) {
-                       unsigned long saved_heartbeat;
-
                        intel_gt_pm_wait_for_idle(engine->gt);
                        GEM_BUG_ON(intel_rps_is_active(rps));
 
-                       saved_heartbeat = engine_heartbeat_disable(engine);
+                       engine_heartbeat_disable(engine);
 
                        err = __rps_up_interrupt(rps, engine, &spin);
 
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        if (err)
                                goto out;
 
@@ -1084,15 +1074,13 @@ int live_rps_interrupt(void *arg)
 
                /* Keep the engine awake but idle and check for DOWN */
                if (pm_events & GEN6_PM_RP_DOWN_THRESHOLD) {
-                       unsigned long saved_heartbeat;
-
-                       saved_heartbeat = engine_heartbeat_disable(engine);
+                       engine_heartbeat_disable(engine);
                        intel_rc6_disable(&gt->rc6);
 
                        err = __rps_down_interrupt(rps, engine);
 
                        intel_rc6_enable(&gt->rc6);
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        if (err)
                                goto out;
                }
@@ -1168,7 +1156,6 @@ int live_rps_power(void *arg)
        rps->work.func = dummy_rps_work;
 
        for_each_engine(engine, gt, id) {
-               unsigned long saved_heartbeat;
                struct i915_request *rq;
                struct {
                        u64 power;
@@ -1178,13 +1165,13 @@ int live_rps_power(void *arg)
                if (!intel_engine_can_store_dword(engine))
                        continue;
 
-               saved_heartbeat = engine_heartbeat_disable(engine);
+               engine_heartbeat_disable(engine);
 
                rq = igt_spinner_create_request(&spin,
                                                engine->kernel_context,
                                                MI_NOOP);
                if (IS_ERR(rq)) {
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        err = PTR_ERR(rq);
                        break;
                }
@@ -1195,7 +1182,7 @@ int live_rps_power(void *arg)
                        pr_err("%s: RPS spinner did not start\n",
                               engine->name);
                        igt_spinner_end(&spin);
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        intel_gt_set_wedged(engine->gt);
                        err = -EIO;
                        break;
@@ -1208,7 +1195,7 @@ int live_rps_power(void *arg)
                min.power = measure_power_at(rps, &min.freq);
 
                igt_spinner_end(&spin);
-               engine_heartbeat_enable(engine, saved_heartbeat);
+               engine_heartbeat_enable(engine);
 
                pr_info("%s: min:%llumW @ %uMHz, max:%llumW @ %uMHz\n",
                        engine->name,
index c2578a0..ef1c350 100644 (file)
@@ -751,22 +751,20 @@ out_free:
        return err;
 }
 
-static void engine_heartbeat_disable(struct intel_engine_cs *engine,
-                                    unsigned long *saved)
+static void engine_heartbeat_disable(struct intel_engine_cs *engine)
 {
-       *saved = engine->props.heartbeat_interval_ms;
        engine->props.heartbeat_interval_ms = 0;
 
        intel_engine_pm_get(engine);
        intel_engine_park_heartbeat(engine);
 }
 
-static void engine_heartbeat_enable(struct intel_engine_cs *engine,
-                                   unsigned long saved)
+static void engine_heartbeat_enable(struct intel_engine_cs *engine)
 {
        intel_engine_pm_put(engine);
 
-       engine->props.heartbeat_interval_ms = saved;
+       engine->props.heartbeat_interval_ms =
+               engine->defaults.heartbeat_interval_ms;
 }
 
 static int live_hwsp_rollover_kernel(void *arg)
@@ -785,10 +783,9 @@ static int live_hwsp_rollover_kernel(void *arg)
                struct intel_context *ce = engine->kernel_context;
                struct intel_timeline *tl = ce->timeline;
                struct i915_request *rq[3] = {};
-               unsigned long heartbeat;
                int i;
 
-               engine_heartbeat_disable(engine, &heartbeat);
+               engine_heartbeat_disable(engine);
                if (intel_gt_wait_for_idle(gt, HZ / 2)) {
                        err = -EIO;
                        goto out;
@@ -839,7 +836,7 @@ static int live_hwsp_rollover_kernel(void *arg)
 out:
                for (i = 0; i < ARRAY_SIZE(rq); i++)
                        i915_request_put(rq[i]);
-               engine_heartbeat_enable(engine, heartbeat);
+               engine_heartbeat_enable(engine);
                if (err)
                        break;
        }
index 5ed3232..3278546 100644 (file)
@@ -623,6 +623,8 @@ err_request:
                                err = -EINVAL;
                                goto out_unpin;
                        }
+               } else {
+                       rsvd = 0;
                }
 
                expect = results[0];
diff --git a/drivers/gpu/drm/i915/gt/shaders/README b/drivers/gpu/drm/i915/gt/shaders/README
new file mode 100644 (file)
index 0000000..e7e96d7
--- /dev/null
@@ -0,0 +1,46 @@
+ASM sources for auto generated shaders
+======================================
+
+The i915/gt/hsw_clear_kernel.c and i915/gt/ivb_clear_kernel.c files contain
+pre-compiled batch chunks that will clear any residual render cache during
+context switch.
+
+They are generated from their respective platform ASM files present on
+i915/gt/shaders/clear_kernel directory.
+
+The generated .c files should never be modified directly. Instead, any modification
+needs to be done on the on their respective ASM files and build instructions below
+needes to be followed.
+
+Building
+========
+
+Environment
+-----------
+
+IGT GPU tool scripts and the Mesa's i965 instruction assembler tool are used
+on building.
+
+Please make sure your Mesa tool is compiled with "-Dtools=intel" and
+"-Ddri-drivers=i965", and run this script from IGT source root directory"
+
+The instructions bellow assume:
+    *  IGT gpu tools source code is located on your home directory (~) as ~/igt
+    *  Mesa source code is located on your home directory (~) as ~/mesa
+       and built under the ~/mesa/build directory
+    *  Linux kernel source code is under your home directory (~) as ~/linux
+
+Instructions
+------------
+
+~ $ cp ~/linux/drivers/gpu/drm/i915/gt/shaders/clear_kernel/ivb.asm \
+       ~/igt/lib/i915/shaders/clear_kernel/ivb.asm
+~ $ cd ~/igt
+igt $ ./scripts/generate_clear_kernel.sh -g ivb \
+      -m ~/mesa/build/src/intel/tools/i965_asm
+
+~ $ cp ~/linux/drivers/gpu/drm/i915/gt/shaders/clear_kernel/hsw.asm \
+    ~/igt/lib/i915/shaders/clear_kernel/hsw.asm
+~ $ cd ~/igt
+igt $ ./scripts/generate_clear_kernel.sh -g hsw \
+      -m ~/mesa/build/src/intel/tools/i965_asm
\ No newline at end of file
diff --git a/drivers/gpu/drm/i915/gt/shaders/clear_kernel/hsw.asm b/drivers/gpu/drm/i915/gt/shaders/clear_kernel/hsw.asm
new file mode 100644 (file)
index 0000000..5fdf384
--- /dev/null
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright Â© 2020 Intel Corporation
+ */
+
+/*
+ * Kernel for PAVP buffer clear.
+ *
+ *     1. Clear all 64 GRF registers assigned to the kernel with designated value;
+ *     2. Write 32x16 block of all "0" to render target buffer which indirectly clears
+ *        512 bytes of Render Cache.
+ */
+
+/* Store designated "clear GRF" value */
+mov(1)          f0.1<1>UW       g1.2<0,1,0>UW                   { align1 1N };
+
+/**
+ * Curbe Format
+ *
+ * DW 1.0 - Block Offset to write Render Cache
+ * DW 1.1 [15:0] - Clear Word
+ * DW 1.2 - Delay iterations
+ * DW 1.3 - Enable Instrumentation (only for debug)
+ * DW 1.4 - Rsvd (intended for context ID)
+ * DW 1.5 - [31:16]:SliceCount, [15:0]:SubSlicePerSliceCount
+ * DW 1.6 - Rsvd MBZ (intended for Enable Wait on Total Thread Count)
+ * DW 1.7 - Rsvd MBZ (inteded for Total Thread Count)
+ *
+ * Binding Table
+ *
+ * BTI 0: 2D Surface to help clear L3 (Render/Data Cache)
+ * BTI 1: Wait/Instrumentation Buffer
+ *  Size : (SliceCount * SubSliceCount  * 16 EUs/SubSlice) rows * (16 threads/EU) cols (Format R32_UINT)
+ *         Expected to be initialized to 0 by driver/another kernel
+ *  Layout:
+ *          RowN: Histogram for EU-N: (SliceID*SubSlicePerSliceCount + SSID)*16 + EUID [assume max 16 EUs / SS]
+ *          Col-k[DW-k]: Threads Executed on ThreadID-k for EU-N
+ */
+add(1)          g1.2<1>UD       g1.2<0,1,0>UD   0x00000001UD    { align1 1N }; /* Loop count to delay kernel: Init to (g1.2 + 1) */
+cmp.z.f0.0(1)   null<1>UD       g1.3<0,1,0>UD   0x00000000UD    { align1 1N };
+(+f0.0) jmpi(1) 352D                                            { align1 WE_all 1N };
+
+/**
+ * State Register has info on where this thread is running
+ *     IVB: sr0.0 :: [15:13]: MBZ, 12: HSID (Half-Slice ID), [11:8]EUID, [2:0] ThreadSlotID
+ *     HSW: sr0.0 :: 15: MBZ, [14:13]: SliceID, 12: HSID (Half-Slice ID), [11:8]EUID, [2:0] ThreadSlotID
+ */
+mov(8)          g3<1>UD         0x00000000UD                    { align1 1Q };
+shr(1)          g3<1>D          sr0<0,1,0>D     12D             { align1 1N };
+and(1)          g3<1>D          g3<0,1,0>D      1D              { align1 1N }; /* g3 has HSID */
+shr(1)          g3.1<1>D        sr0<0,1,0>D     13D             { align1 1N };
+and(1)          g3.1<1>D        g3.1<0,1,0>D    3D              { align1 1N }; /* g3.1 has sliceID */
+mul(1)          g3.5<1>D        g3.1<0,1,0>D    g1.10<0,1,0>UW  { align1 1N };
+add(1)          g3<1>D          g3<0,1,0>D      g3.5<0,1,0>D    { align1 1N }; /* g3 = sliceID * SubSlicePerSliceCount + HSID */
+shr(1)          g3.2<1>D        sr0<0,1,0>D     8D              { align1 1N };
+and(1)          g3.2<1>D        g3.2<0,1,0>D    15D             { align1 1N }; /* g3.2 = EUID */
+mul(1)          g3.4<1>D        g3<0,1,0>D      16D             { align1 1N };
+add(1)          g3.2<1>D        g3.2<0,1,0>D    g3.4<0,1,0>D    { align1 1N }; /* g3.2 now points to EU row number (Y-pixel = V address )  in instrumentation surf */
+
+mov(8)          g5<1>UD         0x00000000UD                    { align1 1Q };
+and(1)          g3.3<1>D        sr0<0,1,0>D     7D              { align1 1N };
+mul(1)          g3.3<1>D        g3.3<0,1,0>D    4D              { align1 1N };
+
+mov(8)          g4<1>UD         g0<8,8,1>UD                     { align1 1Q }; /* Initialize message header with g0 */
+mov(1)          g4<1>UD         g3.3<0,1,0>UD                   { align1 1N }; /* Block offset */
+mov(1)          g4.1<1>UD       g3.2<0,1,0>UD                   { align1 1N }; /* Block offset */
+mov(1)          g4.2<1>UD       0x00000003UD                    { align1 1N }; /* Block size (1 row x 4 bytes) */
+and(1)          g4.3<1>UD       g4.3<0,1,0>UW   0xffffffffUD    { align1 1N };
+
+/* Media block read to fetch current value at specified location in instrumentation buffer */
+sendc(8)        g5<1>UD         g4<8,8,1>F      0x02190001
+
+                            render MsgDesc: media block read MsgCtrl = 0x0 Surface = 1 mlen 1 rlen 1 { align1 1Q };
+add(1)          g5<1>D          g5<0,1,0>D      1D              { align1 1N };
+
+/* Media block write for updated value at specified location in instrumentation buffer */
+sendc(8)        g5<1>UD         g4<8,8,1>F      0x040a8001
+                            render MsgDesc: media block write MsgCtrl = 0x0 Surface = 1 mlen 2 rlen 0 { align1 1Q };
+
+/* Delay thread for specified parameter */
+add.nz.f0.0(1)  g1.2<1>UD       g1.2<0,1,0>UD   -1D             { align1 1N };
+(+f0.0) jmpi(1) -32D                                            { align1 WE_all 1N };
+
+/* Store designated "clear GRF" value */
+mov(1)          f0.1<1>UW       g1.2<0,1,0>UW                   { align1 1N };
+
+/* Initialize looping parameters */
+mov(1)          a0<1>D          0D                              { align1 1N }; /* Initialize a0.0:w=0 */
+mov(1)          a0.4<1>W        127W                            { align1 1N }; /* Loop count. Each loop contains 16 GRF's */
+
+/* Write 32x16 all "0" block */
+mov(8)          g2<1>UD         g0<8,8,1>UD                     { align1 1Q };
+mov(8)          g127<1>UD       g0<8,8,1>UD                     { align1 1Q };
+mov(2)          g2<1>UD         g1<2,2,1>UW                     { align1 1N };
+mov(1)          g2.2<1>UD       0x000f000fUD                    { align1 1N }; /* Block size (16x16) */
+and(1)          g2.3<1>UD       g2.3<0,1,0>UW   0xffffffefUD    { align1 1N };
+mov(16)         g3<1>UD         0x00000000UD                    { align1 1H };
+mov(16)         g4<1>UD         0x00000000UD                    { align1 1H };
+mov(16)         g5<1>UD         0x00000000UD                    { align1 1H };
+mov(16)         g6<1>UD         0x00000000UD                    { align1 1H };
+mov(16)         g7<1>UD         0x00000000UD                    { align1 1H };
+mov(16)         g8<1>UD         0x00000000UD                    { align1 1H };
+mov(16)         g9<1>UD         0x00000000UD                    { align1 1H };
+mov(16)         g10<1>UD        0x00000000UD                    { align1 1H };
+sendc(8)        null<1>UD       g2<8,8,1>F      0x120a8000
+                            render MsgDesc: media block write MsgCtrl = 0x0 Surface = 0 mlen 9 rlen 0 { align1 1Q };
+add(1)          g2<1>UD         g1<0,1,0>UW     0x0010UW        { align1 1N };
+sendc(8)        null<1>UD       g2<8,8,1>F      0x120a8000
+                            render MsgDesc: media block write MsgCtrl = 0x0 Surface = 0 mlen 9 rlen 0 { align1 1Q };
+
+/* Now, clear all GRF registers */
+add.nz.f0.0(1)  a0.4<1>W        a0.4<0,1,0>W    -1W             { align1 1N };
+mov(16)         g[a0]<1>UW      f0.1<0,1,0>UW                   { align1 1H };
+add(1)          a0<1>D          a0<0,1,0>D      32D             { align1 1N };
+(+f0.0) jmpi(1) -64D                                            { align1 WE_all 1N };
+
+/* Terminante the thread */
+sendc(8)        null<1>UD       g127<8,8,1>F    0x82000010
+                            thread_spawner MsgDesc: mlen 1 rlen 0           { align1 1Q EOT };
diff --git a/drivers/gpu/drm/i915/gt/shaders/clear_kernel/ivb.asm b/drivers/gpu/drm/i915/gt/shaders/clear_kernel/ivb.asm
new file mode 100644 (file)
index 0000000..97c7ac9
--- /dev/null
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright Â© 2020 Intel Corporation
+ */
+
+/*
+ * Kernel for PAVP buffer clear.
+ *
+ *     1. Clear all 64 GRF registers assigned to the kernel with designated value;
+ *     2. Write 32x16 block of all "0" to render target buffer which indirectly clears
+ *        512 bytes of Render Cache.
+ */
+
+/* Store designated "clear GRF" value */
+mov(1)          f0.1<1>UW       g1.2<0,1,0>UW                   { align1 1N };
+
+/**
+ * Curbe Format
+ *
+ * DW 1.0 - Block Offset to write Render Cache
+ * DW 1.1 [15:0] - Clear Word
+ * DW 1.2 - Delay iterations
+ * DW 1.3 - Enable Instrumentation (only for debug)
+ * DW 1.4 - Rsvd (intended for context ID)
+ * DW 1.5 - [31:16]:SliceCount, [15:0]:SubSlicePerSliceCount
+ * DW 1.6 - Rsvd MBZ (intended for Enable Wait on Total Thread Count)
+ * DW 1.7 - Rsvd MBZ (inteded for Total Thread Count)
+ *
+ * Binding Table
+ *
+ * BTI 0: 2D Surface to help clear L3 (Render/Data Cache)
+ * BTI 1: Wait/Instrumentation Buffer
+ *  Size : (SliceCount * SubSliceCount  * 16 EUs/SubSlice) rows * (16 threads/EU) cols (Format R32_UINT)
+ *         Expected to be initialized to 0 by driver/another kernel
+ *  Layout :
+ *           RowN: Histogram for EU-N: (SliceID*SubSlicePerSliceCount + SSID)*16 + EUID [assume max 16 EUs / SS]
+ *           Col-k[DW-k]: Threads Executed on ThreadID-k for EU-N
+ */
+add(1)          g1.2<1>UD       g1.2<0,1,0>UD   0x00000001UD    { align1 1N }; /* Loop count to delay kernel: Init to (g1.2 + 1) */
+cmp.z.f0.0(1)   null<1>UD       g1.3<0,1,0>UD   0x00000000UD    { align1 1N };
+(+f0.0) jmpi(1) 44D                                             { align1 WE_all 1N };
+
+/**
+ * State Register has info on where this thread is running
+ *     IVB: sr0.0 :: [15:13]: MBZ, 12: HSID (Half-Slice ID), [11:8]EUID, [2:0] ThreadSlotID
+ *     HSW: sr0.0 :: 15: MBZ, [14:13]: SliceID, 12: HSID (Half-Slice ID), [11:8]EUID, [2:0] ThreadSlotID
+ */
+mov(8)          g3<1>UD         0x00000000UD                    { align1 1Q };
+shr(1)          g3<1>D          sr0<0,1,0>D     12D             { align1 1N };
+and(1)          g3<1>D          g3<0,1,0>D      1D              { align1 1N }; /* g3 has HSID */
+shr(1)          g3.1<1>D        sr0<0,1,0>D     13D             { align1 1N };
+and(1)          g3.1<1>D        g3.1<0,1,0>D    3D              { align1 1N }; /* g3.1 has sliceID */
+mul(1)          g3.5<1>D        g3.1<0,1,0>D    g1.10<0,1,0>UW  { align1 1N };
+add(1)          g3<1>D          g3<0,1,0>D      g3.5<0,1,0>D    { align1 1N }; /* g3 = sliceID * SubSlicePerSliceCount + HSID */
+shr(1)          g3.2<1>D        sr0<0,1,0>D     8D              { align1 1N };
+and(1)          g3.2<1>D        g3.2<0,1,0>D    15D             { align1 1N }; /* g3.2 = EUID */
+mul(1)          g3.4<1>D        g3<0,1,0>D      16D             { align1 1N };
+add(1)          g3.2<1>D        g3.2<0,1,0>D    g3.4<0,1,0>D    { align1 1N }; /* g3.2 now points to EU row number (Y-pixel = V address )  in instrumentation surf */
+
+mov(8)          g5<1>UD         0x00000000UD                    { align1 1Q };
+and(1)          g3.3<1>D        sr0<0,1,0>D     7D              { align1 1N };
+mul(1)          g3.3<1>D        g3.3<0,1,0>D    4D              { align1 1N };
+
+mov(8)          g4<1>UD         g0<8,8,1>UD                     { align1 1Q }; /* Initialize message header with g0 */
+mov(1)          g4<1>UD         g3.3<0,1,0>UD                   { align1 1N }; /* Block offset */
+mov(1)          g4.1<1>UD       g3.2<0,1,0>UD                   { align1 1N }; /* Block offset */
+mov(1)          g4.2<1>UD       0x00000003UD                    { align1 1N }; /* Block size (1 row x 4 bytes) */
+and(1)          g4.3<1>UD       g4.3<0,1,0>UW   0xffffffffUD    { align1 1N };
+
+/* Media block read to fetch current value at specified location in instrumentation buffer */
+sendc(8)        g5<1>UD         g4<8,8,1>F      0x02190001
+                            render MsgDesc: media block read MsgCtrl = 0x0 Surface = 1 mlen 1 rlen 1 { align1 1Q };
+add(1)          g5<1>D          g5<0,1,0>D      1D              { align1 1N };
+
+/* Media block write for updated value at specified location in instrumentation buffer */
+sendc(8)        g5<1>UD         g4<8,8,1>F      0x040a8001
+                            render MsgDesc: media block write MsgCtrl = 0x0 Surface = 1 mlen 2 rlen 0 { align1 1Q };
+/* Delay thread for specified parameter */
+add.nz.f0.0(1)  g1.2<1>UD       g1.2<0,1,0>UD   -1D             { align1 1N };
+(+f0.0) jmpi(1) -4D                                             { align1 WE_all 1N };
+
+/* Store designated "clear GRF" value */
+mov(1)          f0.1<1>UW       g1.2<0,1,0>UW                   { align1 1N };
+
+/* Initialize looping parameters */
+mov(1)          a0<1>D          0D                              { align1 1N }; /* Initialize a0.0:w=0 */
+mov(1)          a0.4<1>W        127W                            { align1 1N }; /* Loop count. Each loop contains 16 GRF's */
+
+/* Write 32x16 all "0" block */
+mov(8)          g2<1>UD         g0<8,8,1>UD                     { align1 1Q };
+mov(8)          g127<1>UD       g0<8,8,1>UD                     { align1 1Q };
+mov(2)          g2<1>UD         g1<2,2,1>UW                     { align1 1N };
+mov(1)          g2.2<1>UD       0x000f000fUD                    { align1 1N }; /* Block size (16x16) */
+and(1)          g2.3<1>UD       g2.3<0,1,0>UW   0xffffffefUD    { align1 1N };
+mov(16)         g3<1>UD         0x00000000UD                    { align1 1H };
+mov(16)         g4<1>UD         0x00000000UD                    { align1 1H };
+mov(16)         g5<1>UD         0x00000000UD                    { align1 1H };
+mov(16)         g6<1>UD         0x00000000UD                    { align1 1H };
+mov(16)         g7<1>UD         0x00000000UD                    { align1 1H };
+mov(16)         g8<1>UD         0x00000000UD                    { align1 1H };
+mov(16)         g9<1>UD         0x00000000UD                    { align1 1H };
+mov(16)         g10<1>UD        0x00000000UD                    { align1 1H };
+sendc(8)        null<1>UD       g2<8,8,1>F      0x120a8000
+                            render MsgDesc: media block write MsgCtrl = 0x0 Surface = 0 mlen 9 rlen 0 { align1 1Q };
+add(1)          g2<1>UD         g1<0,1,0>UW     0x0010UW        { align1 1N };
+sendc(8)        null<1>UD       g2<8,8,1>F      0x120a8000
+                            render MsgDesc: media block write MsgCtrl = 0x0 Surface = 0 mlen 9 rlen 0 { align1 1Q };
+
+/* Now, clear all GRF registers */
+add.nz.f0.0(1)  a0.4<1>W        a0.4<0,1,0>W    -1W             { align1 1N };
+mov(16)         g[a0]<1>UW      f0.1<0,1,0>UW                   { align1 1H };
+add(1)          a0<1>D          a0<0,1,0>D      32D             { align1 1N };
+(+f0.0) jmpi(1) -8D                                             { align1 WE_all 1N };
+
+/* Terminante the thread */
+sendc(8)        null<1>UD       g127<8,8,1>F    0x82000010
+                            thread_spawner MsgDesc: mlen 1 rlen 0           { align1 1Q EOT };
index ec47d41..62e6a14 100644 (file)
@@ -66,7 +66,7 @@ static inline int mmio_diff_handler(struct intel_gvt *gvt,
        vreg = vgpu_vreg(param->vgpu, offset);
 
        if (preg != vreg) {
-               node = kmalloc(sizeof(*node), GFP_KERNEL);
+               node = kmalloc(sizeof(*node), GFP_ATOMIC);
                if (!node)
                        return -ENOMEM;
 
index 3e88e3b..fadd2ad 100644 (file)
@@ -1726,13 +1726,13 @@ static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
                (*(u32 *)p_data) &= ~_MASKED_BIT_ENABLE(2);
        write_vreg(vgpu, offset, p_data, bytes);
 
-       if (data & _MASKED_BIT_ENABLE(1)) {
+       if (IS_MASKED_BITS_ENABLED(data, 1)) {
                enter_failsafe_mode(vgpu, GVT_FAILSAFE_UNSUPPORTED_GUEST);
                return 0;
        }
 
        if (IS_COFFEELAKE(vgpu->gvt->gt->i915) &&
-           data & _MASKED_BIT_ENABLE(2)) {
+           IS_MASKED_BITS_ENABLED(data, 2)) {
                enter_failsafe_mode(vgpu, GVT_FAILSAFE_UNSUPPORTED_GUEST);
                return 0;
        }
@@ -1741,14 +1741,14 @@ static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
         * pvinfo, if not, we will treat this guest as non-gvtg-aware
         * guest, and stop emulating its cfg space, mmio, gtt, etc.
         */
-       if (((data & _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)) ||
-                       (data & _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE)))
-                       && !vgpu->pv_notified) {
+       if ((IS_MASKED_BITS_ENABLED(data, GFX_PPGTT_ENABLE) ||
+           IS_MASKED_BITS_ENABLED(data, GFX_RUN_LIST_ENABLE)) &&
+           !vgpu->pv_notified) {
                enter_failsafe_mode(vgpu, GVT_FAILSAFE_UNSUPPORTED_GUEST);
                return 0;
        }
-       if ((data & _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE))
-                       || (data & _MASKED_BIT_DISABLE(GFX_RUN_LIST_ENABLE))) {
+       if (IS_MASKED_BITS_ENABLED(data, GFX_RUN_LIST_ENABLE) ||
+           IS_MASKED_BITS_DISABLED(data, GFX_RUN_LIST_ENABLE)) {
                enable_execlist = !!(data & GFX_RUN_LIST_ENABLE);
 
                gvt_dbg_core("EXECLIST %s on ring %s\n",
@@ -1809,7 +1809,7 @@ static int ring_reset_ctl_write(struct intel_vgpu *vgpu,
        write_vreg(vgpu, offset, p_data, bytes);
        data = vgpu_vreg(vgpu, offset);
 
-       if (data & _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET))
+       if (IS_MASKED_BITS_ENABLED(data, RESET_CTL_REQUEST_RESET))
                data |= RESET_CTL_READY_TO_RESET;
        else if (data & _MASKED_BIT_DISABLE(RESET_CTL_REQUEST_RESET))
                data &= ~RESET_CTL_READY_TO_RESET;
@@ -1827,7 +1827,8 @@ static int csfe_chicken1_mmio_write(struct intel_vgpu *vgpu,
        (*(u32 *)p_data) &= ~_MASKED_BIT_ENABLE(0x18);
        write_vreg(vgpu, offset, p_data, bytes);
 
-       if (data & _MASKED_BIT_ENABLE(0x10) || data & _MASKED_BIT_ENABLE(0x8))
+       if (IS_MASKED_BITS_ENABLED(data, 0x10) ||
+           IS_MASKED_BITS_ENABLED(data, 0x8))
                enter_failsafe_mode(vgpu, GVT_FAILSAFE_UNSUPPORTED_GUEST);
 
        return 0;
@@ -3055,6 +3056,7 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)
        MMIO_D(_MMIO(0x72380), D_SKL_PLUS);
        MMIO_D(_MMIO(0x7239c), D_SKL_PLUS);
        MMIO_D(_MMIO(_PLANE_SURF_3_A), D_SKL_PLUS);
+       MMIO_D(_MMIO(_PLANE_SURF_3_B), D_SKL_PLUS);
 
        MMIO_D(CSR_SSP_BASE, D_SKL_PLUS);
        MMIO_D(CSR_HTP_SKL, D_SKL_PLUS);
@@ -3131,8 +3133,8 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)
        MMIO_DFH(GEN9_WM_CHICKEN3, D_SKL_PLUS, F_MODE_MASK | F_CMD_ACCESS,
                 NULL, NULL);
 
-       MMIO_D(GAMT_CHKN_BIT_REG, D_KBL);
-       MMIO_D(GEN9_CTX_PREEMPT_REG, D_KBL | D_SKL);
+       MMIO_D(GAMT_CHKN_BIT_REG, D_KBL | D_CFL);
+       MMIO_D(GEN9_CTX_PREEMPT_REG, D_SKL_PLUS);
 
        return 0;
 }
index 970704b..3b25e7f 100644 (file)
@@ -54,8 +54,8 @@ bool is_inhibit_context(struct intel_context *ce);
 
 int intel_vgpu_restore_inhibit_context(struct intel_vgpu *vgpu,
                                       struct i915_request *req);
-#define IS_RESTORE_INHIBIT(a)  \
-       (_MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT) == \
-       ((a) & _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT)))
+
+#define IS_RESTORE_INHIBIT(a) \
+       IS_MASKED_BITS_ENABLED(a, CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT)
 
 #endif
index 5b66e14..b88e033 100644 (file)
 #define GFX_MODE_BIT_SET_IN_MASK(val, bit) \
                ((((bit) & 0xffff0000) == 0) && !!((val) & (((bit) << 16))))
 
+#define IS_MASKED_BITS_ENABLED(_val, _b) \
+               (((_val) & _MASKED_BIT_ENABLE(_b)) == _MASKED_BIT_ENABLE(_b))
+#define IS_MASKED_BITS_DISABLED(_val, _b) \
+               ((_val) & _MASKED_BIT_DISABLE(_b))
+
 #define FORCEWAKE_RENDER_GEN9_REG 0xa278
 #define FORCEWAKE_ACK_RENDER_GEN9_REG 0x0D84
 #define FORCEWAKE_BLITTER_GEN9_REG 0xa188
index bca036a..e7532e7 100644 (file)
@@ -230,7 +230,7 @@ static int per_file_stats(int id, void *ptr, void *data)
        struct file_stats *stats = data;
        struct i915_vma *vma;
 
-       if (!kref_get_unless_zero(&obj->base.refcount))
+       if (IS_ERR_OR_NULL(obj) || !kref_get_unless_zero(&obj->base.refcount))
                return 0;
 
        stats->count++;
index adb9bf3..ae99a91 100644 (file)
@@ -410,8 +410,6 @@ struct intel_fbc {
                        int adjusted_x;
                        int adjusted_y;
 
-                       int y;
-
                        u16 pixel_blend_mode;
                } plane;
 
@@ -420,6 +418,8 @@ struct intel_fbc {
                        unsigned int stride;
                        u64 modifier;
                } fb;
+
+               unsigned int fence_y_offset;
                u16 gen9_wa_cfb_stride;
                s8 fence_id;
        } state_cache;
@@ -435,15 +435,16 @@ struct intel_fbc {
                struct {
                        enum pipe pipe;
                        enum i9xx_plane_id i9xx_plane;
-                       unsigned int fence_y_offset;
                } crtc;
 
                struct {
                        const struct drm_format_info *format;
                        unsigned int stride;
+                       u64 modifier;
                } fb;
 
                int cfb_size;
+               unsigned int fence_y_offset;
                u16 gen9_wa_cfb_stride;
                s8 fence_id;
                bool plane_visible;
index 4dc601d..284cf07 100644 (file)
@@ -3125,6 +3125,7 @@ static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv)
 
        val = I915_READ(GEN11_DE_HPD_IMR);
        val &= ~hotplug_irqs;
+       val |= ~enabled_irqs & hotplug_irqs;
        I915_WRITE(GEN11_DE_HPD_IMR, val);
        POSTING_READ(GEN11_DE_HPD_IMR);
 
index 25329b7..014f34c 100644 (file)
@@ -1592,6 +1592,7 @@ static u32 *save_restore_register(struct i915_perf_stream *stream, u32 *cs,
        u32 d;
 
        cmd = save ? MI_STORE_REGISTER_MEM : MI_LOAD_REGISTER_MEM;
+       cmd |= MI_SRM_LRM_GLOBAL_GTT;
        if (INTEL_GEN(stream->perf->i915) >= 8)
                cmd++;
 
index e991a70..962ded9 100644 (file)
@@ -269,12 +269,48 @@ static bool exclusive_mmio_access(const struct drm_i915_private *i915)
        return IS_GEN(i915, 7);
 }
 
+static void engine_sample(struct intel_engine_cs *engine, unsigned int period_ns)
+{
+       struct intel_engine_pmu *pmu = &engine->pmu;
+       bool busy;
+       u32 val;
+
+       val = ENGINE_READ_FW(engine, RING_CTL);
+       if (val == 0) /* powerwell off => engine idle */
+               return;
+
+       if (val & RING_WAIT)
+               add_sample(&pmu->sample[I915_SAMPLE_WAIT], period_ns);
+       if (val & RING_WAIT_SEMAPHORE)
+               add_sample(&pmu->sample[I915_SAMPLE_SEMA], period_ns);
+
+       /* No need to sample when busy stats are supported. */
+       if (intel_engine_supports_stats(engine))
+               return;
+
+       /*
+        * While waiting on a semaphore or event, MI_MODE reports the
+        * ring as idle. However, previously using the seqno, and with
+        * execlists sampling, we account for the ring waiting as the
+        * engine being busy. Therefore, we record the sample as being
+        * busy if either waiting or !idle.
+        */
+       busy = val & (RING_WAIT_SEMAPHORE | RING_WAIT);
+       if (!busy) {
+               val = ENGINE_READ_FW(engine, RING_MI_MODE);
+               busy = !(val & MODE_IDLE);
+       }
+       if (busy)
+               add_sample(&pmu->sample[I915_SAMPLE_BUSY], period_ns);
+}
+
 static void
 engines_sample(struct intel_gt *gt, unsigned int period_ns)
 {
        struct drm_i915_private *i915 = gt->i915;
        struct intel_engine_cs *engine;
        enum intel_engine_id id;
+       unsigned long flags;
 
        if ((i915->pmu.enable & ENGINE_SAMPLE_MASK) == 0)
                return;
@@ -283,53 +319,17 @@ engines_sample(struct intel_gt *gt, unsigned int period_ns)
                return;
 
        for_each_engine(engine, gt, id) {
-               struct intel_engine_pmu *pmu = &engine->pmu;
-               spinlock_t *mmio_lock;
-               unsigned long flags;
-               bool busy;
-               u32 val;
-
                if (!intel_engine_pm_get_if_awake(engine))
                        continue;
 
-               mmio_lock = NULL;
-               if (exclusive_mmio_access(i915))
-                       mmio_lock = &engine->uncore->lock;
-
-               if (unlikely(mmio_lock))
-                       spin_lock_irqsave(mmio_lock, flags);
-
-               val = ENGINE_READ_FW(engine, RING_CTL);
-               if (val == 0) /* powerwell off => engine idle */
-                       goto skip;
-
-               if (val & RING_WAIT)
-                       add_sample(&pmu->sample[I915_SAMPLE_WAIT], period_ns);
-               if (val & RING_WAIT_SEMAPHORE)
-                       add_sample(&pmu->sample[I915_SAMPLE_SEMA], period_ns);
-
-               /* No need to sample when busy stats are supported. */
-               if (intel_engine_supports_stats(engine))
-                       goto skip;
-
-               /*
-                * While waiting on a semaphore or event, MI_MODE reports the
-                * ring as idle. However, previously using the seqno, and with
-                * execlists sampling, we account for the ring waiting as the
-                * engine being busy. Therefore, we record the sample as being
-                * busy if either waiting or !idle.
-                */
-               busy = val & (RING_WAIT_SEMAPHORE | RING_WAIT);
-               if (!busy) {
-                       val = ENGINE_READ_FW(engine, RING_MI_MODE);
-                       busy = !(val & MODE_IDLE);
+               if (exclusive_mmio_access(i915)) {
+                       spin_lock_irqsave(&engine->uncore->lock, flags);
+                       engine_sample(engine, period_ns);
+                       spin_unlock_irqrestore(&engine->uncore->lock, flags);
+               } else {
+                       engine_sample(engine, period_ns);
                }
-               if (busy)
-                       add_sample(&pmu->sample[I915_SAMPLE_BUSY], period_ns);
 
-skip:
-               if (unlikely(mmio_lock))
-                       spin_unlock_irqrestore(mmio_lock, flags);
                intel_engine_pm_put_async(engine);
        }
 }
index 5003a71..8aa7866 100644 (file)
@@ -42,7 +42,7 @@ enum {
  * active request.
  */
 #define I915_PRIORITY_UNPREEMPTABLE INT_MAX
-#define I915_PRIORITY_BARRIER INT_MAX
+#define I915_PRIORITY_BARRIER (I915_PRIORITY_UNPREEMPTABLE - 1)
 
 struct i915_priolist {
        struct list_head requests[I915_PRIORITY_COUNT];
index 7717581..06cd1d2 100644 (file)
@@ -7896,7 +7896,7 @@ enum {
 
 /* GEN7 chicken */
 #define GEN7_COMMON_SLICE_CHICKEN1             _MMIO(0x7010)
-  #define GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC    ((1 << 10) | (1 << 26))
+  #define GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC    (1 << 10)
   #define GEN9_RHWO_OPTIMIZATION_DISABLE       (1 << 14)
 
 #define COMMON_SLICE_CHICKEN2                                  _MMIO(0x7014)
index fc14ebf..1f9cd33 100644 (file)
@@ -104,6 +104,7 @@ vma_create(struct drm_i915_gem_object *obj,
           struct i915_address_space *vm,
           const struct i915_ggtt_view *view)
 {
+       struct i915_vma *pos = ERR_PTR(-E2BIG);
        struct i915_vma *vma;
        struct rb_node *rb, **p;
 
@@ -184,7 +185,6 @@ vma_create(struct drm_i915_gem_object *obj,
        rb = NULL;
        p = &obj->vma.tree.rb_node;
        while (*p) {
-               struct i915_vma *pos;
                long cmp;
 
                rb = *p;
@@ -196,16 +196,12 @@ vma_create(struct drm_i915_gem_object *obj,
                 * and dispose of ours.
                 */
                cmp = i915_vma_compare(pos, vm, view);
-               if (cmp == 0) {
-                       spin_unlock(&obj->vma.lock);
-                       i915_vma_free(vma);
-                       return pos;
-               }
-
                if (cmp < 0)
                        p = &rb->rb_right;
-               else
+               else if (cmp > 0)
                        p = &rb->rb_left;
+               else
+                       goto err_unlock;
        }
        rb_link_node(&vma->obj_node, rb, p);
        rb_insert_color(&vma->obj_node, &obj->vma.tree);
@@ -228,8 +224,9 @@ vma_create(struct drm_i915_gem_object *obj,
 err_unlock:
        spin_unlock(&obj->vma.lock);
 err_vma:
+       i915_vm_put(vm);
        i915_vma_free(vma);
-       return ERR_PTR(-E2BIG);
+       return pos;
 }
 
 static struct i915_vma *
index 696491d..07f663c 100644 (file)
@@ -6830,16 +6830,6 @@ static void ilk_init_clock_gating(struct drm_i915_private *dev_priv)
        I915_WRITE(ILK_DISPLAY_CHICKEN2,
                   I915_READ(ILK_DISPLAY_CHICKEN2) |
                   ILK_ELPIN_409_SELECT);
-       I915_WRITE(_3D_CHICKEN2,
-                  _3D_CHICKEN2_WM_READ_PIPELINED << 16 |
-                  _3D_CHICKEN2_WM_READ_PIPELINED);
-
-       /* WaDisableRenderCachePipelinedFlush:ilk */
-       I915_WRITE(CACHE_MODE_0,
-                  _MASKED_BIT_ENABLE(CM0_PIPELINED_RENDER_FLUSH_DISABLE));
-
-       /* WaDisable_RenderCache_OperationalFlush:ilk */
-       I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
 
        g4x_disable_trickle_feed(dev_priv);
 
@@ -6902,27 +6892,6 @@ static void gen6_init_clock_gating(struct drm_i915_private *dev_priv)
                   I915_READ(ILK_DISPLAY_CHICKEN2) |
                   ILK_ELPIN_409_SELECT);
 
-       /* WaDisableHiZPlanesWhenMSAAEnabled:snb */
-       I915_WRITE(_3D_CHICKEN,
-                  _MASKED_BIT_ENABLE(_3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB));
-
-       /* WaDisable_RenderCache_OperationalFlush:snb */
-       I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
-
-       /*
-        * BSpec recoomends 8x4 when MSAA is used,
-        * however in practice 16x4 seems fastest.
-        *
-        * Note that PS/WM thread counts depend on the WIZ hashing
-        * disable bit, which we don't touch here, but it's good
-        * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
-        */
-       I915_WRITE(GEN6_GT_MODE,
-                  _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4));
-
-       I915_WRITE(CACHE_MODE_0,
-                  _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB));
-
        I915_WRITE(GEN6_UCGCTL1,
                   I915_READ(GEN6_UCGCTL1) |
                   GEN6_BLBUNIT_CLOCK_GATE_DISABLE |
@@ -6945,18 +6914,6 @@ static void gen6_init_clock_gating(struct drm_i915_private *dev_priv)
                   GEN6_RCPBUNIT_CLOCK_GATE_DISABLE |
                   GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
 
-       /* WaStripsFansDisableFastClipPerformanceFix:snb */
-       I915_WRITE(_3D_CHICKEN3,
-                  _MASKED_BIT_ENABLE(_3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL));
-
-       /*
-        * Bspec says:
-        * "This bit must be set if 3DSTATE_CLIP clip mode is set to normal and
-        * 3DSTATE_SF number of SF output attributes is more than 16."
-        */
-       I915_WRITE(_3D_CHICKEN3,
-                  _MASKED_BIT_ENABLE(_3D_CHICKEN3_SF_DISABLE_PIPELINED_ATTR_FETCH));
-
        /*
         * According to the spec the following bits should be
         * set in order to enable memory self-refresh and fbc:
@@ -6986,24 +6943,6 @@ static void gen6_init_clock_gating(struct drm_i915_private *dev_priv)
        gen6_check_mch_setup(dev_priv);
 }
 
-static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv)
-{
-       u32 reg = I915_READ(GEN7_FF_THREAD_MODE);
-
-       /*
-        * WaVSThreadDispatchOverride:ivb,vlv
-        *
-        * This actually overrides the dispatch
-        * mode for all thread types.
-        */
-       reg &= ~GEN7_FF_SCHED_MASK;
-       reg |= GEN7_FF_TS_SCHED_HW;
-       reg |= GEN7_FF_VS_SCHED_HW;
-       reg |= GEN7_FF_DS_SCHED_HW;
-
-       I915_WRITE(GEN7_FF_THREAD_MODE, reg);
-}
-
 static void lpt_init_clock_gating(struct drm_i915_private *dev_priv)
 {
        /*
@@ -7230,45 +7169,10 @@ static void bdw_init_clock_gating(struct drm_i915_private *dev_priv)
 
 static void hsw_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-       /* L3 caching of data atomics doesn't work -- disable it. */
-       I915_WRITE(HSW_SCRATCH1, HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE);
-       I915_WRITE(HSW_ROW_CHICKEN3,
-                  _MASKED_BIT_ENABLE(HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE));
-
        /* This is required by WaCatErrorRejectionIssue:hsw */
        I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
-                       I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
-                       GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
-
-       /* WaVSRefCountFullforceMissDisable:hsw */
-       I915_WRITE(GEN7_FF_THREAD_MODE,
-                  I915_READ(GEN7_FF_THREAD_MODE) & ~GEN7_FF_VS_REF_CNT_FFME);
-
-       /* WaDisable_RenderCache_OperationalFlush:hsw */
-       I915_WRITE(CACHE_MODE_0_GEN7, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
-
-       /* enable HiZ Raw Stall Optimization */
-       I915_WRITE(CACHE_MODE_0_GEN7,
-                  _MASKED_BIT_DISABLE(HIZ_RAW_STALL_OPT_DISABLE));
-
-       /* WaDisable4x2SubspanOptimization:hsw */
-       I915_WRITE(CACHE_MODE_1,
-                  _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
-
-       /*
-        * BSpec recommends 8x4 when MSAA is used,
-        * however in practice 16x4 seems fastest.
-        *
-        * Note that PS/WM thread counts depend on the WIZ hashing
-        * disable bit, which we don't touch here, but it's good
-        * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
-        */
-       I915_WRITE(GEN7_GT_MODE,
-                  _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4));
-
-       /* WaSampleCChickenBitEnable:hsw */
-       I915_WRITE(HALF_SLICE_CHICKEN3,
-                  _MASKED_BIT_ENABLE(HSW_SAMPLE_C_PERFORMANCE));
+                  I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
+                  GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
 
        /* WaSwitchSolVfFArbitrationPriority:hsw */
        I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL);
@@ -7282,32 +7186,11 @@ static void ivb_init_clock_gating(struct drm_i915_private *dev_priv)
 
        I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE);
 
-       /* WaDisableEarlyCull:ivb */
-       I915_WRITE(_3D_CHICKEN3,
-                  _MASKED_BIT_ENABLE(_3D_CHICKEN_SF_DISABLE_OBJEND_CULL));
-
        /* WaDisableBackToBackFlipFix:ivb */
        I915_WRITE(IVB_CHICKEN3,
                   CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE |
                   CHICKEN3_DGMG_DONE_FIX_DISABLE);
 
-       /* WaDisablePSDDualDispatchEnable:ivb */
-       if (IS_IVB_GT1(dev_priv))
-               I915_WRITE(GEN7_HALF_SLICE_CHICKEN1,
-                          _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE));
-
-       /* WaDisable_RenderCache_OperationalFlush:ivb */
-       I915_WRITE(CACHE_MODE_0_GEN7, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
-
-       /* Apply the WaDisableRHWOOptimizationForRenderHang:ivb workaround. */
-       I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
-                  GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
-
-       /* WaApplyL3ControlAndL3ChickenMode:ivb */
-       I915_WRITE(GEN7_L3CNTLREG1,
-                       GEN7_WA_FOR_GEN7_L3_CONTROL);
-       I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER,
-                  GEN7_WA_L3_CHICKEN_MODE);
        if (IS_IVB_GT1(dev_priv))
                I915_WRITE(GEN7_ROW_CHICKEN2,
                           _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
@@ -7319,10 +7202,6 @@ static void ivb_init_clock_gating(struct drm_i915_private *dev_priv)
                           _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
        }
 
-       /* WaForceL3Serialization:ivb */
-       I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) &
-                  ~L3SQ_URB_READ_CAM_MATCH_DISABLE);
-
        /*
         * According to the spec, bit 13 (RCZUNIT) must be set on IVB.
         * This implements the WaDisableRCZUnitClockGating:ivb workaround.
@@ -7337,29 +7216,6 @@ static void ivb_init_clock_gating(struct drm_i915_private *dev_priv)
 
        g4x_disable_trickle_feed(dev_priv);
 
-       gen7_setup_fixed_func_scheduler(dev_priv);
-
-       if (0) { /* causes HiZ corruption on ivb:gt1 */
-               /* enable HiZ Raw Stall Optimization */
-               I915_WRITE(CACHE_MODE_0_GEN7,
-                          _MASKED_BIT_DISABLE(HIZ_RAW_STALL_OPT_DISABLE));
-       }
-
-       /* WaDisable4x2SubspanOptimization:ivb */
-       I915_WRITE(CACHE_MODE_1,
-                  _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
-
-       /*
-        * BSpec recommends 8x4 when MSAA is used,
-        * however in practice 16x4 seems fastest.
-        *
-        * Note that PS/WM thread counts depend on the WIZ hashing
-        * disable bit, which we don't touch here, but it's good
-        * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
-        */
-       I915_WRITE(GEN7_GT_MODE,
-                  _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4));
-
        snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
        snpcr &= ~GEN6_MBC_SNPCR_MASK;
        snpcr |= GEN6_MBC_SNPCR_MED;
@@ -7373,28 +7229,11 @@ static void ivb_init_clock_gating(struct drm_i915_private *dev_priv)
 
 static void vlv_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-       /* WaDisableEarlyCull:vlv */
-       I915_WRITE(_3D_CHICKEN3,
-                  _MASKED_BIT_ENABLE(_3D_CHICKEN_SF_DISABLE_OBJEND_CULL));
-
        /* WaDisableBackToBackFlipFix:vlv */
        I915_WRITE(IVB_CHICKEN3,
                   CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE |
                   CHICKEN3_DGMG_DONE_FIX_DISABLE);
 
-       /* WaPsdDispatchEnable:vlv */
-       /* WaDisablePSDDualDispatchEnable:vlv */
-       I915_WRITE(GEN7_HALF_SLICE_CHICKEN1,
-                  _MASKED_BIT_ENABLE(GEN7_MAX_PS_THREAD_DEP |
-                                     GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE));
-
-       /* WaDisable_RenderCache_OperationalFlush:vlv */
-       I915_WRITE(CACHE_MODE_0_GEN7, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
-
-       /* WaForceL3Serialization:vlv */
-       I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) &
-                  ~L3SQ_URB_READ_CAM_MATCH_DISABLE);
-
        /* WaDisableDopClockGating:vlv */
        I915_WRITE(GEN7_ROW_CHICKEN2,
                   _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
@@ -7404,8 +7243,6 @@ static void vlv_init_clock_gating(struct drm_i915_private *dev_priv)
                   I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
                   GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
 
-       gen7_setup_fixed_func_scheduler(dev_priv);
-
        /*
         * According to the spec, bit 13 (RCZUNIT) must be set on IVB.
         * This implements the WaDisableRCZUnitClockGating:vlv workaround.
@@ -7419,30 +7256,6 @@ static void vlv_init_clock_gating(struct drm_i915_private *dev_priv)
        I915_WRITE(GEN7_UCGCTL4,
                   I915_READ(GEN7_UCGCTL4) | GEN7_L3BANK2X_CLOCK_GATE_DISABLE);
 
-       /*
-        * BSpec says this must be set, even though
-        * WaDisable4x2SubspanOptimization isn't listed for VLV.
-        */
-       I915_WRITE(CACHE_MODE_1,
-                  _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
-
-       /*
-        * BSpec recommends 8x4 when MSAA is used,
-        * however in practice 16x4 seems fastest.
-        *
-        * Note that PS/WM thread counts depend on the WIZ hashing
-        * disable bit, which we don't touch here, but it's good
-        * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
-        */
-       I915_WRITE(GEN7_GT_MODE,
-                  _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4));
-
-       /*
-        * WaIncreaseL3CreditsForVLVB0:vlv
-        * This is the hardware default actually.
-        */
-       I915_WRITE(GEN7_L3SQCREG1, VLV_B0_WA_L3SQCREG1_VALUE);
-
        /*
         * WaDisableVLVClockGating_VBIIssue:vlv
         * Disable clock gating on th GCFG unit to prevent a delay
@@ -7495,13 +7308,6 @@ static void g4x_init_clock_gating(struct drm_i915_private *dev_priv)
                dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE;
        I915_WRITE(DSPCLK_GATE_D, dspclk_gate);
 
-       /* WaDisableRenderCachePipelinedFlush */
-       I915_WRITE(CACHE_MODE_0,
-                  _MASKED_BIT_ENABLE(CM0_PIPELINED_RENDER_FLUSH_DISABLE));
-
-       /* WaDisable_RenderCache_OperationalFlush:g4x */
-       I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
-
        g4x_disable_trickle_feed(dev_priv);
 }
 
@@ -7517,11 +7323,6 @@ static void i965gm_init_clock_gating(struct drm_i915_private *dev_priv)
        intel_uncore_write(uncore,
                           MI_ARB_STATE,
                           _MASKED_BIT_ENABLE(MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE));
-
-       /* WaDisable_RenderCache_OperationalFlush:gen4 */
-       intel_uncore_write(uncore,
-                          CACHE_MODE_0,
-                          _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
 }
 
 static void i965g_init_clock_gating(struct drm_i915_private *dev_priv)
@@ -7534,9 +7335,6 @@ static void i965g_init_clock_gating(struct drm_i915_private *dev_priv)
        I915_WRITE(RENCLK_GATE_D2, 0);
        I915_WRITE(MI_ARB_STATE,
                   _MASKED_BIT_ENABLE(MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE));
-
-       /* WaDisable_RenderCache_OperationalFlush:gen4 */
-       I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
 }
 
 static void gen3_init_clock_gating(struct drm_i915_private *dev_priv)
index 6a2be7d..6090ce3 100644 (file)
@@ -21,6 +21,7 @@ selftest(fence, i915_sw_fence_mock_selftests)
 selftest(scatterlist, scatterlist_mock_selftests)
 selftest(syncmap, i915_syncmap_mock_selftests)
 selftest(uncore, intel_uncore_mock_selftests)
+selftest(ring, intel_ring_mock_selftests)
 selftest(engine, intel_engine_cs_mock_selftests)
 selftest(timelines, intel_timeline_mock_selftests)
 selftest(requests, i915_request_mock_selftests)
index 33f0138..a5c95be 100644 (file)
@@ -271,6 +271,8 @@ void lima_pp_fini(struct lima_ip *ip)
 
 int lima_pp_bcast_resume(struct lima_ip *ip)
 {
+       /* PP has been reset by individual PP resume */
+       ip->data.async_reset = false;
        return 0;
 }
 
index 04e1d38..4d2290f 100644 (file)
@@ -812,7 +812,7 @@ static void mcde_display_enable(struct drm_simple_display_pipe *pipe,
        struct drm_crtc *crtc = &pipe->crtc;
        struct drm_plane *plane = &pipe->plane;
        struct drm_device *drm = crtc->dev;
-       struct mcde *mcde = drm->dev_private;
+       struct mcde *mcde = to_mcde(drm);
        const struct drm_display_mode *mode = &cstate->mode;
        struct drm_framebuffer *fb = plane->state->fb;
        u32 format = fb->format->format;
@@ -1060,9 +1060,14 @@ static void mcde_display_update(struct drm_simple_display_pipe *pipe,
         */
        if (fb) {
                mcde_set_extsrc(mcde, drm_fb_cma_get_gem_addr(fb, pstate, 0));
-               if (!mcde->video_mode)
-                       /* Send a single frame using software sync */
-                       mcde_display_send_one_frame(mcde);
+               if (!mcde->video_mode) {
+                       /*
+                        * Send a single frame using software sync if the flow
+                        * is not active yet.
+                        */
+                       if (mcde->flow_active == 0)
+                               mcde_display_send_one_frame(mcde);
+               }
                dev_info_once(mcde->dev, "sent first display update\n");
        } else {
                /*
index 84f3e2d..80082d6 100644 (file)
@@ -209,7 +209,6 @@ static int mcde_modeset_init(struct drm_device *drm)
 
        drm_mode_config_reset(drm);
        drm_kms_helper_poll_init(drm);
-       drm_fbdev_generic_setup(drm, 32);
 
        return 0;
 }
@@ -264,6 +263,8 @@ static int mcde_drm_bind(struct device *dev)
        if (ret < 0)
                goto unbind;
 
+       drm_fbdev_generic_setup(drm, 32);
+
        return 0;
 
 unbind:
index c420f5a..aa74aac 100644 (file)
@@ -6,12 +6,12 @@ config DRM_MEDIATEK
        depends on COMMON_CLK
        depends on HAVE_ARM_SMCCC
        depends on OF
+       depends on MTK_MMSYS
        select DRM_GEM_CMA_HELPER
        select DRM_KMS_HELPER
        select DRM_MIPI_DSI
        select DRM_PANEL
        select MEMORY
-       select MTK_MMSYS
        select MTK_SMI
        select VIDEOMODE_HELPERS
        help
index fe46c4b..7cd8f41 100644 (file)
@@ -193,7 +193,6 @@ static int mtk_crtc_ddp_clk_enable(struct mtk_drm_crtc *mtk_crtc)
        int ret;
        int i;
 
-       DRM_DEBUG_DRIVER("%s\n", __func__);
        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
                ret = clk_prepare_enable(mtk_crtc->ddp_comp[i]->clk);
                if (ret) {
@@ -213,7 +212,6 @@ static void mtk_crtc_ddp_clk_disable(struct mtk_drm_crtc *mtk_crtc)
 {
        int i;
 
-       DRM_DEBUG_DRIVER("%s\n", __func__);
        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
                clk_disable_unprepare(mtk_crtc->ddp_comp[i]->clk);
 }
@@ -258,7 +256,6 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
        int ret;
        int i;
 
-       DRM_DEBUG_DRIVER("%s\n", __func__);
        if (WARN_ON(!crtc->state))
                return -EINVAL;
 
@@ -299,7 +296,6 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
                goto err_mutex_unprepare;
        }
 
-       DRM_DEBUG_DRIVER("mediatek_ddp_ddp_path_setup\n");
        for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
                mtk_mmsys_ddp_connect(mtk_crtc->mmsys_dev,
                                      mtk_crtc->ddp_comp[i]->id,
@@ -349,7 +345,6 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc)
        struct drm_crtc *crtc = &mtk_crtc->base;
        int i;
 
-       DRM_DEBUG_DRIVER("%s\n", __func__);
        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
                mtk_ddp_comp_stop(mtk_crtc->ddp_comp[i]);
                if (i == 1)
@@ -831,7 +826,8 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
 
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
        mtk_crtc->cmdq_client =
-                       cmdq_mbox_create(dev, drm_crtc_index(&mtk_crtc->base),
+                       cmdq_mbox_create(mtk_crtc->mmsys_dev,
+                                        drm_crtc_index(&mtk_crtc->base),
                                         2000);
        if (IS_ERR(mtk_crtc->cmdq_client)) {
                dev_dbg(dev, "mtk_crtc %d failed to create mailbox client, writing register by CPU now\n",
index 6bd3694..040a8f3 100644 (file)
@@ -444,7 +444,6 @@ static int mtk_drm_probe(struct platform_device *pdev)
        if (!private)
                return -ENOMEM;
 
-       private->data = of_device_get_match_data(dev);
        private->mmsys_dev = dev->parent;
        if (!private->mmsys_dev) {
                dev_err(dev, "Failed to get MMSYS device\n");
@@ -514,7 +513,8 @@ static int mtk_drm_probe(struct platform_device *pdev)
                                goto err_node;
                        }
 
-                       ret = mtk_ddp_comp_init(dev, node, comp, comp_id, NULL);
+                       ret = mtk_ddp_comp_init(dev->parent, node, comp,
+                                               comp_id, NULL);
                        if (ret) {
                                of_node_put(node);
                                goto err_node;
@@ -571,7 +571,6 @@ static int mtk_drm_sys_suspend(struct device *dev)
        int ret;
 
        ret = drm_mode_config_helper_suspend(drm);
-       DRM_DEBUG_DRIVER("mtk_drm_sys_suspend\n");
 
        return ret;
 }
@@ -583,7 +582,6 @@ static int mtk_drm_sys_resume(struct device *dev)
        int ret;
 
        ret = drm_mode_config_helper_resume(drm);
-       DRM_DEBUG_DRIVER("mtk_drm_sys_resume\n");
 
        return ret;
 }
index c2bd683..92141a1 100644 (file)
@@ -164,6 +164,16 @@ static int mtk_plane_atomic_check(struct drm_plane *plane,
                                                   true, true);
 }
 
+static void mtk_plane_atomic_disable(struct drm_plane *plane,
+                                    struct drm_plane_state *old_state)
+{
+       struct mtk_plane_state *state = to_mtk_plane_state(plane->state);
+
+       state->pending.enable = false;
+       wmb(); /* Make sure the above parameter is set before update */
+       state->pending.dirty = true;
+}
+
 static void mtk_plane_atomic_update(struct drm_plane *plane,
                                    struct drm_plane_state *old_state)
 {
@@ -178,6 +188,11 @@ static void mtk_plane_atomic_update(struct drm_plane *plane,
        if (!crtc || WARN_ON(!fb))
                return;
 
+       if (!plane->state->visible) {
+               mtk_plane_atomic_disable(plane, old_state);
+               return;
+       }
+
        gem = fb->obj[0];
        mtk_gem = to_mtk_gem_obj(gem);
        addr = mtk_gem->dma_addr;
@@ -200,16 +215,6 @@ static void mtk_plane_atomic_update(struct drm_plane *plane,
        state->pending.dirty = true;
 }
 
-static void mtk_plane_atomic_disable(struct drm_plane *plane,
-                                    struct drm_plane_state *old_state)
-{
-       struct mtk_plane_state *state = to_mtk_plane_state(plane->state);
-
-       state->pending.enable = false;
-       wmb(); /* Make sure the above parameter is set before update */
-       state->pending.dirty = true;
-}
-
 static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = {
        .prepare_fb = drm_gem_fb_prepare_fb,
        .atomic_check = mtk_plane_atomic_check,
index 270bf22..02ac55c 100644 (file)
@@ -316,10 +316,7 @@ static void mtk_dsi_lane0_ulp_mode_leave(struct mtk_dsi *dsi)
 
 static bool mtk_dsi_clk_hs_state(struct mtk_dsi *dsi)
 {
-       u32 tmp_reg1;
-
-       tmp_reg1 = readl(dsi->regs + DSI_PHY_LCCON);
-       return ((tmp_reg1 & LC_HS_TX_EN) == 1) ? true : false;
+       return readl(dsi->regs + DSI_PHY_LCCON) & LC_HS_TX_EN;
 }
 
 static void mtk_dsi_clk_hs_mode(struct mtk_dsi *dsi, bool enter)
index 5feb760..1eebe31 100644 (file)
@@ -1630,8 +1630,6 @@ static int mtk_hdmi_audio_startup(struct device *dev, void *data)
 {
        struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
 
-       dev_dbg(dev, "%s\n", __func__);
-
        mtk_hdmi_audio_enable(hdmi);
 
        return 0;
@@ -1641,8 +1639,6 @@ static void mtk_hdmi_audio_shutdown(struct device *dev, void *data)
 {
        struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
 
-       dev_dbg(dev, "%s\n", __func__);
-
        mtk_hdmi_audio_disable(hdmi);
 }
 
@@ -1651,8 +1647,6 @@ mtk_hdmi_audio_digital_mute(struct device *dev, void *data, bool enable)
 {
        struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
 
-       dev_dbg(dev, "%s(%d)\n", __func__, enable);
-
        if (enable)
                mtk_hdmi_hw_aud_mute(hdmi);
        else
@@ -1665,8 +1659,6 @@ static int mtk_hdmi_audio_get_eld(struct device *dev, void *data, uint8_t *buf,
 {
        struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
 
-       dev_dbg(dev, "%s\n", __func__);
-
        memcpy(buf, hdmi->conn.eld, min(sizeof(hdmi->conn.eld), len));
 
        return 0;
@@ -1766,7 +1758,6 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev)
                goto err_bridge_remove;
        }
 
-       dev_dbg(dev, "mediatek hdmi probe success\n");
        return 0;
 
 err_bridge_remove:
@@ -1789,7 +1780,7 @@ static int mtk_hdmi_suspend(struct device *dev)
        struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
 
        mtk_hdmi_clk_disable_audio(hdmi);
-       dev_dbg(dev, "hdmi suspend success!\n");
+
        return 0;
 }
 
@@ -1804,7 +1795,6 @@ static int mtk_hdmi_resume(struct device *dev)
                return ret;
        }
 
-       dev_dbg(dev, "hdmi resume success!\n");
        return 0;
 }
 #endif
index b55f516..827b937 100644 (file)
 #define RGS_HDMITX_5T1_EDG             (0xf << 4)
 #define RGS_HDMITX_PLUG_TST            BIT(0)
 
-static const u8 PREDIV[3][4] = {
-       {0x0, 0x0, 0x0, 0x0},   /* 27Mhz */
-       {0x1, 0x1, 0x1, 0x1},   /* 74Mhz */
-       {0x1, 0x1, 0x1, 0x1}    /* 148Mhz */
-};
-
-static const u8 TXDIV[3][4] = {
-       {0x3, 0x3, 0x3, 0x2},   /* 27Mhz */
-       {0x2, 0x1, 0x1, 0x1},   /* 74Mhz */
-       {0x1, 0x0, 0x0, 0x0}    /* 148Mhz */
-};
-
-static const u8 FBKSEL[3][4] = {
-       {0x1, 0x1, 0x1, 0x1},   /* 27Mhz */
-       {0x1, 0x0, 0x1, 0x1},   /* 74Mhz */
-       {0x1, 0x0, 0x1, 0x1}    /* 148Mhz */
-};
-
-static const u8 FBKDIV[3][4] = {
-       {19, 24, 29, 19},       /* 27Mhz */
-       {19, 24, 14, 19},       /* 74Mhz */
-       {19, 24, 14, 19}        /* 148Mhz */
-};
-
-static const u8 DIVEN[3][4] = {
-       {0x2, 0x1, 0x1, 0x2},   /* 27Mhz */
-       {0x2, 0x2, 0x2, 0x2},   /* 74Mhz */
-       {0x2, 0x2, 0x2, 0x2}    /* 148Mhz */
-};
-
-static const u8 HTPLLBP[3][4] = {
-       {0xc, 0xc, 0x8, 0xc},   /* 27Mhz */
-       {0xc, 0xf, 0xf, 0xc},   /* 74Mhz */
-       {0xc, 0xf, 0xf, 0xc}    /* 148Mhz */
-};
-
-static const u8 HTPLLBC[3][4] = {
-       {0x2, 0x3, 0x3, 0x2},   /* 27Mhz */
-       {0x2, 0x3, 0x3, 0x2},   /* 74Mhz */
-       {0x2, 0x3, 0x3, 0x2}    /* 148Mhz */
-};
-
-static const u8 HTPLLBR[3][4] = {
-       {0x1, 0x1, 0x0, 0x1},   /* 27Mhz */
-       {0x1, 0x2, 0x2, 0x1},   /* 74Mhz */
-       {0x1, 0x2, 0x2, 0x1}    /* 148Mhz */
-};
-
 static int mtk_hdmi_pll_prepare(struct clk_hw *hw)
 {
        struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
 
-       dev_dbg(hdmi_phy->dev, "%s\n", __func__);
-
        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_AUTOK_EN);
        mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_POSDIV);
        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3, RG_HDMITX_MHLCK_EN);
@@ -178,8 +128,6 @@ static void mtk_hdmi_pll_unprepare(struct clk_hw *hw)
 {
        struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
 
-       dev_dbg(hdmi_phy->dev, "%s\n", __func__);
-
        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_TXDIV_EN);
        mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_LPF_EN);
        usleep_range(100, 150);
index 8ea0054..049c4bf 100644 (file)
 #define VIU_OSD_FIFO_DEPTH_VAL(val)      ((val & 0x7f) << 12)
 #define VIU_OSD_WORDS_PER_BURST(words)   (((words & 0x4) >> 1) << 22)
 #define VIU_OSD_FIFO_LIMITS(size)        ((size & 0xf) << 24)
+#define VIU_OSD_BURST_LENGTH_24          (0x0 << 31 | 0x0 << 10)
+#define VIU_OSD_BURST_LENGTH_32          (0x0 << 31 | 0x1 << 10)
+#define VIU_OSD_BURST_LENGTH_48          (0x0 << 31 | 0x2 << 10)
+#define VIU_OSD_BURST_LENGTH_64          (0x0 << 31 | 0x3 << 10)
+#define VIU_OSD_BURST_LENGTH_96          (0x1 << 31 | 0x0 << 10)
+#define VIU_OSD_BURST_LENGTH_128         (0x1 << 31 | 0x1 << 10)
 
 #define VD1_IF0_GEN_REG 0x1a50
 #define VD1_IF0_CANVAS0 0x1a51
index 304f8ff..aede0c6 100644 (file)
@@ -411,13 +411,6 @@ void meson_viu_gxm_disable_osd1_afbc(struct meson_drm *priv)
                            priv->io_base + _REG(VIU_MISC_CTRL1));
 }
 
-static inline uint32_t meson_viu_osd_burst_length_reg(uint32_t length)
-{
-       uint32_t val = (((length & 0x80) % 24) / 12);
-
-       return (((val & 0x3) << 10) | (((val & 0x4) >> 2) << 31));
-}
-
 void meson_viu_init(struct meson_drm *priv)
 {
        uint32_t reg;
@@ -444,9 +437,9 @@ void meson_viu_init(struct meson_drm *priv)
                VIU_OSD_FIFO_LIMITS(2);      /* fifo_lim: 2*16=32 */
 
        if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
-               reg |= meson_viu_osd_burst_length_reg(32);
+               reg |= VIU_OSD_BURST_LENGTH_32;
        else
-               reg |= meson_viu_osd_burst_length_reg(64);
+               reg |= VIU_OSD_BURST_LENGTH_64;
 
        writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
        writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
index 60f6472..6021f8d 100644 (file)
@@ -408,7 +408,7 @@ a2xx_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev)
        struct msm_gem_address_space *aspace;
 
        aspace = msm_gem_address_space_create(mmu, "gpu", SZ_16M,
-               SZ_16M + 0xfff * SZ_64K);
+               0xfff * SZ_64K);
 
        if (IS_ERR(aspace) && !IS_ERR(mmu))
                mmu->funcs->destroy(mmu);
index 096be97..21e77d6 100644 (file)
@@ -1121,7 +1121,7 @@ static int a6xx_gmu_memory_probe(struct a6xx_gmu *gmu)
                return -ENODEV;
 
        mmu = msm_iommu_new(gmu->dev, domain);
-       gmu->aspace = msm_gem_address_space_create(mmu, "gmu", 0x0, 0x7fffffff);
+       gmu->aspace = msm_gem_address_space_create(mmu, "gmu", 0x0, 0x80000000);
        if (IS_ERR(gmu->aspace)) {
                iommu_domain_free(domain);
                return PTR_ERR(gmu->aspace);
index a1589e0..7768557 100644 (file)
@@ -893,8 +893,8 @@ static const struct adreno_gpu_funcs funcs = {
 #if defined(CONFIG_DRM_MSM_GPU_STATE)
                .gpu_state_get = a6xx_gpu_state_get,
                .gpu_state_put = a6xx_gpu_state_put,
-               .create_address_space = adreno_iommu_create_address_space,
 #endif
+               .create_address_space = adreno_iommu_create_address_space,
        },
        .get_timestamp = a6xx_get_timestamp,
 };
index 89673c7..5db06b5 100644 (file)
@@ -194,7 +194,7 @@ adreno_iommu_create_address_space(struct msm_gpu *gpu,
        struct msm_gem_address_space *aspace;
 
        aspace = msm_gem_address_space_create(mmu, "gpu", SZ_16M,
-               0xfffffff);
+               0xffffffff - SZ_16M);
 
        if (IS_ERR(aspace) && !IS_ERR(mmu))
                mmu->funcs->destroy(mmu);
index 63976dc..0946a86 100644 (file)
@@ -521,7 +521,7 @@ static struct msm_display_topology dpu_encoder_get_topology(
                        struct dpu_kms *dpu_kms,
                        struct drm_display_mode *mode)
 {
-       struct msm_display_topology topology;
+       struct msm_display_topology topology = {0};
        int i, intf_count = 0;
 
        for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
@@ -537,7 +537,8 @@ static struct msm_display_topology dpu_encoder_get_topology(
         * 1 LM, 1 INTF
         * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
         *
-        * Adding color blocks only to primary interface
+        * Adding color blocks only to primary interface if available in
+        * sufficient number
         */
        if (intf_count == 2)
                topology.num_lm = 2;
@@ -546,8 +547,11 @@ static struct msm_display_topology dpu_encoder_get_topology(
        else
                topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
 
-       if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI)
-               topology.num_dspp = topology.num_lm;
+       if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI) {
+               if (dpu_kms->catalog->dspp &&
+                       (dpu_kms->catalog->dspp_count >= topology.num_lm))
+                       topology.num_dspp = topology.num_lm;
+       }
 
        topology.num_enc = 0;
        topology.num_intf = intf_count;
@@ -2136,7 +2140,6 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc,
 
        dpu_enc = to_dpu_encoder_virt(enc);
 
-       mutex_init(&dpu_enc->enc_lock);
        ret = dpu_encoder_setup_display(dpu_enc, dpu_kms, disp_info);
        if (ret)
                goto fail;
@@ -2151,7 +2154,6 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc,
                                0);
 
 
-       mutex_init(&dpu_enc->rc_lock);
        INIT_DELAYED_WORK(&dpu_enc->delayed_off_work,
                        dpu_encoder_off_work);
        dpu_enc->idle_timeout = IDLE_TIMEOUT;
@@ -2183,7 +2185,7 @@ struct drm_encoder *dpu_encoder_init(struct drm_device *dev,
 
        dpu_enc = devm_kzalloc(dev->dev, sizeof(*dpu_enc), GFP_KERNEL);
        if (!dpu_enc)
-               return ERR_PTR(ENOMEM);
+               return ERR_PTR(-ENOMEM);
 
        rc = drm_encoder_init(dev, &dpu_enc->base, &dpu_encoder_funcs,
                        drm_enc_mode, NULL);
@@ -2196,6 +2198,8 @@ struct drm_encoder *dpu_encoder_init(struct drm_device *dev,
 
        spin_lock_init(&dpu_enc->enc_spinlock);
        dpu_enc->enabled = false;
+       mutex_init(&dpu_enc->enc_lock);
+       mutex_init(&dpu_enc->rc_lock);
 
        return &dpu_enc->base;
 }
index b8615d4..680527e 100644 (file)
@@ -780,7 +780,7 @@ static int _dpu_kms_mmu_init(struct dpu_kms *dpu_kms)
 
        mmu = msm_iommu_new(dpu_kms->dev->dev, domain);
        aspace = msm_gem_address_space_create(mmu, "dpu1",
-               0x1000, 0xfffffff);
+               0x1000, 0x100000000 - 0x1000);
 
        if (IS_ERR(aspace)) {
                mmu->funcs->destroy(mmu);
index 0889718..fc6a3f8 100644 (file)
@@ -514,7 +514,7 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
                        config->iommu);
 
                aspace  = msm_gem_address_space_create(mmu,
-                       "mdp4", 0x1000, 0xffffffff);
+                       "mdp4", 0x1000, 0x100000000 - 0x1000);
 
                if (IS_ERR(aspace)) {
                        if (!IS_ERR(mmu))
index 19ec486..e193865 100644 (file)
@@ -633,7 +633,7 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
                mmu = msm_iommu_new(iommu_dev, config->platform.iommu);
 
                aspace = msm_gem_address_space_create(mmu, "mdp5",
-                       0x1000, 0xffffffff);
+                       0x1000, 0x100000000 - 0x1000);
 
                if (IS_ERR(aspace)) {
                        if (!IS_ERR(mmu))
index 001fbf5..a1d94be 100644 (file)
@@ -71,8 +71,10 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,
        queue->flags = flags;
 
        if (priv->gpu) {
-               if (prio >= priv->gpu->nr_rings)
+               if (prio >= priv->gpu->nr_rings) {
+                       kfree(queue);
                        return -EINVAL;
+               }
 
                queue->prio = prio;
        }
index d472942..800b775 100644 (file)
@@ -601,6 +601,9 @@ nv50_audio_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
                                (0x0100 << nv_crtc->index),
        };
 
+       if (!nv_encoder->audio)
+               return;
+
        nv_encoder->audio = false;
        nvif_mthd(&disp->disp->object, 0, &args, sizeof(args));
 
@@ -2070,7 +2073,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
         */
        if (core->assign_windows) {
                core->func->wndw.owner(core);
-               core->func->update(core, interlock, false);
+               nv50_disp_atomic_commit_core(state, interlock);
                core->assign_windows = false;
                interlock[NV50_DISP_INTERLOCK_CORE] = 0;
        }
@@ -2503,7 +2506,7 @@ nv50_display_create(struct drm_device *dev)
        if (disp->disp->object.oclass >= TU102_DISP)
                nouveau_display(dev)->format_modifiers = wndwc57e_modifiers;
        else
-       if (disp->disp->object.oclass >= GF110_DISP)
+       if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_FERMI)
                nouveau_display(dev)->format_modifiers = disp90xx_modifiers;
        else
                nouveau_display(dev)->format_modifiers = disp50xx_modifiers;
index 496c462..07373bb 100644 (file)
@@ -191,6 +191,7 @@ nouveau_decode_mod(struct nouveau_drm *drm,
                   uint32_t *tile_mode,
                   uint8_t *kind)
 {
+       struct nouveau_display *disp = nouveau_display(drm->dev);
        BUG_ON(!tile_mode || !kind);
 
        if (modifier == DRM_FORMAT_MOD_LINEAR) {
@@ -202,6 +203,12 @@ nouveau_decode_mod(struct nouveau_drm *drm,
                 * Extract the block height and kind from the corresponding
                 * modifier fields.  See drm_fourcc.h for details.
                 */
+
+               if ((modifier & (0xffull << 12)) == 0ull) {
+                       /* Legacy modifier.  Translate to this dev's 'kind.' */
+                       modifier |= disp->format_modifiers[0] & (0xffull << 12);
+               }
+
                *tile_mode = (uint32_t)(modifier & 0xF);
                *kind = (uint8_t)((modifier >> 12) & 0xFF);
 
@@ -227,6 +234,16 @@ nouveau_framebuffer_get_layout(struct drm_framebuffer *fb,
        }
 }
 
+static const u64 legacy_modifiers[] = {
+       DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0),
+       DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1),
+       DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2),
+       DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3),
+       DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4),
+       DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5),
+       DRM_FORMAT_MOD_INVALID
+};
+
 static int
 nouveau_validate_decode_mod(struct nouveau_drm *drm,
                            uint64_t modifier,
@@ -247,8 +264,14 @@ nouveau_validate_decode_mod(struct nouveau_drm *drm,
             (disp->format_modifiers[mod] != modifier);
             mod++);
 
-       if (disp->format_modifiers[mod] == DRM_FORMAT_MOD_INVALID)
-               return -EINVAL;
+       if (disp->format_modifiers[mod] == DRM_FORMAT_MOD_INVALID) {
+               for (mod = 0;
+                    (legacy_modifiers[mod] != DRM_FORMAT_MOD_INVALID) &&
+                    (legacy_modifiers[mod] != modifier);
+                    mod++);
+               if (legacy_modifiers[mod] == DRM_FORMAT_MOD_INVALID)
+                       return -EINVAL;
+       }
 
        nouveau_decode_mod(drm, modifier, tile_mode, kind);
 
index e5c230d..cc99938 100644 (file)
@@ -550,7 +550,7 @@ static unsigned long nouveau_dmem_migrate_copy_one(struct nouveau_drm *drm,
                                         DMA_BIDIRECTIONAL);
                if (dma_mapping_error(dev, *dma_addr))
                        goto out_free_page;
-               if (drm->dmem->migrate.copy_func(drm, page_size(spage),
+               if (drm->dmem->migrate.copy_func(drm, 1,
                        NOUVEAU_APER_VRAM, paddr, NOUVEAU_APER_HOST, *dma_addr))
                        goto out_dma_unmap;
        } else {
index 3d11b84..d5c23d1 100644 (file)
@@ -315,7 +315,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
        struct drm_framebuffer *fb;
        struct nouveau_channel *chan;
        struct nouveau_bo *nvbo;
-       struct drm_mode_fb_cmd2 mode_cmd;
+       struct drm_mode_fb_cmd2 mode_cmd = {};
        int ret;
 
        mode_cmd.width = sizes->surface_width;
@@ -590,6 +590,7 @@ fini:
        drm_fb_helper_fini(&fbcon->helper);
 free:
        kfree(fbcon);
+       drm->fbcon = NULL;
        return ret;
 }
 
index ba9f935..6586d9d 100644 (file)
@@ -562,6 +562,7 @@ static int nouveau_range_fault(struct nouveau_svmm *svmm,
                .end = notifier->notifier.interval_tree.last + 1,
                .pfn_flags_mask = HMM_PFN_REQ_FAULT | HMM_PFN_REQ_WRITE,
                .hmm_pfns = hmm_pfns,
+               .dev_private_owner = drm->dev,
        };
        struct mm_struct *mm = notifier->notifier.mm;
        int ret;
index dcf0824..dffcac2 100644 (file)
@@ -117,15 +117,6 @@ nvkm_outp_acquire_hda(struct nvkm_outp *outp, enum nvkm_ior_type type,
 {
        struct nvkm_ior *ior;
 
-       /* First preference is to reuse the OR that is currently armed
-        * on HW, if any, in order to prevent unnecessary switching.
-        */
-       list_for_each_entry(ior, &outp->disp->ior, head) {
-               if (!ior->identity && !!ior->func->hda.hpd == hda &&
-                   !ior->asy.outp && ior->arm.outp == outp)
-                       return nvkm_outp_acquire_ior(outp, user, ior);
-       }
-
        /* Failing that, a completely unused OR is the next best thing. */
        list_for_each_entry(ior, &outp->disp->ior, head) {
                if (!ior->identity && !!ior->func->hda.hpd == hda &&
@@ -173,6 +164,27 @@ nvkm_outp_acquire(struct nvkm_outp *outp, u8 user, bool hda)
                return nvkm_outp_acquire_ior(outp, user, ior);
        }
 
+       /* First preference is to reuse the OR that is currently armed
+        * on HW, if any, in order to prevent unnecessary switching.
+        */
+       list_for_each_entry(ior, &outp->disp->ior, head) {
+               if (!ior->identity && !ior->asy.outp && ior->arm.outp == outp) {
+                       /*XXX: For various complicated reasons, we can't outright switch
+                        *     the boot-time OR on the first modeset without some fairly
+                        *     invasive changes.
+                        *
+                        *     The systems that were fixed by modifying the OR selection
+                        *     code to account for HDA support shouldn't regress here as
+                        *     the HDA-enabled ORs match the relevant output's pad macro
+                        *     index, and the firmware seems to select an OR this way.
+                        *
+                        *     This warning is to make it obvious if that proves wrong.
+                        */
+                       WARN_ON(hda && !ior->func->hda.hpd);
+                       return nvkm_outp_acquire_ior(outp, user, ior);
+               }
+       }
+
        /* If we don't need HDA, first try to acquire an OR that doesn't
         * support it to leave free the ones that do.
         */
index c8ab1b5..db7769c 100644 (file)
@@ -118,10 +118,10 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
                if (retries)
                        udelay(400);
 
-               /* transaction request, wait up to 1ms for it to complete */
+               /* transaction request, wait up to 2ms for it to complete */
                nvkm_wr32(device, 0x00e4e4 + base, 0x00010000 | ctrl);
 
-               timeout = 1000;
+               timeout = 2000;
                do {
                        ctrl = nvkm_rd32(device, 0x00e4e4 + base);
                        udelay(1);
index 7ef6089..edb6148 100644 (file)
@@ -118,10 +118,10 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
                if (retries)
                        udelay(400);
 
-               /* transaction request, wait up to 1ms for it to complete */
+               /* transaction request, wait up to 2ms for it to complete */
                nvkm_wr32(device, 0x00d954 + base, 0x00010000 | ctrl);
 
-               timeout = 1000;
+               timeout = 2000;
                do {
                        ctrl = nvkm_rd32(device, 0x00d954 + base);
                        udelay(1);
index 46fe180..2649469 100644 (file)
@@ -615,9 +615,9 @@ static const struct panel_desc boe_tv101wum_nl6_desc = {
 static const struct drm_display_mode auo_kd101n80_45na_default_mode = {
        .clock = 157000,
        .hdisplay = 1200,
-       .hsync_start = 1200 + 80,
-       .hsync_end = 1200 + 80 + 24,
-       .htotal = 1200 + 80 + 24 + 36,
+       .hsync_start = 1200 + 60,
+       .hsync_end = 1200 + 60 + 24,
+       .htotal = 1200 + 60 + 24 + 56,
        .vdisplay = 1920,
        .vsync_start = 1920 + 16,
        .vsync_end = 1920 + 16 + 4,
index b6ecd15..4aeb960 100644 (file)
@@ -1250,7 +1250,21 @@ static const struct panel_desc boe_nv133fhm_n61 = {
                .height = 165,
        },
        .delay = {
-               .hpd_absent_delay = 200,
+               /*
+                * When power is first given to the panel there's a short
+                * spike on the HPD line.  It was explained that this spike
+                * was until the TCON data download was complete.  On
+                * one system this was measured at 8 ms.  We'll put 15 ms
+                * in the prepare delay just to be safe and take it away
+                * from the hpd_absent_delay (which would otherwise be 200 ms)
+                * to handle this.  That means:
+                * - If HPD isn't hooked up you still have 200 ms delay.
+                * - If HPD is hooked up we won't try to look at it for the
+                *   first 15 ms.
+                */
+               .prepare = 15,
+               .hpd_absent_delay = 185,
+
                .unprepare = 500,
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
@@ -2495,6 +2509,7 @@ static const struct panel_desc logicpd_type_28 = {
        .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
        .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE |
                     DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE,
+       .connector_type = DRM_MODE_CONNECTOR_DPI,
 };
 
 static const struct panel_desc mitsubishi_aa070mc01 = {
@@ -2663,6 +2678,7 @@ static const struct panel_desc newhaven_nhd_43_480272ef_atxl = {
        .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
        .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE |
                     DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE,
+       .connector_type = DRM_MODE_CONNECTOR_DPI,
 };
 
 static const struct display_timing nlt_nl192108ac18_02d_timing = {
index 134aa2b..f434efd 100644 (file)
@@ -5563,6 +5563,7 @@ static int ci_parse_power_table(struct radeon_device *rdev)
        if (!rdev->pm.dpm.ps)
                return -ENOMEM;
        power_state_offset = (u8 *)state_array->states;
+       rdev->pm.dpm.num_ps = 0;
        for (i = 0; i < state_array->ucNumEntries; i++) {
                u8 *idx;
                power_state = (union pplib_power_state *)power_state_offset;
@@ -5572,10 +5573,8 @@ static int ci_parse_power_table(struct radeon_device *rdev)
                if (!rdev->pm.power_state[i].clock_info)
                        return -EINVAL;
                ps = kzalloc(sizeof(struct ci_ps), GFP_KERNEL);
-               if (ps == NULL) {
-                       kfree(rdev->pm.dpm.ps);
+               if (ps == NULL)
                        return -ENOMEM;
-               }
                rdev->pm.dpm.ps[i].ps_priv = ps;
                ci_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
                                              non_clock_info,
@@ -5597,8 +5596,8 @@ static int ci_parse_power_table(struct radeon_device *rdev)
                        k++;
                }
                power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
+               rdev->pm.dpm.num_ps = i + 1;
        }
-       rdev->pm.dpm.num_ps = state_array->ucNumEntries;
 
        /* fill in the vce power states */
        for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) {
index b57c37d..c7fbb79 100644 (file)
@@ -2127,7 +2127,7 @@ static int ni_init_smc_spll_table(struct radeon_device *rdev)
                if (clk_s & ~(SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT))
                        ret = -EINVAL;
 
-               if (clk_s & ~(SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT))
+               if (fb_div & ~(SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT))
                        ret = -EINVAL;
 
                if (clk_v & ~(SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT))
index 0919f1f..f65d148 100644 (file)
@@ -31,6 +31,7 @@ config DRM_RCAR_DW_HDMI
 config DRM_RCAR_LVDS
        tristate "R-Car DU LVDS Encoder Support"
        depends on DRM && DRM_BRIDGE && OF
+       select DRM_KMS_HELPER
        select DRM_PANEL
        select OF_FLATTREE
        select OF_OVERLAY
index ce07ddc..2f2c9f0 100644 (file)
@@ -259,9 +259,8 @@ sun4i_hdmi_connector_detect(struct drm_connector *connector, bool force)
        struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector);
        unsigned long reg;
 
-       if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_HPD_REG, reg,
-                              reg & SUN4I_HDMI_HPD_HIGH,
-                              0, 500000)) {
+       reg = readl(hdmi->base + SUN4I_HDMI_HPD_REG);
+       if (!(reg & SUN4I_HDMI_HPD_HIGH)) {
                cec_phys_addr_invalidate(hdmi->cec_adap);
                return connector_status_disconnected;
        }
index 56cc037..cc4fb91 100644 (file)
@@ -363,6 +363,19 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
        mixer->engine.ops = &sun8i_engine_ops;
        mixer->engine.node = dev->of_node;
 
+       if (of_find_property(dev->of_node, "iommus", NULL)) {
+               /*
+                * This assume we have the same DMA constraints for
+                * all our the mixers in our pipeline. This sounds
+                * bad, but it has always been the case for us, and
+                * DRM doesn't do per-device allocation either, so we
+                * would need to fix DRM first...
+                */
+               ret = of_dma_configure(drm->dev, dev->of_node, true);
+               if (ret)
+                       return ret;
+       }
+
        /*
         * While this function can fail, we shouldn't do anything
         * if this happens. Some early DE2 DT entries don't provide
index 83f31c6..04d6848 100644 (file)
@@ -957,6 +957,7 @@ static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm,
        }
 
        drm_plane_helper_add(&plane->base, &tegra_cursor_plane_helper_funcs);
+       drm_plane_create_zpos_immutable_property(&plane->base, 255);
 
        return &plane->base;
 }
index 8183e61..22a03f7 100644 (file)
@@ -149,7 +149,9 @@ int tegra_display_hub_prepare(struct tegra_display_hub *hub)
        for (i = 0; i < hub->soc->num_wgrps; i++) {
                struct tegra_windowgroup *wgrp = &hub->wgrps[i];
 
-               tegra_windowgroup_enable(wgrp);
+               /* Skip orphaned window group whose parent DC is disabled */
+               if (wgrp->parent)
+                       tegra_windowgroup_enable(wgrp);
        }
 
        return 0;
@@ -166,7 +168,9 @@ void tegra_display_hub_cleanup(struct tegra_display_hub *hub)
        for (i = 0; i < hub->soc->num_wgrps; i++) {
                struct tegra_windowgroup *wgrp = &hub->wgrps[i];
 
-               tegra_windowgroup_disable(wgrp);
+               /* Skip orphaned window group whose parent DC is disabled */
+               if (wgrp->parent)
+                       tegra_windowgroup_disable(wgrp);
        }
 }
 
@@ -944,6 +948,15 @@ static int tegra_display_hub_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "failed to register host1x client: %d\n",
                        err);
 
+       err = devm_of_platform_populate(&pdev->dev);
+       if (err < 0)
+               goto unregister;
+
+       return err;
+
+unregister:
+       host1x_client_unregister(&hub->client);
+       pm_runtime_disable(&pdev->dev);
        return err;
 }
 
index f73b81c..0f20e14 100644 (file)
@@ -883,8 +883,10 @@ static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo,
        if (!fence)
                return 0;
 
-       if (no_wait_gpu)
+       if (no_wait_gpu) {
+               dma_fence_put(fence);
                return -EBUSY;
+       }
 
        dma_resv_add_shared_fence(bo->base.resv, fence);
 
index a43aa72..fa03fab 100644 (file)
@@ -300,8 +300,10 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf,
                        break;
                case -EBUSY:
                case -ERESTARTSYS:
+                       dma_fence_put(moving);
                        return VM_FAULT_NOPAGE;
                default:
+                       dma_fence_put(moving);
                        return VM_FAULT_SIGBUS;
                }
 
index 9ffa9c7..16b3856 100644 (file)
@@ -1069,10 +1069,6 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane,
        if (new_content_type != SAME_AS_DISPLAY) {
                struct vmw_surface_metadata metadata = {0};
 
-               metadata.base_size.width = hdisplay;
-               metadata.base_size.height = vdisplay;
-               metadata.base_size.depth = 1;
-
                /*
                 * If content buffer is a buffer object, then we have to
                 * construct surface info
@@ -1104,6 +1100,10 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane,
                        metadata = new_vfbs->surface->metadata;
                }
 
+               metadata.base_size.width = hdisplay;
+               metadata.base_size.height = vdisplay;
+               metadata.base_size.depth = 1;
+
                if (vps->surf) {
                        struct drm_vmw_size cur_base_size =
                                vps->surf->metadata.base_size;
index 6a995db..e201f62 100644 (file)
@@ -686,8 +686,17 @@ EXPORT_SYMBOL(host1x_driver_register_full);
  */
 void host1x_driver_unregister(struct host1x_driver *driver)
 {
+       struct host1x *host1x;
+
        driver_unregister(&driver->driver);
 
+       mutex_lock(&devices_lock);
+
+       list_for_each_entry(host1x, &devices, list)
+               host1x_detach_driver(host1x, driver);
+
+       mutex_unlock(&devices_lock);
+
        mutex_lock(&drivers_lock);
        list_del_init(&driver->list);
        mutex_unlock(&drivers_lock);
index d24344e..d0ebb70 100644 (file)
@@ -468,11 +468,18 @@ static int host1x_probe(struct platform_device *pdev)
 
        err = host1x_register(host);
        if (err < 0)
-               goto deinit_intr;
+               goto deinit_debugfs;
+
+       err = devm_of_platform_populate(&pdev->dev);
+       if (err < 0)
+               goto unregister;
 
        return 0;
 
-deinit_intr:
+unregister:
+       host1x_unregister(host);
+deinit_debugfs:
+       host1x_debug_deinit(host);
        host1x_intr_deinit(host);
 deinit_syncpt:
        host1x_syncpt_deinit(host);
index 6f1fe72..a9c2de9 100644 (file)
@@ -25,6 +25,7 @@
 
 #define U1_MOUSE_REPORT_ID                     0x01 /* Mouse data ReportID */
 #define U1_ABSOLUTE_REPORT_ID          0x03 /* Absolute data ReportID */
+#define U1_ABSOLUTE_REPORT_ID_SECD  0x02 /* FW-PTP Absolute data ReportID */
 #define U1_FEATURE_REPORT_ID           0x05 /* Feature ReportID */
 #define U1_SP_ABSOLUTE_REPORT_ID       0x06 /* Feature ReportID */
 
@@ -368,6 +369,7 @@ static int u1_raw_event(struct alps_dev *hdata, u8 *data, int size)
        case U1_FEATURE_REPORT_ID:
                break;
        case U1_ABSOLUTE_REPORT_ID:
+       case U1_ABSOLUTE_REPORT_ID_SECD:
                for (i = 0; i < hdata->max_fingers; i++) {
                        u8 *contact = &data[i * 5];
 
index 359bdfb..e82f604 100644 (file)
@@ -60,6 +60,7 @@ MODULE_PARM_DESC(swap_fn_leftctrl, "Swap the Fn and left Control keys. "
 struct apple_sc {
        unsigned long quirks;
        unsigned int fn_on;
+       unsigned int fn_found;
        DECLARE_BITMAP(pressed_numlock, KEY_CNT);
 };
 
@@ -365,12 +366,15 @@ static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                struct hid_field *field, struct hid_usage *usage,
                unsigned long **bit, int *max)
 {
+       struct apple_sc *asc = hid_get_drvdata(hdev);
+
        if (usage->hid == (HID_UP_CUSTOM | 0x0003) ||
                        usage->hid == (HID_UP_MSVENDOR | 0x0003) ||
                        usage->hid == (HID_UP_HPVENDOR2 | 0x0003)) {
                /* The fn key on Apple USB keyboards */
                set_bit(EV_REP, hi->input->evbit);
                hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN);
+               asc->fn_found = true;
                apple_setup_input(hi->input);
                return 1;
        }
@@ -397,6 +401,19 @@ static int apple_input_mapped(struct hid_device *hdev, struct hid_input *hi,
        return 0;
 }
 
+static int apple_input_configured(struct hid_device *hdev,
+               struct hid_input *hidinput)
+{
+       struct apple_sc *asc = hid_get_drvdata(hdev);
+
+       if ((asc->quirks & APPLE_HAS_FN) && !asc->fn_found) {
+               hid_info(hdev, "Fn key not found (Apple Wireless Keyboard clone?), disabling Fn key handling\n");
+               asc->quirks = 0;
+       }
+
+       return 0;
+}
+
 static int apple_probe(struct hid_device *hdev,
                const struct hid_device_id *id)
 {
@@ -611,6 +628,7 @@ static struct hid_driver apple_driver = {
        .event = apple_event,
        .input_mapping = apple_input_mapping,
        .input_mapped = apple_input_mapped,
+       .input_configured = apple_input_configured,
 };
 module_hid_driver(apple_driver);
 
index 874fc37..6f370e0 100644 (file)
 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081    0xa081
 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A0C2    0xa0c2
 #define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096 0xa096
+#define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A293 0xa293
 
 #define USB_VENDOR_ID_IMATION          0x0718
 #define USB_DEVICE_ID_DISC_STAKKA      0xd000
 #define USB_DEVICE_ID_ROCCAT_RYOS_MK_PRO       0x3232
 #define USB_DEVICE_ID_ROCCAT_SAVU      0x2d5a
 
+#define USB_VENDOR_ID_SAI              0x17dd
+
 #define USB_VENDOR_ID_SAITEK           0x06a3
 #define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17
 #define USB_DEVICE_ID_SAITEK_PS1000    0x0621
index 48dff5d..a78c13c 100644 (file)
@@ -1153,7 +1153,7 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
        if (!dj_report)
                return -ENOMEM;
        dj_report->report_id = REPORT_ID_DJ_SHORT;
-       dj_report->device_index = 0xFF;
+       dj_report->device_index = HIDPP_RECEIVER_INDEX;
        dj_report->report_type = REPORT_TYPE_CMD_GET_PAIRED_DEVICES;
        retval = logi_dj_recv_send_report(djrcv_dev, dj_report);
        kfree(dj_report);
@@ -1175,7 +1175,7 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
 
        if (djrcv_dev->type == recvr_type_dj) {
                dj_report->report_id = REPORT_ID_DJ_SHORT;
-               dj_report->device_index = 0xFF;
+               dj_report->device_index = HIDPP_RECEIVER_INDEX;
                dj_report->report_type = REPORT_TYPE_CMD_SWITCH;
                dj_report->report_params[CMD_SWITCH_PARAM_DEVBITFIELD] = 0x3F;
                dj_report->report_params[CMD_SWITCH_PARAM_TIMEOUT_SECONDS] =
@@ -1204,7 +1204,7 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
        memset(buf, 0, HIDPP_REPORT_SHORT_LENGTH);
 
        buf[0] = REPORT_ID_HIDPP_SHORT;
-       buf[1] = 0xFF;
+       buf[1] = HIDPP_RECEIVER_INDEX;
        buf[2] = 0x80;
        buf[3] = 0x00;
        buf[4] = 0x00;
index 1e1cf8e..b8b53dc 100644 (file)
@@ -3146,7 +3146,7 @@ static int hi_res_scroll_enable(struct hidpp_device *hidpp)
                multiplier = 1;
 
        hidpp->vertical_wheel_counter.wheel_multiplier = multiplier;
-       hid_info(hidpp->hid_dev, "multiplier = %d\n", multiplier);
+       hid_dbg(hidpp->hid_dev, "wheel multiplier = %d\n", multiplier);
        return 0;
 }
 
index 3413866..abd8690 100644 (file)
@@ -535,6 +535,12 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd
                __set_bit(MSC_RAW, input->mscbit);
        }
 
+       /*
+        * hid-input may mark device as using autorepeat, but neither
+        * the trackpad, nor the mouse actually want it.
+        */
+       __clear_bit(EV_REP, input->evbit);
+
        return 0;
 }
 
index ca8b5c2..934fc0a 100644 (file)
@@ -88,6 +88,7 @@ static const struct hid_device_id hid_quirks[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
        { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
        { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096), HID_QUIRK_NO_INIT_REPORTS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A293), HID_QUIRK_ALWAYS_POLL },
        { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A), HID_QUIRK_ALWAYS_POLL },
        { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A), HID_QUIRK_ALWAYS_POLL },
        { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
@@ -832,6 +833,7 @@ static const struct hid_device_id hid_ignore_list[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_PETZL, USB_DEVICE_ID_PETZL_HEADLAMP) },
        { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_SAI, USB_DEVICE_ID_CYPRESS_HIDCOM) },
 #if IS_ENABLED(CONFIG_MOUSE_SYNAPTICS_USB)
        { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_INT_TP) },
index 6286204..a3b151b 100644 (file)
@@ -526,7 +526,8 @@ static int steam_register(struct steam_device *steam)
                        steam_battery_register(steam);
 
                mutex_lock(&steam_devices_lock);
-               list_add(&steam->list, &steam_devices);
+               if (list_empty(&steam->list))
+                       list_add(&steam->list, &steam_devices);
                mutex_unlock(&steam_devices_lock);
        }
 
@@ -552,7 +553,7 @@ static void steam_unregister(struct steam_device *steam)
                hid_info(steam->hdev, "Steam Controller '%s' disconnected",
                                steam->serial_no);
                mutex_lock(&steam_devices_lock);
-               list_del(&steam->list);
+               list_del_init(&steam->list);
                mutex_unlock(&steam_devices_lock);
                steam->serial_no[0] = 0;
        }
@@ -738,6 +739,7 @@ static int steam_probe(struct hid_device *hdev,
        mutex_init(&steam->mutex);
        steam->quirks = id->driver_data;
        INIT_WORK(&steam->work_connect, steam_work_connect_cb);
+       INIT_LIST_HEAD(&steam->list);
 
        steam->client_hdev = steam_create_client_hid(hdev);
        if (IS_ERR(steam->client_hdev)) {
index ec142bc..35f3bfc 100644 (file)
@@ -373,6 +373,14 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = {
                },
                .driver_data = (void *)&sipodev_desc
        },
+       {
+               .ident = "Mediacom FlexBook edge 13",
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MEDIACOM"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "FlexBook_edge13-M-FBE13"),
+               },
+               .driver_data = (void *)&sipodev_desc
+       },
        {
                .ident = "Odys Winbook 13",
                .matches = {
index 9147ee9..d69f4ef 100644 (file)
@@ -1368,7 +1368,7 @@ static void hv_kmsg_dump(struct kmsg_dumper *dumper,
         * Write dump contents to the page. No need to synchronize; panic should
         * be single-threaded.
         */
-       kmsg_dump_get_buffer(dumper, true, hv_panic_page, HV_HYP_PAGE_SIZE,
+       kmsg_dump_get_buffer(dumper, false, hv_panic_page, HV_HYP_PAGE_SIZE,
                             &bytes_written);
        if (bytes_written)
                hyperv_report_panic_msg(panic_pa, bytes_written);
index 0db8ef4..a270b97 100644 (file)
@@ -883,7 +883,7 @@ static int acpi_power_meter_add(struct acpi_device *device)
 
        res = setup_attrs(resource);
        if (res)
-               goto exit_free;
+               goto exit_free_capability;
 
        resource->hwmon_dev = hwmon_device_register(&device->dev);
        if (IS_ERR(resource->hwmon_dev)) {
@@ -896,6 +896,8 @@ static int acpi_power_meter_add(struct acpi_device *device)
 
 exit_remove:
        remove_attrs(resource);
+exit_free_capability:
+       free_capabilities(resource);
 exit_free:
        kfree(resource);
 exit:
index e95b742..2960374 100644 (file)
@@ -362,7 +362,7 @@ static struct platform_driver amd_energy_driver = {
 static struct platform_device *amd_energy_platdev;
 
 static const struct x86_cpu_id cpu_ids[] __initconst = {
-       X86_MATCH_VENDOR_FAM(AMD, 0x17, NULL),
+       X86_MATCH_VENDOR_FAM_MODEL(AMD, 0x17, 0x31, NULL),
        {}
 };
 MODULE_DEVICE_TABLE(x86cpu, cpu_ids);
index 33fb548..3d8239f 100644 (file)
@@ -851,6 +851,8 @@ static int aspeed_create_fan(struct device *dev,
        ret = of_property_read_u32(child, "reg", &pwm_port);
        if (ret)
                return ret;
+       if (pwm_port >= ARRAY_SIZE(pwm_port_params))
+               return -EINVAL;
        aspeed_create_pwm_port(priv, (u8)pwm_port);
 
        ret = of_property_count_u8_elems(child, "cooling-levels");
index 1a9772f..94698ca 100644 (file)
@@ -64,7 +64,7 @@ static const struct pvt_sensor_info pvt_info[] = {
  *     48380,
  * where T = [-48380, 147438] mC and N = [0, 1023].
  */
-static const struct pvt_poly poly_temp_to_N = {
+static const struct pvt_poly __maybe_unused poly_temp_to_N = {
        .total_divider = 10000,
        .terms = {
                {4, 18322, 10000, 10000},
@@ -96,7 +96,7 @@ static const struct pvt_poly poly_N_to_temp = {
  * N = (18658e-3*V - 11572) / 10,
  * V = N * 10^5 / 18658 + 11572 * 10^4 / 18658.
  */
-static const struct pvt_poly poly_volt_to_N = {
+static const struct pvt_poly __maybe_unused poly_volt_to_N = {
        .total_divider = 10,
        .terms = {
                {1, 18658, 1000, 1},
@@ -300,12 +300,12 @@ static irqreturn_t pvt_soft_isr(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-inline umode_t pvt_limit_is_visible(enum pvt_sensor_type type)
+static inline umode_t pvt_limit_is_visible(enum pvt_sensor_type type)
 {
        return 0644;
 }
 
-inline umode_t pvt_alarm_is_visible(enum pvt_sensor_type type)
+static inline umode_t pvt_alarm_is_visible(enum pvt_sensor_type type)
 {
        return 0444;
 }
@@ -462,12 +462,12 @@ static irqreturn_t pvt_hard_isr(int irq, void *data)
 
 #define pvt_soft_isr NULL
 
-inline umode_t pvt_limit_is_visible(enum pvt_sensor_type type)
+static inline umode_t pvt_limit_is_visible(enum pvt_sensor_type type)
 {
        return 0;
 }
 
-inline umode_t pvt_alarm_is_visible(enum pvt_sensor_type type)
+static inline umode_t pvt_alarm_is_visible(enum pvt_sensor_type type)
 {
        return 0;
 }
index 0d4f3d9..72c7603 100644 (file)
@@ -285,6 +285,42 @@ static int drivetemp_get_scttemp(struct drivetemp_data *st, u32 attr, long *val)
        return err;
 }
 
+static const char * const sct_avoid_models[] = {
+/*
+ * These drives will have WRITE FPDMA QUEUED command timeouts and sometimes just
+ * freeze until power-cycled under heavy write loads when their temperature is
+ * getting polled in SCT mode. The SMART mode seems to be fine, though.
+ *
+ * While only the 3 TB model (DT01ACA3) was actually caught exhibiting the
+ * problem let's play safe here to avoid data corruption and ban the whole
+ * DT01ACAx family.
+
+ * The models from this array are prefix-matched.
+ */
+       "TOSHIBA DT01ACA",
+};
+
+static bool drivetemp_sct_avoid(struct drivetemp_data *st)
+{
+       struct scsi_device *sdev = st->sdev;
+       unsigned int ctr;
+
+       if (!sdev->model)
+               return false;
+
+       /*
+        * The "model" field contains just the raw SCSI INQUIRY response
+        * "product identification" field, which has a width of 16 bytes.
+        * This field is space-filled, but is NOT NULL-terminated.
+        */
+       for (ctr = 0; ctr < ARRAY_SIZE(sct_avoid_models); ctr++)
+               if (!strncmp(sdev->model, sct_avoid_models[ctr],
+                            strlen(sct_avoid_models[ctr])))
+                       return true;
+
+       return false;
+}
+
 static int drivetemp_identify_sata(struct drivetemp_data *st)
 {
        struct scsi_device *sdev = st->sdev;
@@ -326,6 +362,13 @@ static int drivetemp_identify_sata(struct drivetemp_data *st)
        /* bail out if this is not a SATA device */
        if (!is_ata || !is_sata)
                return -ENODEV;
+
+       if (have_sct && drivetemp_sct_avoid(st)) {
+               dev_notice(&sdev->sdev_gendev,
+                          "will avoid using SCT for temperature monitoring\n");
+               have_sct = false;
+       }
+
        if (!have_sct)
                goto skip_sct;
 
index 491a570..924c02c 100644 (file)
@@ -443,7 +443,7 @@ static ssize_t pwm1_enable_store(struct device *dev,
        }
 
        result = read_u8_from_i2c(client, REG_FAN_CONF1, &conf_reg);
-       if (result) {
+       if (result < 0) {
                count = result;
                goto err;
        }
index 743752a..64122eb 100644 (file)
@@ -38,8 +38,9 @@ static const u8 MAX6697_REG_CRIT[] = {
  * Map device tree / platform data register bit map to chip bit map.
  * Applies to alert register and over-temperature register.
  */
-#define MAX6697_MAP_BITS(reg)  ((((reg) & 0x7e) >> 1) | \
+#define MAX6697_ALERT_MAP_BITS(reg)    ((((reg) & 0x7e) >> 1) | \
                                 (((reg) & 0x01) << 6) | ((reg) & 0x80))
+#define MAX6697_OVERT_MAP_BITS(reg) (((reg) >> 1) | (((reg) & 0x01) << 7))
 
 #define MAX6697_REG_STAT(n)            (0x44 + (n))
 
@@ -562,12 +563,12 @@ static int max6697_init_chip(struct max6697_data *data,
                return ret;
 
        ret = i2c_smbus_write_byte_data(client, MAX6697_REG_ALERT_MASK,
-                                       MAX6697_MAP_BITS(pdata->alert_mask));
+                               MAX6697_ALERT_MAP_BITS(pdata->alert_mask));
        if (ret < 0)
                return ret;
 
        ret = i2c_smbus_write_byte_data(client, MAX6697_REG_OVERT_MASK,
-                               MAX6697_MAP_BITS(pdata->over_temperature_mask));
+                       MAX6697_OVERT_MAP_BITS(pdata->over_temperature_mask));
        if (ret < 0)
                return ret;
 
index e7e1ddc..750b087 100644 (file)
@@ -786,13 +786,13 @@ static const char *const nct6798_temp_label[] = {
        "Agent1 Dimm1",
        "BYTE_TEMP0",
        "BYTE_TEMP1",
-       "",
-       "",
+       "PECI Agent 0 Calibration",     /* undocumented */
+       "PECI Agent 1 Calibration",     /* undocumented */
        "",
        "Virtual_TEMP"
 };
 
-#define NCT6798_TEMP_MASK      0x8fff0ffe
+#define NCT6798_TEMP_MASK      0xbfff0ffe
 #define NCT6798_VIRT_TEMP_MASK 0x80000c00
 
 /* NCT6102D/NCT6106D specific data */
index a337195..ea516ce 100644 (file)
@@ -71,7 +71,7 @@ config SENSORS_IR35221
          Infineon IR35221 controller.
 
          This driver can also be built as a module. If so, the module will
-         be called ir35521.
+         be called ir35221.
 
 config SENSORS_IR38064
        tristate "Infineon IR38064"
index e25f541..1931757 100644 (file)
@@ -465,6 +465,7 @@ MODULE_DEVICE_TABLE(i2c, adm1275_id);
 static int adm1275_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
+       s32 (*config_read_fn)(const struct i2c_client *client, u8 reg);
        u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1];
        int config, device_config;
        int ret;
@@ -510,11 +511,16 @@ static int adm1275_probe(struct i2c_client *client,
                           "Device mismatch: Configured %s, detected %s\n",
                           id->name, mid->name);
 
-       config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG);
+       if (mid->driver_data == adm1272 || mid->driver_data == adm1278 ||
+           mid->driver_data == adm1293 || mid->driver_data == adm1294)
+               config_read_fn = i2c_smbus_read_word_data;
+       else
+               config_read_fn = i2c_smbus_read_byte_data;
+       config = config_read_fn(client, ADM1275_PMON_CONFIG);
        if (config < 0)
                return config;
 
-       device_config = i2c_smbus_read_byte_data(client, ADM1275_DEVICE_CONFIG);
+       device_config = config_read_fn(client, ADM1275_DEVICE_CONFIG);
        if (device_config < 0)
                return device_config;
 
index a420877..2191575 100644 (file)
@@ -1869,7 +1869,7 @@ static int pmbus_add_fan_ctrl(struct i2c_client *client,
        struct pmbus_sensor *sensor;
 
        sensor = pmbus_add_sensor(data, "fan", "target", index, page,
-                                 PMBUS_VIRT_FAN_TARGET_1 + id, 0xff, PSC_FAN,
+                                 0xff, PMBUS_VIRT_FAN_TARGET_1 + id, PSC_FAN,
                                  false, false, true);
 
        if (!sensor)
@@ -1880,14 +1880,14 @@ static int pmbus_add_fan_ctrl(struct i2c_client *client,
                return 0;
 
        sensor = pmbus_add_sensor(data, "pwm", NULL, index, page,
-                                 PMBUS_VIRT_PWM_1 + id, 0xff, PSC_PWM,
+                                 0xff, PMBUS_VIRT_PWM_1 + id, PSC_PWM,
                                  false, false, true);
 
        if (!sensor)
                return -ENOMEM;
 
        sensor = pmbus_add_sensor(data, "pwm", "enable", index, page,
-                                 PMBUS_VIRT_PWM_ENABLE_1 + id, 0xff, PSC_PWM,
+                                 0xff, PMBUS_VIRT_PWM_ENABLE_1 + id, PSC_PWM,
                                  true, false, false);
 
        if (!sensor)
@@ -1929,7 +1929,7 @@ static int pmbus_add_fan_attributes(struct i2c_client *client,
                                continue;
 
                        if (pmbus_add_sensor(data, "fan", "input", index,
-                                            page, pmbus_fan_registers[f], 0xff,
+                                            page, 0xff, pmbus_fan_registers[f],
                                             PSC_FAN, true, true, true) == NULL)
                                return -ENOMEM;
 
index 286d3cf..d421e69 100644 (file)
@@ -147,7 +147,7 @@ static enum hwmon_sensor_types scmi_types[] = {
        [ENERGY] = hwmon_energy,
 };
 
-static u32 hwmon_attributes[] = {
+static u32 hwmon_attributes[hwmon_max] = {
        [hwmon_chip] = HWMON_C_REGISTER_TZ,
        [hwmon_temp] = HWMON_T_INPUT | HWMON_T_LABEL,
        [hwmon_in] = HWMON_I_INPUT | HWMON_I_LABEL,
index 40387d5..3ccc703 100644 (file)
@@ -747,17 +747,50 @@ static int cti_dying_cpu(unsigned int cpu)
        return 0;
 }
 
+static int cti_pm_setup(struct cti_drvdata *drvdata)
+{
+       int ret;
+
+       if (drvdata->ctidev.cpu == -1)
+               return 0;
+
+       if (nr_cti_cpu)
+               goto done;
+
+       cpus_read_lock();
+       ret = cpuhp_setup_state_nocalls_cpuslocked(
+                       CPUHP_AP_ARM_CORESIGHT_CTI_STARTING,
+                       "arm/coresight_cti:starting",
+                       cti_starting_cpu, cti_dying_cpu);
+       if (ret) {
+               cpus_read_unlock();
+               return ret;
+       }
+
+       ret = cpu_pm_register_notifier(&cti_cpu_pm_nb);
+       cpus_read_unlock();
+       if (ret) {
+               cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_CTI_STARTING);
+               return ret;
+       }
+
+done:
+       nr_cti_cpu++;
+       cti_cpu_drvdata[drvdata->ctidev.cpu] = drvdata;
+
+       return 0;
+}
+
 /* release PM registrations */
 static void cti_pm_release(struct cti_drvdata *drvdata)
 {
-       if (drvdata->ctidev.cpu >= 0) {
-               if (--nr_cti_cpu == 0) {
-                       cpu_pm_unregister_notifier(&cti_cpu_pm_nb);
+       if (drvdata->ctidev.cpu == -1)
+               return;
 
-                       cpuhp_remove_state_nocalls(
-                               CPUHP_AP_ARM_CORESIGHT_CTI_STARTING);
-               }
-               cti_cpu_drvdata[drvdata->ctidev.cpu] = NULL;
+       cti_cpu_drvdata[drvdata->ctidev.cpu] = NULL;
+       if (--nr_cti_cpu == 0) {
+               cpu_pm_unregister_notifier(&cti_cpu_pm_nb);
+               cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_CTI_STARTING);
        }
 }
 
@@ -823,19 +856,14 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
 
        /* driver data*/
        drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
-       if (!drvdata) {
-               ret = -ENOMEM;
-               dev_info(dev, "%s, mem err\n", __func__);
-               goto err_out;
-       }
+       if (!drvdata)
+               return -ENOMEM;
 
        /* Validity for the resource is already checked by the AMBA core */
        base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(base)) {
-               ret = PTR_ERR(base);
-               dev_err(dev, "%s, remap err\n", __func__);
-               goto err_out;
-       }
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
        drvdata->base = base;
 
        dev_set_drvdata(dev, drvdata);
@@ -854,8 +882,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
        pdata = coresight_cti_get_platform_data(dev);
        if (IS_ERR(pdata)) {
                dev_err(dev, "coresight_cti_get_platform_data err\n");
-               ret =  PTR_ERR(pdata);
-               goto err_out;
+               return  PTR_ERR(pdata);
        }
 
        /* default to powered - could change on PM notifications */
@@ -867,35 +894,20 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
                                               drvdata->ctidev.cpu);
        else
                cti_desc.name = coresight_alloc_device_name(&cti_sys_devs, dev);
-       if (!cti_desc.name) {
-               ret = -ENOMEM;
-               goto err_out;
-       }
+       if (!cti_desc.name)
+               return -ENOMEM;
 
        /* setup CPU power management handling for CPU bound CTI devices. */
-       if (drvdata->ctidev.cpu >= 0) {
-               cti_cpu_drvdata[drvdata->ctidev.cpu] = drvdata;
-               if (!nr_cti_cpu++) {
-                       cpus_read_lock();
-                       ret = cpuhp_setup_state_nocalls_cpuslocked(
-                               CPUHP_AP_ARM_CORESIGHT_CTI_STARTING,
-                               "arm/coresight_cti:starting",
-                               cti_starting_cpu, cti_dying_cpu);
-
-                       if (!ret)
-                               ret = cpu_pm_register_notifier(&cti_cpu_pm_nb);
-                       cpus_read_unlock();
-                       if (ret)
-                               goto err_out;
-               }
-       }
+       ret = cti_pm_setup(drvdata);
+       if (ret)
+               return ret;
 
        /* create dynamic attributes for connections */
        ret = cti_create_cons_sysfs(dev, drvdata);
        if (ret) {
                dev_err(dev, "%s: create dynamic sysfs entries failed\n",
                        cti_desc.name);
-               goto err_out;
+               goto pm_release;
        }
 
        /* set up coresight component description */
@@ -908,7 +920,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
        drvdata->csdev = coresight_register(&cti_desc);
        if (IS_ERR(drvdata->csdev)) {
                ret = PTR_ERR(drvdata->csdev);
-               goto err_out;
+               goto pm_release;
        }
 
        /* add to list of CTI devices */
@@ -927,7 +939,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
        dev_info(&drvdata->csdev->dev, "CTI initialized\n");
        return 0;
 
-err_out:
+pm_release:
        cti_pm_release(drvdata);
        return ret;
 }
index 747afc8..0c35cd5 100644 (file)
@@ -1388,18 +1388,57 @@ static struct notifier_block etm4_cpu_pm_nb = {
        .notifier_call = etm4_cpu_pm_notify,
 };
 
-static int etm4_cpu_pm_register(void)
+/* Setup PM. Called with cpus locked. Deals with error conditions and counts */
+static int etm4_pm_setup_cpuslocked(void)
 {
-       if (IS_ENABLED(CONFIG_CPU_PM))
-               return cpu_pm_register_notifier(&etm4_cpu_pm_nb);
+       int ret;
 
-       return 0;
+       if (etm4_count++)
+               return 0;
+
+       ret = cpu_pm_register_notifier(&etm4_cpu_pm_nb);
+       if (ret)
+               goto reduce_count;
+
+       ret = cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ARM_CORESIGHT_STARTING,
+                                                  "arm/coresight4:starting",
+                                                  etm4_starting_cpu, etm4_dying_cpu);
+
+       if (ret)
+               goto unregister_notifier;
+
+       ret = cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ONLINE_DYN,
+                                                  "arm/coresight4:online",
+                                                  etm4_online_cpu, NULL);
+
+       /* HP dyn state ID returned in ret on success */
+       if (ret > 0) {
+               hp_online = ret;
+               return 0;
+       }
+
+       /* failed dyn state - remove others */
+       cpuhp_remove_state_nocalls_cpuslocked(CPUHP_AP_ARM_CORESIGHT_STARTING);
+
+unregister_notifier:
+       cpu_pm_unregister_notifier(&etm4_cpu_pm_nb);
+
+reduce_count:
+       --etm4_count;
+       return ret;
 }
 
-static void etm4_cpu_pm_unregister(void)
+static void etm4_pm_clear(void)
 {
-       if (IS_ENABLED(CONFIG_CPU_PM))
-               cpu_pm_unregister_notifier(&etm4_cpu_pm_nb);
+       if (--etm4_count != 0)
+               return;
+
+       cpu_pm_unregister_notifier(&etm4_cpu_pm_nb);
+       cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING);
+       if (hp_online) {
+               cpuhp_remove_state_nocalls(hp_online);
+               hp_online = 0;
+       }
 }
 
 static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
@@ -1453,24 +1492,15 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
                                etm4_init_arch_data,  drvdata, 1))
                dev_err(dev, "ETM arch init failed\n");
 
-       if (!etm4_count++) {
-               cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ARM_CORESIGHT_STARTING,
-                                                    "arm/coresight4:starting",
-                                                    etm4_starting_cpu, etm4_dying_cpu);
-               ret = cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ONLINE_DYN,
-                                                          "arm/coresight4:online",
-                                                          etm4_online_cpu, NULL);
-               if (ret < 0)
-                       goto err_arch_supported;
-               hp_online = ret;
+       ret = etm4_pm_setup_cpuslocked();
+       cpus_read_unlock();
 
-               ret = etm4_cpu_pm_register();
-               if (ret)
-                       goto err_arch_supported;
+       /* etm4_pm_setup_cpuslocked() does its own cleanup - exit on error */
+       if (ret) {
+               etmdrvdata[drvdata->cpu] = NULL;
+               return ret;
        }
 
-       cpus_read_unlock();
-
        if (etm4_arch_supported(drvdata->arch) == false) {
                ret = -EINVAL;
                goto err_arch_supported;
@@ -1517,13 +1547,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
 
 err_arch_supported:
        etmdrvdata[drvdata->cpu] = NULL;
-       if (--etm4_count == 0) {
-               etm4_cpu_pm_unregister();
-
-               cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING);
-               if (hp_online)
-                       cpuhp_remove_state_nocalls(hp_online);
-       }
+       etm4_pm_clear();
        return ret;
 }
 
index ca232ec..c9ac3dc 100644 (file)
@@ -1021,15 +1021,30 @@ int intel_th_set_output(struct intel_th_device *thdev,
 {
        struct intel_th_device *hub = to_intel_th_hub(thdev);
        struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver);
+       int ret;
 
        /* In host mode, this is up to the external debugger, do nothing. */
        if (hub->host_mode)
                return 0;
 
-       if (!hubdrv->set_output)
-               return -ENOTSUPP;
+       /*
+        * hub is instantiated together with the source device that
+        * calls here, so guaranteed to be present.
+        */
+       hubdrv = to_intel_th_driver(hub->dev.driver);
+       if (!hubdrv || !try_module_get(hubdrv->driver.owner))
+               return -EINVAL;
+
+       if (!hubdrv->set_output) {
+               ret = -ENOTSUPP;
+               goto out;
+       }
+
+       ret = hubdrv->set_output(hub, master);
 
-       return hubdrv->set_output(hub, master);
+out:
+       module_put(hubdrv->driver.owner);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(intel_th_set_output);
 
index 7ccac74..21fdf0b 100644 (file)
@@ -233,11 +233,21 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa0a6),
                .driver_data = (kernel_ulong_t)&intel_th_2x,
        },
+       {
+               /* Tiger Lake PCH-H */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x43a6),
+               .driver_data = (kernel_ulong_t)&intel_th_2x,
+       },
        {
                /* Jasper Lake PCH */
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4da6),
                .driver_data = (kernel_ulong_t)&intel_th_2x,
        },
+       {
+               /* Jasper Lake CPU */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4e29),
+               .driver_data = (kernel_ulong_t)&intel_th_2x,
+       },
        {
                /* Elkhart Lake CPU */
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4529),
@@ -248,6 +258,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4b26),
                .driver_data = (kernel_ulong_t)&intel_th_2x,
        },
+       {
+               /* Emmitsburg PCH */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1bcc),
+               .driver_data = (kernel_ulong_t)&intel_th_2x,
+       },
        { 0 },
 };
 
index 3a1f4e6..a1529f5 100644 (file)
@@ -161,9 +161,7 @@ static int sth_stm_link(struct stm_data *stm_data, unsigned int master,
 {
        struct sth_device *sth = container_of(stm_data, struct sth_device, stm);
 
-       intel_th_set_output(to_intel_th_device(sth->dev), master);
-
-       return 0;
+       return intel_th_set_output(to_intel_th_device(sth->dev), master);
 }
 
 static int intel_th_sw_init(struct sth_device *sth)
index 4f932a4..603b4a9 100644 (file)
@@ -34,7 +34,7 @@ struct stp_policy_node {
        unsigned int            first_channel;
        unsigned int            last_channel;
        /* this is the one that's exposed to the attributes */
-       unsigned char           priv[0];
+       unsigned char           priv[];
 };
 
 void *stp_policy_node_priv(struct stp_policy_node *pn)
index 3569439..a9be49f 100644 (file)
@@ -23,7 +23,7 @@ void *stp_policy_node_priv(struct stp_policy_node *pn);
 
 struct stp_master {
        unsigned int    nr_free;
-       unsigned long   chan_map[0];
+       unsigned long   chan_map[];
 };
 
 struct stm_device {
@@ -42,7 +42,7 @@ struct stm_device {
        const struct config_item_type           *pdrv_node_type;
        /* master allocation */
        spinlock_t              mc_lock;
-       struct stp_master       *masters[0];
+       struct stp_master       *masters[];
 };
 
 #define to_stm_device(_d)                              \
index ef39c83..bae1dc0 100644 (file)
@@ -113,11 +113,18 @@ config I2C_STUB
 
 config I2C_SLAVE
        bool "I2C slave support"
+       help
+         This enables Linux to act as an I2C slave device. Note that your I2C
+         bus master driver also needs to support this functionality. Please
+         read Documentation/i2c/slave-interface.rst for further details.
 
 if I2C_SLAVE
 
 config I2C_SLAVE_EEPROM
        tristate "I2C eeprom slave driver"
+       help
+         This backend makes Linux behave like an I2C EEPROM. Please read
+         Documentation/i2c/slave-eeprom-backend.rst for further details.
 
 endif
 
index 7f10312..3889787 100644 (file)
@@ -314,7 +314,8 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
                        DEB2("BUS ERROR - SDA Stuck low\n");
                        pca_reset(adap);
                        goto out;
-               case 0x90: /* Bus error - SCL stuck low */
+               case 0x78: /* Bus error - SCL stuck low (PCA9665) */
+               case 0x90: /* Bus error - SCL stuck low (PCA9564) */
                        DEB2("BUS ERROR - SCL Stuck low\n");
                        pca_reset(adap);
                        goto out;
index 4b72398..e4b7f2a 100644 (file)
@@ -421,20 +421,21 @@ static irqreturn_t cdns_i2c_master_isr(void *ptr)
                /* Read data if receive data valid is set */
                while (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) &
                       CDNS_I2C_SR_RXDV) {
-                       /*
-                        * Clear hold bit that was set for FIFO control if
-                        * RX data left is less than FIFO depth, unless
-                        * repeated start is selected.
-                        */
-                       if ((id->recv_count < CDNS_I2C_FIFO_DEPTH) &&
-                           !id->bus_hold_flag)
-                               cdns_i2c_clear_bus_hold(id);
-
                        if (id->recv_count > 0) {
                                *(id->p_recv_buf)++ =
                                        cdns_i2c_readreg(CDNS_I2C_DATA_OFFSET);
                                id->recv_count--;
                                id->curr_recv_count--;
+
+                               /*
+                                * Clear hold bit that was set for FIFO control
+                                * if RX data left is less than or equal to
+                                * FIFO DEPTH unless repeated start is selected
+                                */
+                               if (id->recv_count <= CDNS_I2C_FIFO_DEPTH &&
+                                   !id->bus_hold_flag)
+                                       cdns_i2c_clear_bus_hold(id);
+
                        } else {
                                dev_err(id->adap.dev.parent,
                                        "xfer_size reg rollover. xfer aborted!\n");
@@ -594,10 +595,8 @@ 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)  || id->bus_hold_flag)
+       if (id->recv_count > CDNS_I2C_FIFO_DEPTH)
                ctrl_reg |= CDNS_I2C_CR_HOLD;
-       else
-               ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD;
 
        cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
 
@@ -654,11 +653,8 @@ 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) || id->bus_hold_flag)
+       if (id->send_count > CDNS_I2C_FIFO_DEPTH)
                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 e3a8640..3c19aad 100644 (file)
@@ -286,10 +286,8 @@ int i2c_dw_acpi_configure(struct device *device)
 }
 EXPORT_SYMBOL_GPL(i2c_dw_acpi_configure);
 
-void i2c_dw_acpi_adjust_bus_speed(struct device *device)
+static u32 i2c_dw_acpi_round_bus_speed(struct device *device)
 {
-       struct dw_i2c_dev *dev = dev_get_drvdata(device);
-       struct i2c_timings *t = &dev->timings;
        u32 acpi_speed;
        int i;
 
@@ -300,9 +298,22 @@ void i2c_dw_acpi_adjust_bus_speed(struct device *device)
         */
        for (i = 0; i < ARRAY_SIZE(supported_speeds); i++) {
                if (acpi_speed >= supported_speeds[i])
-                       break;
+                       return supported_speeds[i];
        }
-       acpi_speed = i < ARRAY_SIZE(supported_speeds) ? supported_speeds[i] : 0;
+
+       return 0;
+}
+
+#else  /* CONFIG_ACPI */
+
+static inline u32 i2c_dw_acpi_round_bus_speed(struct device *device) { return 0; }
+
+#endif /* CONFIG_ACPI */
+
+void i2c_dw_adjust_bus_speed(struct dw_i2c_dev *dev)
+{
+       u32 acpi_speed = i2c_dw_acpi_round_bus_speed(dev->dev);
+       struct i2c_timings *t = &dev->timings;
 
        /*
         * Find bus speed from the "clock-frequency" device property, ACPI
@@ -315,9 +326,7 @@ void i2c_dw_acpi_adjust_bus_speed(struct device *device)
        else
                t->bus_freq_hz = I2C_MAX_FAST_MODE_FREQ;
 }
-EXPORT_SYMBOL_GPL(i2c_dw_acpi_adjust_bus_speed);
-
-#endif /* CONFIG_ACPI */
+EXPORT_SYMBOL_GPL(i2c_dw_adjust_bus_speed);
 
 u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
 {
index 556673a..eb5ef4d 100644 (file)
@@ -361,11 +361,10 @@ static inline int i2c_dw_probe_lock_support(struct dw_i2c_dev *dev) { return 0;
 #endif
 
 int i2c_dw_validate_speed(struct dw_i2c_dev *dev);
+void i2c_dw_adjust_bus_speed(struct dw_i2c_dev *dev);
 
 #if IS_ENABLED(CONFIG_ACPI)
 int i2c_dw_acpi_configure(struct device *device);
-void i2c_dw_acpi_adjust_bus_speed(struct device *device);
 #else
 static inline int i2c_dw_acpi_configure(struct device *device) { return -ENODEV; }
-static inline void i2c_dw_acpi_adjust_bus_speed(struct device *device) {}
 #endif
index 947c096..8522134 100644 (file)
@@ -240,7 +240,7 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
                }
        }
 
-       i2c_dw_acpi_adjust_bus_speed(&pdev->dev);
+       i2c_dw_adjust_bus_speed(dev);
 
        if (has_acpi_companion(&pdev->dev))
                i2c_dw_acpi_configure(&pdev->dev);
index 0de4e30..a71bc58 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/clk-provider.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/dmi.h>
 #include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/i2c.h>
@@ -191,6 +192,17 @@ static int dw_i2c_plat_request_regs(struct dw_i2c_dev *dev)
        return ret;
 }
 
+static const struct dmi_system_id dw_i2c_hwmon_class_dmi[] = {
+       {
+               .ident = "Qtechnology QT5222",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Qtechnology"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "QT5222"),
+               },
+       },
+       { } /* terminate list */
+};
+
 static int dw_i2c_plat_probe(struct platform_device *pdev)
 {
        struct dw_i2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
@@ -228,7 +240,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
        else
                i2c_parse_fw_timings(&pdev->dev, t, false);
 
-       i2c_dw_acpi_adjust_bus_speed(&pdev->dev);
+       i2c_dw_adjust_bus_speed(dev);
 
        if (pdev->dev.of_node)
                dw_i2c_of_configure(pdev);
@@ -267,7 +279,8 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
 
        adap = &dev->adapter;
        adap->owner = THIS_MODULE;
-       adap->class = I2C_CLASS_DEPRECATED;
+       adap->class = dmi_check_system(dw_i2c_hwmon_class_dmi) ?
+                                       I2C_CLASS_HWMON : I2C_CLASS_DEPRECATED;
        ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev));
        adap->dev.of_node = pdev->dev.of_node;
        adap->nr = -1;
index bb810de..73f1396 100644 (file)
@@ -180,6 +180,7 @@ static const struct pci_device_id pch_pcidev_id[] = {
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_I2C), 1, },
        {0,}
 };
+MODULE_DEVICE_TABLE(pci, pch_pcidev_id);
 
 static irqreturn_t pch_i2c_handler(int irq, void *pData);
 
index e0c2569..977d6f5 100644 (file)
@@ -98,7 +98,7 @@
 #define I2C_STAT_DAT_REQ       BIT(25)
 #define I2C_STAT_CMD_COMP      BIT(24)
 #define I2C_STAT_STOP_ERR      BIT(23)
-#define I2C_STAT_MAX_PORT      GENMASK(19, 16)
+#define I2C_STAT_MAX_PORT      GENMASK(22, 16)
 #define I2C_STAT_ANY_INT       BIT(15)
 #define I2C_STAT_SCL_IN                BIT(11)
 #define I2C_STAT_SDA_IN                BIT(10)
index 2fd717d..71d7bae 100644 (file)
@@ -337,9 +337,9 @@ static int mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv)
                if (priv->smbus_block && (val & MLXCPLD_I2C_SMBUS_BLK_BIT)) {
                        mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_NUM_DAT_REG,
                                              &datalen, 1);
-                       if (unlikely(datalen > (I2C_SMBUS_BLOCK_MAX + 1))) {
+                       if (unlikely(datalen > I2C_SMBUS_BLOCK_MAX)) {
                                dev_err(priv->dev, "Incorrect smbus block read message len\n");
-                               return -E2BIG;
+                               return -EPROTO;
                        }
                } else {
                        datalen = priv->xfer.data_len;
index 18d1e4f..7f13082 100644 (file)
@@ -367,7 +367,6 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
                geni_se_select_mode(se, GENI_SE_FIFO);
 
        writel_relaxed(len, se->base + SE_I2C_RX_TRANS_LEN);
-       geni_se_setup_m_cmd(se, I2C_READ, m_param);
 
        if (dma_buf && geni_se_rx_dma_prep(se, dma_buf, len, &rx_dma)) {
                geni_se_select_mode(se, GENI_SE_FIFO);
@@ -375,6 +374,8 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
                dma_buf = NULL;
        }
 
+       geni_se_setup_m_cmd(se, I2C_READ, m_param);
+
        time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT);
        if (!time_left)
                geni_i2c_abort_xfer(gi2c);
@@ -408,7 +409,6 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
                geni_se_select_mode(se, GENI_SE_FIFO);
 
        writel_relaxed(len, se->base + SE_I2C_TX_TRANS_LEN);
-       geni_se_setup_m_cmd(se, I2C_WRITE, m_param);
 
        if (dma_buf && geni_se_tx_dma_prep(se, dma_buf, len, &tx_dma)) {
                geni_se_select_mode(se, GENI_SE_FIFO);
@@ -416,6 +416,8 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
                dma_buf = NULL;
        }
 
+       geni_se_setup_m_cmd(se, I2C_WRITE, m_param);
+
        if (!dma_buf) /* Get FIFO IRQ */
                writel_relaxed(1, se->base + SE_GENI_TX_WATERMARK_REG);
 
index a45c4bf..2e3e1bb 100644 (file)
@@ -868,6 +868,7 @@ static int rcar_unreg_slave(struct i2c_client *slave)
        /* disable irqs and ensure none is running before clearing ptr */
        rcar_i2c_write(priv, ICSIER, 0);
        rcar_i2c_write(priv, ICSCR, 0);
+       rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */
 
        synchronize_irq(priv->irq);
        priv->slave = NULL;
@@ -969,6 +970,8 @@ static int rcar_i2c_probe(struct platform_device *pdev)
        if (ret < 0)
                goto out_pm_put;
 
+       rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */
+
        if (priv->devtype == I2C_RCAR_GEN3) {
                priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
                if (!IS_ERR(priv->rstc)) {
index d1f278f..26f03a1 100644 (file)
@@ -815,31 +815,6 @@ out_err_silent:
 }
 EXPORT_SYMBOL_GPL(i2c_new_client_device);
 
-/**
- * i2c_new_device - instantiate an i2c device
- * @adap: the adapter managing the device
- * @info: describes one I2C device; bus_num is ignored
- * Context: can sleep
- *
- * This deprecated function has the same functionality as
- * @i2c_new_client_device, it just returns NULL instead of an ERR_PTR in case of
- * an error for compatibility with current I2C API. It will be removed once all
- * users are converted.
- *
- * This returns the new i2c client, which may be saved for later use with
- * i2c_unregister_device(); or NULL to indicate an error.
- */
-struct i2c_client *
-i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
-{
-       struct i2c_client *ret;
-
-       ret = i2c_new_client_device(adap, info);
-       return IS_ERR(ret) ? NULL : ret;
-}
-EXPORT_SYMBOL_GPL(i2c_new_device);
-
-
 /**
  * i2c_unregister_device - reverse effect of i2c_new_*_device()
  * @client: value returned from i2c_new_*_device()
index 5427f04..1589179 100644 (file)
@@ -18,10 +18,8 @@ int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)
 {
        int ret;
 
-       if (!client || !slave_cb) {
-               WARN(1, "insufficient data\n");
+       if (WARN(IS_ERR_OR_NULL(client) || !slave_cb, "insufficient data\n"))
                return -EINVAL;
-       }
 
        if (!(client->flags & I2C_CLIENT_SLAVE))
                dev_warn(&client->dev, "%s: client slave flag not set. You might see address collisions\n",
@@ -60,6 +58,9 @@ int i2c_slave_unregister(struct i2c_client *client)
 {
        int ret;
 
+       if (IS_ERR_OR_NULL(client))
+               return -EINVAL;
+
        if (!client->adapter->algo->unreg_slave) {
                dev_err(&client->dev, "%s: not supported by adapter\n", __func__);
                return -EOPNOTSUPP;
index b34d2ff..f5c9787 100644 (file)
@@ -4,7 +4,7 @@
  *
  * This file contains the SMBus functions which are always included in the I2C
  * core because they can be emulated via I2C. SMBus specific extensions
- * (e.g. smbalert) are handled in a seperate i2c-smbus module.
+ * (e.g. smbalert) are handled in a separate i2c-smbus module.
  *
  * All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl>
  * SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and
@@ -495,6 +495,13 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
                        break;
                case I2C_SMBUS_BLOCK_DATA:
                case I2C_SMBUS_BLOCK_PROC_CALL:
+                       if (msg[1].buf[0] > I2C_SMBUS_BLOCK_MAX) {
+                               dev_err(&adapter->dev,
+                                       "Invalid block size returned: %d\n",
+                                       msg[1].buf[0]);
+                               status = -EPROTO;
+                               goto cleanup;
+                       }
                        for (i = 0; i < msg[1].buf[0] + 1; i++)
                                data->block[i] = msg[1].buf[i];
                        break;
index 00e100f..813bca7 100644 (file)
@@ -1685,10 +1685,13 @@ static int mma8452_probe(struct i2c_client *client,
 
        ret = mma8452_set_freefall_mode(data, false);
        if (ret < 0)
-               goto buffer_cleanup;
+               goto unregister_device;
 
        return 0;
 
+unregister_device:
+       iio_device_unregister(indio_dev);
+
 buffer_cleanup:
        iio_triggered_buffer_cleanup(indio_dev);
 
index f47606e..b33fe6c 100644 (file)
@@ -329,7 +329,7 @@ static int ad7780_probe(struct spi_device *spi)
 
        ret = ad7780_init_gpios(&spi->dev, st);
        if (ret)
-               goto error_cleanup_buffer_and_trigger;
+               return ret;
 
        st->reg = devm_regulator_get(&spi->dev, "avdd");
        if (IS_ERR(st->reg))
index c24c8da..7af8f05 100644 (file)
@@ -332,12 +332,12 @@ static struct adi_axi_adc_client *adi_axi_adc_attach_client(struct device *dev)
                if (cl->dev->of_node != cln)
                        continue;
 
-               if (!try_module_get(dev->driver->owner)) {
+               if (!try_module_get(cl->dev->driver->owner)) {
                        mutex_unlock(&registered_clients_lock);
                        return ERR_PTR(-ENODEV);
                }
 
-               get_device(dev);
+               get_device(cl->dev);
                cl->info = info;
                mutex_unlock(&registered_clients_lock);
                return cl;
index e9f87e4..a350762 100644 (file)
@@ -65,6 +65,7 @@ static const struct reg_field afe4403_reg_fields[] = {
  * @regulator: Pointer to the regulator for the IC
  * @trig: IIO trigger for this device
  * @irq: ADC_RDY line interrupt number
+ * @buffer: Used to construct data layout to push into IIO buffer.
  */
 struct afe4403_data {
        struct device *dev;
@@ -74,6 +75,8 @@ struct afe4403_data {
        struct regulator *regulator;
        struct iio_trigger *trig;
        int irq;
+       /* Ensure suitable alignment for timestamp */
+       s32 buffer[8] __aligned(8);
 };
 
 enum afe4403_chan_id {
@@ -309,7 +312,6 @@ static irqreturn_t afe4403_trigger_handler(int irq, void *private)
        struct iio_dev *indio_dev = pf->indio_dev;
        struct afe4403_data *afe = iio_priv(indio_dev);
        int ret, bit, i = 0;
-       s32 buffer[8];
        u8 tx[4] = {AFE440X_CONTROL0, 0x0, 0x0, AFE440X_CONTROL0_READ};
        u8 rx[3];
 
@@ -326,7 +328,7 @@ static irqreturn_t afe4403_trigger_handler(int irq, void *private)
                if (ret)
                        goto err;
 
-               buffer[i++] = get_unaligned_be24(&rx[0]);
+               afe->buffer[i++] = get_unaligned_be24(&rx[0]);
        }
 
        /* Disable reading from the device */
@@ -335,7 +337,8 @@ static irqreturn_t afe4403_trigger_handler(int irq, void *private)
        if (ret)
                goto err;
 
-       iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp);
+       iio_push_to_buffers_with_timestamp(indio_dev, afe->buffer,
+                                          pf->timestamp);
 err:
        iio_trigger_notify_done(indio_dev->trig);
 
index e728bbb..cebb1fd 100644 (file)
@@ -83,6 +83,7 @@ static const struct reg_field afe4404_reg_fields[] = {
  * @regulator: Pointer to the regulator for the IC
  * @trig: IIO trigger for this device
  * @irq: ADC_RDY line interrupt number
+ * @buffer: Used to construct a scan to push to the iio buffer.
  */
 struct afe4404_data {
        struct device *dev;
@@ -91,6 +92,7 @@ struct afe4404_data {
        struct regulator *regulator;
        struct iio_trigger *trig;
        int irq;
+       s32 buffer[10] __aligned(8);
 };
 
 enum afe4404_chan_id {
@@ -328,17 +330,17 @@ static irqreturn_t afe4404_trigger_handler(int irq, void *private)
        struct iio_dev *indio_dev = pf->indio_dev;
        struct afe4404_data *afe = iio_priv(indio_dev);
        int ret, bit, i = 0;
-       s32 buffer[10];
 
        for_each_set_bit(bit, indio_dev->active_scan_mask,
                         indio_dev->masklength) {
                ret = regmap_read(afe->regmap, afe4404_channel_values[bit],
-                                 &buffer[i++]);
+                                 &afe->buffer[i++]);
                if (ret)
                        goto err;
        }
 
-       iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp);
+       iio_push_to_buffers_with_timestamp(indio_dev, afe->buffer,
+                                          pf->timestamp);
 err:
        iio_trigger_notify_done(indio_dev->trig);
 
index 7ecd2ff..665eb7e 100644 (file)
@@ -38,6 +38,11 @@ struct hdc100x_data {
 
        /* integration time of the sensor */
        int adc_int_us[2];
+       /* Ensure natural alignment of timestamp */
+       struct {
+               __be16 channels[2];
+               s64 ts __aligned(8);
+       } scan;
 };
 
 /* integration time in us */
@@ -322,7 +327,6 @@ static irqreturn_t hdc100x_trigger_handler(int irq, void *p)
        struct i2c_client *client = data->client;
        int delay = data->adc_int_us[0] + data->adc_int_us[1];
        int ret;
-       s16 buf[8];  /* 2x s16 + padding + 8 byte timestamp */
 
        /* dual read starts at temp register */
        mutex_lock(&data->lock);
@@ -333,13 +337,13 @@ static irqreturn_t hdc100x_trigger_handler(int irq, void *p)
        }
        usleep_range(delay, delay + 1000);
 
-       ret = i2c_master_recv(client, (u8 *)buf, 4);
+       ret = i2c_master_recv(client, (u8 *)data->scan.channels, 4);
        if (ret < 0) {
                dev_err(&client->dev, "cannot read sensor data\n");
                goto err;
        }
 
-       iio_push_to_buffers_with_timestamp(indio_dev, buf,
+       iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
                                           iio_get_time_ns(indio_dev));
 err:
        mutex_unlock(&data->lock);
index 7d6771f..b2eb5ab 100644 (file)
@@ -14,8 +14,6 @@
 
 #include <linux/iio/iio.h>
 
-#define HTS221_DATA_SIZE       2
-
 enum hts221_sensor_type {
        HTS221_SENSOR_H,
        HTS221_SENSOR_T,
@@ -39,6 +37,11 @@ struct hts221_hw {
 
        bool enabled;
        u8 odr;
+       /* Ensure natural alignment of timestamp */
+       struct {
+               __le16 channels[2];
+               s64 ts __aligned(8);
+       } scan;
 };
 
 extern const struct dev_pm_ops hts221_pm_ops;
index 9fb3f33..ba7d413 100644 (file)
@@ -160,7 +160,6 @@ static const struct iio_buffer_setup_ops hts221_buffer_ops = {
 
 static irqreturn_t hts221_buffer_handler_thread(int irq, void *p)
 {
-       u8 buffer[ALIGN(2 * HTS221_DATA_SIZE, sizeof(s64)) + sizeof(s64)];
        struct iio_poll_func *pf = p;
        struct iio_dev *iio_dev = pf->indio_dev;
        struct hts221_hw *hw = iio_priv(iio_dev);
@@ -170,18 +169,20 @@ static irqreturn_t hts221_buffer_handler_thread(int irq, void *p)
        /* humidity data */
        ch = &iio_dev->channels[HTS221_SENSOR_H];
        err = regmap_bulk_read(hw->regmap, ch->address,
-                              buffer, HTS221_DATA_SIZE);
+                              &hw->scan.channels[0],
+                              sizeof(hw->scan.channels[0]));
        if (err < 0)
                goto out;
 
        /* temperature data */
        ch = &iio_dev->channels[HTS221_SENSOR_T];
        err = regmap_bulk_read(hw->regmap, ch->address,
-                              buffer + HTS221_DATA_SIZE, HTS221_DATA_SIZE);
+                              &hw->scan.channels[1],
+                              sizeof(hw->scan.channels[1]));
        if (err < 0)
                goto out;
 
-       iio_push_to_buffers_with_timestamp(iio_dev, buffer,
+       iio_push_to_buffers_with_timestamp(iio_dev, &hw->scan,
                                           iio_get_time_ns(iio_dev));
 
 out:
index 1527f01..3525333 100644 (file)
@@ -130,6 +130,8 @@ static const char * const iio_modifier_names[] = {
        [IIO_MOD_PM2P5] = "pm2p5",
        [IIO_MOD_PM4] = "pm4",
        [IIO_MOD_PM10] = "pm10",
+       [IIO_MOD_ETHANOL] = "ethanol",
+       [IIO_MOD_H2] = "h2",
 };
 
 /* relies on pairs of these shared then separate */
index 810fdfd..91c3935 100644 (file)
@@ -192,6 +192,11 @@ struct ak8974 {
        bool drdy_irq;
        struct completion drdy_complete;
        bool drdy_active_low;
+       /* Ensure timestamp is naturally aligned */
+       struct {
+               __le16 channels[3];
+               s64 ts __aligned(8);
+       } scan;
 };
 
 static const char ak8974_reg_avdd[] = "avdd";
@@ -657,7 +662,6 @@ static void ak8974_fill_buffer(struct iio_dev *indio_dev)
 {
        struct ak8974 *ak8974 = iio_priv(indio_dev);
        int ret;
-       __le16 hw_values[8]; /* Three axes + 64bit padding */
 
        pm_runtime_get_sync(&ak8974->i2c->dev);
        mutex_lock(&ak8974->lock);
@@ -667,13 +671,13 @@ static void ak8974_fill_buffer(struct iio_dev *indio_dev)
                dev_err(&ak8974->i2c->dev, "error triggering measure\n");
                goto out_unlock;
        }
-       ret = ak8974_getresult(ak8974, hw_values);
+       ret = ak8974_getresult(ak8974, ak8974->scan.channels);
        if (ret) {
                dev_err(&ak8974->i2c->dev, "error getting measures\n");
                goto out_unlock;
        }
 
-       iio_push_to_buffers_with_timestamp(indio_dev, hw_values,
+       iio_push_to_buffers_with_timestamp(indio_dev, &ak8974->scan,
                                           iio_get_time_ns(indio_dev));
 
  out_unlock:
@@ -862,19 +866,21 @@ static int ak8974_probe(struct i2c_client *i2c,
        ak8974->map = devm_regmap_init_i2c(i2c, &ak8974_regmap_config);
        if (IS_ERR(ak8974->map)) {
                dev_err(&i2c->dev, "failed to allocate register map\n");
+               pm_runtime_put_noidle(&i2c->dev);
+               pm_runtime_disable(&i2c->dev);
                return PTR_ERR(ak8974->map);
        }
 
        ret = ak8974_set_power(ak8974, AK8974_PWR_ON);
        if (ret) {
                dev_err(&i2c->dev, "could not power on\n");
-               goto power_off;
+               goto disable_pm;
        }
 
        ret = ak8974_detect(ak8974);
        if (ret) {
                dev_err(&i2c->dev, "neither AK8974 nor AMI30x found\n");
-               goto power_off;
+               goto disable_pm;
        }
 
        ret = ak8974_selftest(ak8974);
@@ -884,14 +890,9 @@ static int ak8974_probe(struct i2c_client *i2c,
        ret = ak8974_reset(ak8974);
        if (ret) {
                dev_err(&i2c->dev, "AK8974 reset failed\n");
-               goto power_off;
+               goto disable_pm;
        }
 
-       pm_runtime_set_autosuspend_delay(&i2c->dev,
-                                        AK8974_AUTOSUSPEND_DELAY);
-       pm_runtime_use_autosuspend(&i2c->dev);
-       pm_runtime_put(&i2c->dev);
-
        indio_dev->dev.parent = &i2c->dev;
        switch (ak8974->variant) {
        case AK8974_WHOAMI_VALUE_AMI306:
@@ -957,6 +958,11 @@ no_irq:
                goto cleanup_buffer;
        }
 
+       pm_runtime_set_autosuspend_delay(&i2c->dev,
+                                        AK8974_AUTOSUSPEND_DELAY);
+       pm_runtime_use_autosuspend(&i2c->dev);
+       pm_runtime_put(&i2c->dev);
+
        return 0;
 
 cleanup_buffer:
@@ -965,7 +971,6 @@ disable_pm:
        pm_runtime_put_noidle(&i2c->dev);
        pm_runtime_disable(&i2c->dev);
        ak8974_set_power(ak8974, AK8974_PWR_OFF);
-power_off:
        regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs);
 
        return ret;
index 2f598ad..f5db9fa 100644 (file)
@@ -212,16 +212,21 @@ static irqreturn_t ms5611_trigger_handler(int irq, void *p)
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
        struct ms5611_state *st = iio_priv(indio_dev);
-       s32 buf[4]; /* s32 (pressure) + s32 (temp) + 2 * s32 (timestamp) */
+       /* Ensure buffer elements are naturally aligned */
+       struct {
+               s32 channels[2];
+               s64 ts __aligned(8);
+       } scan;
        int ret;
 
        mutex_lock(&st->lock);
-       ret = ms5611_read_temp_and_pressure(indio_dev, &buf[1], &buf[0]);
+       ret = ms5611_read_temp_and_pressure(indio_dev, &scan.channels[1],
+                                           &scan.channels[0]);
        mutex_unlock(&st->lock);
        if (ret < 0)
                goto err;
 
-       iio_push_to_buffers_with_timestamp(indio_dev, buf,
+       iio_push_to_buffers_with_timestamp(indio_dev, &scan,
                                           iio_get_time_ns(indio_dev));
 
 err:
index 37fe851..799a8dc 100644 (file)
@@ -665,8 +665,10 @@ static int zpa2326_resume(const struct iio_dev *indio_dev)
        int err;
 
        err = pm_runtime_get_sync(indio_dev->dev.parent);
-       if (err < 0)
+       if (err < 0) {
+               pm_runtime_put(indio_dev->dev.parent);
                return err;
+       }
 
        if (err > 0) {
                /*
index 9ce787e..dc0558b 100644 (file)
@@ -918,6 +918,7 @@ static void cm_free_work(struct cm_work *work)
 
 static void cm_queue_work_unlock(struct cm_id_private *cm_id_priv,
                                 struct cm_work *work)
+       __releases(&cm_id_priv->lock)
 {
        bool immediate;
 
@@ -3675,10 +3676,12 @@ static int cm_send_sidr_rep_locked(struct cm_id_private *cm_id_priv,
                return ret;
        }
        cm_id_priv->id.state = IB_CM_IDLE;
+       spin_lock_irq(&cm.lock);
        if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node)) {
                rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
                RB_CLEAR_NODE(&cm_id_priv->sidr_id_node);
        }
+       spin_unlock_irq(&cm.lock);
        return 0;
 }
 
index 3d7cc9f..c30cf53 100644 (file)
@@ -1624,6 +1624,8 @@ static struct rdma_id_private *cma_find_listener(
 {
        struct rdma_id_private *id_priv, *id_priv_dev;
 
+       lockdep_assert_held(&lock);
+
        if (!bind_list)
                return ERR_PTR(-EINVAL);
 
@@ -1670,6 +1672,7 @@ cma_ib_id_from_event(struct ib_cm_id *cm_id,
                }
        }
 
+       mutex_lock(&lock);
        /*
         * Net namespace might be getting deleted while route lookup,
         * cm_id lookup is in progress. Therefore, perform netdevice
@@ -1711,6 +1714,7 @@ cma_ib_id_from_event(struct ib_cm_id *cm_id,
        id_priv = cma_find_listener(bind_list, cm_id, ib_event, req, *net_dev);
 err:
        rcu_read_unlock();
+       mutex_unlock(&lock);
        if (IS_ERR(id_priv) && *net_dev) {
                dev_put(*net_dev);
                *net_dev = NULL;
@@ -2492,6 +2496,8 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv,
        struct net *net = id_priv->id.route.addr.dev_addr.net;
        int ret;
 
+       lockdep_assert_held(&lock);
+
        if (cma_family(id_priv) == AF_IB && !rdma_cap_ib_cm(cma_dev->device, 1))
                return;
 
@@ -3342,6 +3348,8 @@ static void cma_bind_port(struct rdma_bind_list *bind_list,
        u64 sid, mask;
        __be16 port;
 
+       lockdep_assert_held(&lock);
+
        addr = cma_src_addr(id_priv);
        port = htons(bind_list->port);
 
@@ -3370,6 +3378,8 @@ static int cma_alloc_port(enum rdma_ucm_port_space ps,
        struct rdma_bind_list *bind_list;
        int ret;
 
+       lockdep_assert_held(&lock);
+
        bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL);
        if (!bind_list)
                return -ENOMEM;
@@ -3396,6 +3406,8 @@ static int cma_port_is_unique(struct rdma_bind_list *bind_list,
        struct sockaddr  *saddr = cma_src_addr(id_priv);
        __be16 dport = cma_port(daddr);
 
+       lockdep_assert_held(&lock);
+
        hlist_for_each_entry(cur_id, &bind_list->owners, node) {
                struct sockaddr  *cur_daddr = cma_dst_addr(cur_id);
                struct sockaddr  *cur_saddr = cma_src_addr(cur_id);
@@ -3435,6 +3447,8 @@ static int cma_alloc_any_port(enum rdma_ucm_port_space ps,
        unsigned int rover;
        struct net *net = id_priv->id.route.addr.dev_addr.net;
 
+       lockdep_assert_held(&lock);
+
        inet_get_local_port_range(net, &low, &high);
        remaining = (high - low) + 1;
        rover = prandom_u32() % remaining + low;
@@ -3482,6 +3496,8 @@ static int cma_check_port(struct rdma_bind_list *bind_list,
        struct rdma_id_private *cur_id;
        struct sockaddr *addr, *cur_addr;
 
+       lockdep_assert_held(&lock);
+
        addr = cma_src_addr(id_priv);
        hlist_for_each_entry(cur_id, &bind_list->owners, node) {
                if (id_priv == cur_id)
@@ -3512,6 +3528,8 @@ static int cma_use_port(enum rdma_ucm_port_space ps,
        unsigned short snum;
        int ret;
 
+       lockdep_assert_held(&lock);
+
        snum = ntohs(cma_port(cma_src_addr(id_priv)));
        if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
                return -EACCES;
index 2257d7f..738d1fa 100644 (file)
@@ -202,7 +202,7 @@ static int __rdma_counter_unbind_qp(struct ib_qp *qp)
        return ret;
 }
 
-static void counter_history_stat_update(const struct rdma_counter *counter)
+static void counter_history_stat_update(struct rdma_counter *counter)
 {
        struct ib_device *dev = counter->device;
        struct rdma_port_counter *port_counter;
@@ -212,6 +212,8 @@ static void counter_history_stat_update(const struct rdma_counter *counter)
        if (!port_counter->hstats)
                return;
 
+       rdma_counter_query_stats(counter);
+
        for (i = 0; i < counter->stats->num_counters; i++)
                port_counter->hstats->value[i] += counter->stats->value[i];
 }
index 655795b..513825e 100644 (file)
@@ -72,6 +72,15 @@ static void rdma_dim_init(struct ib_cq *cq)
        INIT_WORK(&dim->work, ib_cq_rdma_dim_work);
 }
 
+static void rdma_dim_destroy(struct ib_cq *cq)
+{
+       if (!cq->dim)
+               return;
+
+       cancel_work_sync(&cq->dim->work);
+       kfree(cq->dim);
+}
+
 static int __poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc)
 {
        int rc;
@@ -266,6 +275,7 @@ struct ib_cq *__ib_alloc_cq_user(struct ib_device *dev, void *private,
        return cq;
 
 out_destroy_cq:
+       rdma_dim_destroy(cq);
        rdma_restrack_del(&cq->res);
        cq->device->ops.destroy_cq(cq, udata);
 out_free_wc:
@@ -331,12 +341,10 @@ void ib_free_cq_user(struct ib_cq *cq, struct ib_udata *udata)
                WARN_ON_ONCE(1);
        }
 
+       rdma_dim_destroy(cq);
        trace_cq_free(cq);
        rdma_restrack_del(&cq->res);
        cq->device->ops.destroy_cq(cq, udata);
-       if (cq->dim)
-               cancel_work_sync(&cq->dim->work);
-       kfree(cq->dim);
        kfree(cq->wc);
        kfree(cq);
 }
index 186e0d6..a09f8e3 100644 (file)
@@ -509,10 +509,10 @@ static void unregister_mad_agent(struct ib_mad_agent_private *mad_agent_priv)
        xa_erase(&ib_mad_clients, mad_agent_priv->agent.hi_tid);
 
        flush_workqueue(port_priv->wq);
-       ib_cancel_rmpp_recvs(mad_agent_priv);
 
        deref_mad_agent(mad_agent_priv);
        wait_for_completion(&mad_agent_priv->comp);
+       ib_cancel_rmpp_recvs(mad_agent_priv);
 
        ib_mad_agent_security_cleanup(&mad_agent_priv->agent);
 
@@ -2718,6 +2718,7 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info,
                                                 DMA_FROM_DEVICE);
                if (unlikely(ib_dma_mapping_error(qp_info->port_priv->device,
                                                  sg_list.addr))) {
+                       kfree(mad_priv);
                        ret = -ENOMEM;
                        break;
                }
index 38de494..6d3ed7c 100644 (file)
@@ -470,40 +470,46 @@ static struct ib_uobject *
 alloc_begin_fd_uobject(const struct uverbs_api_object *obj,
                       struct uverbs_attr_bundle *attrs)
 {
-       const struct uverbs_obj_fd_type *fd_type =
-               container_of(obj->type_attrs, struct uverbs_obj_fd_type, type);
+       const struct uverbs_obj_fd_type *fd_type;
        int new_fd;
-       struct ib_uobject *uobj;
+       struct ib_uobject *uobj, *ret;
        struct file *filp;
 
+       uobj = alloc_uobj(attrs, obj);
+       if (IS_ERR(uobj))
+               return uobj;
+
+       fd_type =
+               container_of(obj->type_attrs, struct uverbs_obj_fd_type, type);
        if (WARN_ON(fd_type->fops->release != &uverbs_uobject_fd_release &&
-                   fd_type->fops->release != &uverbs_async_event_release))
-               return ERR_PTR(-EINVAL);
+                   fd_type->fops->release != &uverbs_async_event_release)) {
+               ret = ERR_PTR(-EINVAL);
+               goto err_fd;
+       }
 
        new_fd = get_unused_fd_flags(O_CLOEXEC);
-       if (new_fd < 0)
-               return ERR_PTR(new_fd);
-
-       uobj = alloc_uobj(attrs, obj);
-       if (IS_ERR(uobj))
+       if (new_fd < 0) {
+               ret = ERR_PTR(new_fd);
                goto err_fd;
+       }
 
        /* Note that uverbs_uobject_fd_release() is called during abort */
        filp = anon_inode_getfile(fd_type->name, fd_type->fops, NULL,
                                  fd_type->flags);
        if (IS_ERR(filp)) {
-               uverbs_uobject_put(uobj);
-               uobj = ERR_CAST(filp);
-               goto err_fd;
+               ret = ERR_CAST(filp);
+               goto err_getfile;
        }
        uobj->object = filp;
 
        uobj->id = new_fd;
        return uobj;
 
-err_fd:
+err_getfile:
        put_unused_fd(new_fd);
-       return uobj;
+err_fd:
+       uverbs_uobject_put(uobj);
+       return ret;
 }
 
 struct ib_uobject *rdma_alloc_begin_uobject(const struct uverbs_api_object *obj,
@@ -643,9 +649,6 @@ void rdma_alloc_commit_uobject(struct ib_uobject *uobj,
 {
        struct ib_uverbs_file *ufile = attrs->ufile;
 
-       /* alloc_commit consumes the uobj kref */
-       uobj->uapi_object->type_class->alloc_commit(uobj);
-
        /* kref is held so long as the uobj is on the uobj list. */
        uverbs_uobject_get(uobj);
        spin_lock_irq(&ufile->uobjects_lock);
@@ -655,6 +658,9 @@ void rdma_alloc_commit_uobject(struct ib_uobject *uobj,
        /* matches atomic_set(-1) in alloc_uobj */
        atomic_set(&uobj->usecnt, 0);
 
+       /* alloc_commit consumes the uobj kref */
+       uobj->uapi_object->type_class->alloc_commit(uobj);
+
        /* Matches the down_read in rdma_alloc_begin_uobject */
        up_read(&ufile->hw_destroy_rwsem);
 }
index a2ed09a..8c930bf 100644 (file)
@@ -829,13 +829,20 @@ static int ib_nl_get_path_rec_attrs_len(ib_sa_comp_mask comp_mask)
        return len;
 }
 
-static int ib_nl_send_msg(struct ib_sa_query *query, gfp_t gfp_mask)
+static int ib_nl_make_request(struct ib_sa_query *query, gfp_t gfp_mask)
 {
        struct sk_buff *skb = NULL;
        struct nlmsghdr *nlh;
        void *data;
        struct ib_sa_mad *mad;
        int len;
+       unsigned long flags;
+       unsigned long delay;
+       gfp_t gfp_flag;
+       int ret;
+
+       INIT_LIST_HEAD(&query->list);
+       query->seq = (u32)atomic_inc_return(&ib_nl_sa_request_seq);
 
        mad = query->mad_buf->mad;
        len = ib_nl_get_path_rec_attrs_len(mad->sa_hdr.comp_mask);
@@ -860,36 +867,25 @@ static int ib_nl_send_msg(struct ib_sa_query *query, gfp_t gfp_mask)
        /* Repair the nlmsg header length */
        nlmsg_end(skb, nlh);
 
-       return rdma_nl_multicast(&init_net, skb, RDMA_NL_GROUP_LS, gfp_mask);
-}
+       gfp_flag = ((gfp_mask & GFP_ATOMIC) == GFP_ATOMIC) ? GFP_ATOMIC :
+               GFP_NOWAIT;
 
-static int ib_nl_make_request(struct ib_sa_query *query, gfp_t gfp_mask)
-{
-       unsigned long flags;
-       unsigned long delay;
-       int ret;
+       spin_lock_irqsave(&ib_nl_request_lock, flags);
+       ret = rdma_nl_multicast(&init_net, skb, RDMA_NL_GROUP_LS, gfp_flag);
 
-       INIT_LIST_HEAD(&query->list);
-       query->seq = (u32)atomic_inc_return(&ib_nl_sa_request_seq);
+       if (ret)
+               goto out;
 
-       /* Put the request on the list first.*/
-       spin_lock_irqsave(&ib_nl_request_lock, flags);
+       /* Put the request on the list.*/
        delay = msecs_to_jiffies(sa_local_svc_timeout_ms);
        query->timeout = delay + jiffies;
        list_add_tail(&query->list, &ib_nl_request_list);
        /* Start the timeout if this is the only request */
        if (ib_nl_request_list.next == &query->list)
                queue_delayed_work(ib_nl_wq, &ib_nl_timed_work, delay);
-       spin_unlock_irqrestore(&ib_nl_request_lock, flags);
 
-       ret = ib_nl_send_msg(query, gfp_mask);
-       if (ret) {
-               ret = -EIO;
-               /* Remove the request */
-               spin_lock_irqsave(&ib_nl_request_lock, flags);
-               list_del(&query->list);
-               spin_unlock_irqrestore(&ib_nl_request_lock, flags);
-       }
+out:
+       spin_unlock_irqrestore(&ib_nl_request_lock, flags);
 
        return ret;
 }
index 5b87eee..d03daca 100644 (file)
@@ -1084,6 +1084,8 @@ static ssize_t ucma_connect(struct ucma_file *file, const char __user *inbuf,
        size_t in_size;
        int ret;
 
+       if (in_len < offsetofend(typeof(cmd), reserved))
+               return -EINVAL;
        in_size = min_t(size_t, in_len, sizeof(cmd));
        if (copy_from_user(&cmd, inbuf, in_size))
                return -EFAULT;
@@ -1141,6 +1143,8 @@ static ssize_t ucma_accept(struct ucma_file *file, const char __user *inbuf,
        size_t in_size;
        int ret;
 
+       if (in_len < offsetofend(typeof(cmd), reserved))
+               return -EINVAL;
        in_size = min_t(size_t, in_len, sizeof(cmd));
        if (copy_from_user(&cmd, inbuf, in_size))
                return -EFAULT;
index 08313f7..7dd0824 100644 (file)
@@ -212,6 +212,7 @@ int efa_query_device(struct ib_device *ibdev,
        props->max_send_sge = dev_attr->max_sq_sge;
        props->max_recv_sge = dev_attr->max_rq_sge;
        props->max_sge_rd = dev_attr->max_wr_rdma_sge;
+       props->max_pkeys = 1;
 
        if (udata && udata->outlen) {
                resp.max_sq_sge = dev_attr->max_sq_sge;
index 4633a0c..2ced236 100644 (file)
@@ -985,15 +985,10 @@ static ssize_t qsfp2_debugfs_read(struct file *file, char __user *buf,
 static int __i2c_debugfs_open(struct inode *in, struct file *fp, u32 target)
 {
        struct hfi1_pportdata *ppd;
-       int ret;
 
        ppd = private2ppd(fp);
 
-       ret = acquire_chip_resource(ppd->dd, i2c_target(target), 0);
-       if (ret) /* failed - release the module */
-               module_put(THIS_MODULE);
-
-       return ret;
+       return acquire_chip_resource(ppd->dd, i2c_target(target), 0);
 }
 
 static int i2c1_debugfs_open(struct inode *in, struct file *fp)
@@ -1013,7 +1008,6 @@ static int __i2c_debugfs_release(struct inode *in, struct file *fp, u32 target)
        ppd = private2ppd(fp);
 
        release_chip_resource(ppd->dd, i2c_target(target));
-       module_put(THIS_MODULE);
 
        return 0;
 }
@@ -1031,18 +1025,10 @@ static int i2c2_debugfs_release(struct inode *in, struct file *fp)
 static int __qsfp_debugfs_open(struct inode *in, struct file *fp, u32 target)
 {
        struct hfi1_pportdata *ppd;
-       int ret;
-
-       if (!try_module_get(THIS_MODULE))
-               return -ENODEV;
 
        ppd = private2ppd(fp);
 
-       ret = acquire_chip_resource(ppd->dd, i2c_target(target), 0);
-       if (ret) /* failed - release the module */
-               module_put(THIS_MODULE);
-
-       return ret;
+       return acquire_chip_resource(ppd->dd, i2c_target(target), 0);
 }
 
 static int qsfp1_debugfs_open(struct inode *in, struct file *fp)
@@ -1062,7 +1048,6 @@ static int __qsfp_debugfs_release(struct inode *in, struct file *fp, u32 target)
        ppd = private2ppd(fp);
 
        release_chip_resource(ppd->dd, i2c_target(target));
-       module_put(THIS_MODULE);
 
        return 0;
 }
index 5eed436..cb7ad12 100644 (file)
@@ -830,6 +830,29 @@ wq_error:
        return -ENOMEM;
 }
 
+/**
+ * destroy_workqueues - destroy per port workqueues
+ * @dd: the hfi1_ib device
+ */
+static void destroy_workqueues(struct hfi1_devdata *dd)
+{
+       int pidx;
+       struct hfi1_pportdata *ppd;
+
+       for (pidx = 0; pidx < dd->num_pports; ++pidx) {
+               ppd = dd->pport + pidx;
+
+               if (ppd->hfi1_wq) {
+                       destroy_workqueue(ppd->hfi1_wq);
+                       ppd->hfi1_wq = NULL;
+               }
+               if (ppd->link_wq) {
+                       destroy_workqueue(ppd->link_wq);
+                       ppd->link_wq = NULL;
+               }
+       }
+}
+
 /**
  * enable_general_intr() - Enable the IRQs that will be handled by the
  * general interrupt handler.
@@ -1103,15 +1126,10 @@ static void shutdown_device(struct hfi1_devdata *dd)
                 * We can't count on interrupts since we are stopping.
                 */
                hfi1_quiet_serdes(ppd);
-
-               if (ppd->hfi1_wq) {
-                       destroy_workqueue(ppd->hfi1_wq);
-                       ppd->hfi1_wq = NULL;
-               }
-               if (ppd->link_wq) {
-                       destroy_workqueue(ppd->link_wq);
-                       ppd->link_wq = NULL;
-               }
+               if (ppd->hfi1_wq)
+                       flush_workqueue(ppd->hfi1_wq);
+               if (ppd->link_wq)
+                       flush_workqueue(ppd->link_wq);
        }
        sdma_exit(dd);
 }
@@ -1756,6 +1774,7 @@ static void remove_one(struct pci_dev *pdev)
         * clear dma engines, etc.
         */
        shutdown_device(dd);
+       destroy_workqueues(dd);
 
        stop_timers(dd);
 
index 07847cb..d580aa1 100644 (file)
@@ -399,7 +399,7 @@ static inline void iowait_get_priority(struct iowait *w)
  * @wait_head: the wait queue
  *
  * This function is called to insert an iowait struct into a
- * wait queue after a resource (eg, sdma decriptor or pio
+ * wait queue after a resource (eg, sdma descriptor or pio
  * buffer) is run out.
  */
 static inline void iowait_queue(bool pkts_sent, struct iowait *w,
index 185c9b0..b8c9d0a 100644 (file)
@@ -67,6 +67,9 @@ struct hfi1_ipoib_circ_buf {
  * @sde: sdma engine
  * @tx_list: tx request list
  * @sent_txreqs: count of txreqs posted to sdma
+ * @stops: count of stops of queue
+ * @ring_full: ring has been filled
+ * @no_desc: descriptor shortage seen
  * @flow: tracks when list needs to be flushed for a flow change
  * @q_idx: ipoib Tx queue index
  * @pkts_sent: indicator packets have been sent from this queue
@@ -80,6 +83,9 @@ struct hfi1_ipoib_txq {
        struct sdma_engine *sde;
        struct list_head tx_list;
        u64 sent_txreqs;
+       atomic_t stops;
+       atomic_t ring_full;
+       atomic_t no_desc;
        union hfi1_ipoib_flow flow;
        u8 q_idx;
        bool pkts_sent;
index 883cb9d..9df292b 100644 (file)
@@ -55,23 +55,48 @@ static u64 hfi1_ipoib_txreqs(const u64 sent, const u64 completed)
        return sent - completed;
 }
 
-static void hfi1_ipoib_check_queue_depth(struct hfi1_ipoib_txq *txq)
+static u64 hfi1_ipoib_used(struct hfi1_ipoib_txq *txq)
 {
-       if (unlikely(hfi1_ipoib_txreqs(++txq->sent_txreqs,
-                                      atomic64_read(&txq->complete_txreqs)) >=
-           min_t(unsigned int, txq->priv->netdev->tx_queue_len,
-                 txq->tx_ring.max_items - 1)))
+       return hfi1_ipoib_txreqs(txq->sent_txreqs,
+                                atomic64_read(&txq->complete_txreqs));
+}
+
+static void hfi1_ipoib_stop_txq(struct hfi1_ipoib_txq *txq)
+{
+       if (atomic_inc_return(&txq->stops) == 1)
                netif_stop_subqueue(txq->priv->netdev, txq->q_idx);
 }
 
+static void hfi1_ipoib_wake_txq(struct hfi1_ipoib_txq *txq)
+{
+       if (atomic_dec_and_test(&txq->stops))
+               netif_wake_subqueue(txq->priv->netdev, txq->q_idx);
+}
+
+static uint hfi1_ipoib_ring_hwat(struct hfi1_ipoib_txq *txq)
+{
+       return min_t(uint, txq->priv->netdev->tx_queue_len,
+                    txq->tx_ring.max_items - 1);
+}
+
+static uint hfi1_ipoib_ring_lwat(struct hfi1_ipoib_txq *txq)
+{
+       return min_t(uint, txq->priv->netdev->tx_queue_len,
+                    txq->tx_ring.max_items) >> 1;
+}
+
+static void hfi1_ipoib_check_queue_depth(struct hfi1_ipoib_txq *txq)
+{
+       ++txq->sent_txreqs;
+       if (hfi1_ipoib_used(txq) >= hfi1_ipoib_ring_hwat(txq) &&
+           !atomic_xchg(&txq->ring_full, 1))
+               hfi1_ipoib_stop_txq(txq);
+}
+
 static void hfi1_ipoib_check_queue_stopped(struct hfi1_ipoib_txq *txq)
 {
        struct net_device *dev = txq->priv->netdev;
 
-       /* If the queue is already running just return */
-       if (likely(!__netif_subqueue_stopped(dev, txq->q_idx)))
-               return;
-
        /* If shutting down just return as queue state is irrelevant */
        if (unlikely(dev->reg_state != NETREG_REGISTERED))
                return;
@@ -86,11 +111,9 @@ static void hfi1_ipoib_check_queue_stopped(struct hfi1_ipoib_txq *txq)
         * Use the minimum of the current tx_queue_len or the rings max txreqs
         * to protect against ring overflow.
         */
-       if (hfi1_ipoib_txreqs(txq->sent_txreqs,
-                             atomic64_read(&txq->complete_txreqs))
-           < min_t(unsigned int, dev->tx_queue_len,
-                   txq->tx_ring.max_items) >> 1)
-               netif_wake_subqueue(dev, txq->q_idx);
+       if (hfi1_ipoib_used(txq) < hfi1_ipoib_ring_lwat(txq) &&
+           atomic_xchg(&txq->ring_full, 0))
+               hfi1_ipoib_wake_txq(txq);
 }
 
 static void hfi1_ipoib_free_tx(struct ipoib_txreq *tx, int budget)
@@ -364,11 +387,12 @@ static struct ipoib_txreq *hfi1_ipoib_send_dma_common(struct net_device *dev,
        if (unlikely(!tx))
                return ERR_PTR(-ENOMEM);
 
-       /* so that we can test if the sdma decriptors are there */
+       /* so that we can test if the sdma descriptors are there */
        tx->txreq.num_desc = 0;
        tx->priv = priv;
        tx->txq = txp->txq;
        tx->skb = skb;
+       INIT_LIST_HEAD(&tx->txreq.list);
 
        hfi1_ipoib_build_ib_tx_headers(tx, txp);
 
@@ -469,6 +493,7 @@ static int hfi1_ipoib_send_dma_single(struct net_device *dev,
 
        ret = hfi1_ipoib_submit_tx(txq, tx);
        if (likely(!ret)) {
+tx_ok:
                trace_sdma_output_ibhdr(tx->priv->dd,
                                        &tx->sdma_hdr.hdr,
                                        ib_is_sc5(txp->flow.sc5));
@@ -478,20 +503,8 @@ static int hfi1_ipoib_send_dma_single(struct net_device *dev,
 
        txq->pkts_sent = false;
 
-       if (ret == -EBUSY) {
-               list_add_tail(&tx->txreq.list, &txq->tx_list);
-
-               trace_sdma_output_ibhdr(tx->priv->dd,
-                                       &tx->sdma_hdr.hdr,
-                                       ib_is_sc5(txp->flow.sc5));
-               hfi1_ipoib_check_queue_depth(txq);
-               return NETDEV_TX_OK;
-       }
-
-       if (ret == -ECOMM) {
-               hfi1_ipoib_check_queue_depth(txq);
-               return NETDEV_TX_OK;
-       }
+       if (ret == -EBUSY || ret == -ECOMM)
+               goto tx_ok;
 
        sdma_txclean(priv->dd, &tx->txreq);
        dev_kfree_skb_any(skb);
@@ -509,9 +522,17 @@ static int hfi1_ipoib_send_dma_list(struct net_device *dev,
        struct ipoib_txreq *tx;
 
        /* Has the flow change ? */
-       if (txq->flow.as_int != txp->flow.as_int)
-               (void)hfi1_ipoib_flush_tx_list(dev, txq);
-
+       if (txq->flow.as_int != txp->flow.as_int) {
+               int ret;
+
+               ret = hfi1_ipoib_flush_tx_list(dev, txq);
+               if (unlikely(ret)) {
+                       if (ret == -EBUSY)
+                               ++dev->stats.tx_dropped;
+                       dev_kfree_skb_any(skb);
+                       return NETDEV_TX_OK;
+               }
+       }
        tx = hfi1_ipoib_send_dma_common(dev, skb, txp);
        if (IS_ERR(tx)) {
                int ret = PTR_ERR(tx);
@@ -610,10 +631,14 @@ static int hfi1_ipoib_sdma_sleep(struct sdma_engine *sde,
                        return -EAGAIN;
                }
 
-               netif_stop_subqueue(txq->priv->netdev, txq->q_idx);
-
-               if (list_empty(&txq->wait.list))
+               if (list_empty(&txreq->list))
+                       /* came from non-list submit */
+                       list_add_tail(&txreq->list, &txq->tx_list);
+               if (list_empty(&txq->wait.list)) {
+                       if (!atomic_xchg(&txq->no_desc, 1))
+                               hfi1_ipoib_stop_txq(txq);
                        iowait_queue(pkts_sent, wait->iow, &sde->dmawait);
+               }
 
                write_sequnlock(&sde->waitlock);
                return -EBUSY;
@@ -648,9 +673,9 @@ static void hfi1_ipoib_flush_txq(struct work_struct *work)
        struct net_device *dev = txq->priv->netdev;
 
        if (likely(dev->reg_state == NETREG_REGISTERED) &&
-           likely(__netif_subqueue_stopped(dev, txq->q_idx)) &&
            likely(!hfi1_ipoib_flush_tx_list(dev, txq)))
-               netif_wake_subqueue(dev, txq->q_idx);
+               if (atomic_xchg(&txq->no_desc, 0))
+                       hfi1_ipoib_wake_txq(txq);
 }
 
 int hfi1_ipoib_txreq_init(struct hfi1_ipoib_dev_priv *priv)
@@ -704,6 +729,9 @@ int hfi1_ipoib_txreq_init(struct hfi1_ipoib_dev_priv *priv)
                txq->sde = NULL;
                INIT_LIST_HEAD(&txq->tx_list);
                atomic64_set(&txq->complete_txreqs, 0);
+               atomic_set(&txq->stops, 0);
+               atomic_set(&txq->ring_full, 0);
+               atomic_set(&txq->no_desc, 0);
                txq->q_idx = i;
                txq->flow.tx_queue = 0xff;
                txq->flow.sc5 = 0xff;
@@ -769,7 +797,7 @@ static void hfi1_ipoib_drain_tx_list(struct hfi1_ipoib_txq *txq)
                atomic64_inc(complete_txreqs);
        }
 
-       if (hfi1_ipoib_txreqs(txq->sent_txreqs, atomic64_read(complete_txreqs)))
+       if (hfi1_ipoib_used(txq))
                dd_dev_warn(txq->priv->dd,
                            "txq %d not empty found %llu requests\n",
                            txq->q_idx,
index 63688e8..6d263c9 100644 (file)
@@ -373,7 +373,7 @@ void hfi1_netdev_free(struct hfi1_devdata *dd)
 {
        if (dd->dummy_netdev) {
                dd_dev_info(dd, "hfi1 netdev freed\n");
-               free_netdev(dd->dummy_netdev);
+               kfree(dd->dummy_netdev);
                dd->dummy_netdev = NULL;
        }
 }
index 0c2ae9f..be62284 100644 (file)
@@ -195,7 +195,7 @@ static inline int verbs_mtu_enum_to_int(struct ib_device *dev, enum ib_mtu mtu)
 {
        /* Constraining 10KB packets to 8KB packets */
        if (mtu == (enum ib_mtu)OPA_MTU_10240)
-               mtu = OPA_MTU_8192;
+               mtu = (enum ib_mtu)OPA_MTU_8192;
        return opa_mtu_enum_to_int((enum opa_mtu)mtu);
 }
 
@@ -367,7 +367,10 @@ bool _hfi1_schedule_send(struct rvt_qp *qp)
        struct hfi1_ibport *ibp =
                to_iport(qp->ibqp.device, qp->port_num);
        struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
-       struct hfi1_devdata *dd = dd_from_ibdev(qp->ibqp.device);
+       struct hfi1_devdata *dd = ppd->dd;
+
+       if (dd->flags & HFI1_SHUTDOWN)
+               return true;
 
        return iowait_schedule(&priv->s_iowait, ppd->hfi1_wq,
                               priv->s_sde ?
index 243b4ba..facff13 100644 (file)
@@ -5406,7 +5406,10 @@ static bool _hfi1_schedule_tid_send(struct rvt_qp *qp)
        struct hfi1_ibport *ibp =
                to_iport(qp->ibqp.device, qp->port_num);
        struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
-       struct hfi1_devdata *dd = dd_from_ibdev(qp->ibqp.device);
+       struct hfi1_devdata *dd = ppd->dd;
+
+       if ((dd->flags & HFI1_SHUTDOWN))
+               return true;
 
        return iowait_tid_schedule(&priv->s_iowait, ppd->hfi1_wq,
                                   priv->s_sde ?
index bfa6e08..d2d526c 100644 (file)
@@ -91,7 +91,7 @@ static inline struct verbs_txreq *get_txreq(struct hfi1_ibdev *dev,
        tx->mr = NULL;
        tx->sde = priv->s_sde;
        tx->psc = priv->s_sendcontext;
-       /* so that we can test if the sdma decriptors are there */
+       /* so that we can test if the sdma descriptors are there */
        tx->txreq.num_desc = 0;
        /* Set the header type */
        tx->phdr.hdr.hdr_type = priv->hdr_type;
index a77fa67..479fa55 100644 (file)
@@ -898,13 +898,14 @@ struct hns_roce_hw {
        int (*set_mac)(struct hns_roce_dev *hr_dev, u8 phy_port, u8 *addr);
        void (*set_mtu)(struct hns_roce_dev *hr_dev, u8 phy_port,
                        enum ib_mtu mtu);
-       int (*write_mtpt)(void *mb_buf, struct hns_roce_mr *mr,
-                         unsigned long mtpt_idx);
+       int (*write_mtpt)(struct hns_roce_dev *hr_dev, void *mb_buf,
+                         struct hns_roce_mr *mr, unsigned long mtpt_idx);
        int (*rereg_write_mtpt)(struct hns_roce_dev *hr_dev,
                                struct hns_roce_mr *mr, int flags, u32 pdn,
                                int mr_access_flags, u64 iova, u64 size,
                                void *mb_buf);
-       int (*frmr_write_mtpt)(void *mb_buf, struct hns_roce_mr *mr);
+       int (*frmr_write_mtpt)(struct hns_roce_dev *hr_dev, void *mb_buf,
+                              struct hns_roce_mr *mr);
        int (*mw_write_mtpt)(void *mb_buf, struct hns_roce_mw *mw);
        void (*write_cqc)(struct hns_roce_dev *hr_dev,
                          struct hns_roce_cq *hr_cq, void *mb_buf, u64 *mtts,
index d02207c..cf39f56 100644 (file)
@@ -1756,10 +1756,10 @@ static void hns_roce_v1_set_mtu(struct hns_roce_dev *hr_dev, u8 phy_port,
                   val);
 }
 
-static int hns_roce_v1_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,
+static int hns_roce_v1_write_mtpt(struct hns_roce_dev *hr_dev, void *mb_buf,
+                                 struct hns_roce_mr *mr,
                                  unsigned long mtpt_idx)
 {
-       struct hns_roce_dev *hr_dev = to_hr_dev(mr->ibmr.device);
        u64 pages[HNS_ROCE_MAX_INNER_MTPT_NUM] = { 0 };
        struct ib_device *ibdev = &hr_dev->ib_dev;
        struct hns_roce_v1_mpt_entry *mpt_entry;
index c597d72..0618ced 100644 (file)
@@ -910,7 +910,7 @@ static int hns_roce_v2_rst_process_cmd(struct hns_roce_dev *hr_dev)
        instance_stage = handle->rinfo.instance_state;
        reset_stage = handle->rinfo.reset_state;
        reset_cnt = ops->ae_dev_reset_cnt(handle);
-       hw_resetting = ops->get_hw_reset_stat(handle);
+       hw_resetting = ops->get_cmdq_stat(handle);
        sw_resetting = ops->ae_dev_resetting(handle);
 
        if (reset_cnt != hr_dev->reset_cnt)
@@ -2529,10 +2529,10 @@ static int hns_roce_v2_set_mac(struct hns_roce_dev *hr_dev, u8 phy_port,
        return hns_roce_cmq_send(hr_dev, &desc, 1);
 }
 
-static int set_mtpt_pbl(struct hns_roce_v2_mpt_entry *mpt_entry,
+static int set_mtpt_pbl(struct hns_roce_dev *hr_dev,
+                       struct hns_roce_v2_mpt_entry *mpt_entry,
                        struct hns_roce_mr *mr)
 {
-       struct hns_roce_dev *hr_dev = to_hr_dev(mr->ibmr.device);
        u64 pages[HNS_ROCE_V2_MAX_INNER_MTPT_NUM] = { 0 };
        struct ib_device *ibdev = &hr_dev->ib_dev;
        dma_addr_t pbl_ba;
@@ -2571,7 +2571,8 @@ static int set_mtpt_pbl(struct hns_roce_v2_mpt_entry *mpt_entry,
        return 0;
 }
 
-static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,
+static int hns_roce_v2_write_mtpt(struct hns_roce_dev *hr_dev,
+                                 void *mb_buf, struct hns_roce_mr *mr,
                                  unsigned long mtpt_idx)
 {
        struct hns_roce_v2_mpt_entry *mpt_entry;
@@ -2620,7 +2621,7 @@ static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,
        if (mr->type == MR_TYPE_DMA)
                return 0;
 
-       ret = set_mtpt_pbl(mpt_entry, mr);
+       ret = set_mtpt_pbl(hr_dev, mpt_entry, mr);
 
        return ret;
 }
@@ -2666,15 +2667,15 @@ static int hns_roce_v2_rereg_write_mtpt(struct hns_roce_dev *hr_dev,
                mr->iova = iova;
                mr->size = size;
 
-               ret = set_mtpt_pbl(mpt_entry, mr);
+               ret = set_mtpt_pbl(hr_dev, mpt_entry, mr);
        }
 
        return ret;
 }
 
-static int hns_roce_v2_frmr_write_mtpt(void *mb_buf, struct hns_roce_mr *mr)
+static int hns_roce_v2_frmr_write_mtpt(struct hns_roce_dev *hr_dev,
+                                      void *mb_buf, struct hns_roce_mr *mr)
 {
-       struct hns_roce_dev *hr_dev = to_hr_dev(mr->ibmr.device);
        struct ib_device *ibdev = &hr_dev->ib_dev;
        struct hns_roce_v2_mpt_entry *mpt_entry;
        dma_addr_t pbl_ba = 0;
@@ -3953,6 +3954,15 @@ static int config_qp_sq_buf(struct hns_roce_dev *hr_dev,
        return 0;
 }
 
+static inline enum ib_mtu get_mtu(struct ib_qp *ibqp,
+                                 const struct ib_qp_attr *attr)
+{
+       if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_UD)
+               return IB_MTU_4096;
+
+       return attr->path_mtu;
+}
+
 static int modify_qp_init_to_rtr(struct ib_qp *ibqp,
                                 const struct ib_qp_attr *attr, int attr_mask,
                                 struct hns_roce_v2_qp_context *context,
@@ -3964,6 +3974,7 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp,
        struct ib_device *ibdev = &hr_dev->ib_dev;
        dma_addr_t trrl_ba;
        dma_addr_t irrl_ba;
+       enum ib_mtu mtu;
        u8 port_num;
        u64 *mtts;
        u8 *dmac;
@@ -4061,23 +4072,23 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp,
        roce_set_field(qpc_mask->byte_52_udpspn_dmac, V2_QPC_BYTE_52_DMAC_M,
                       V2_QPC_BYTE_52_DMAC_S, 0);
 
-       /* mtu*(2^LP_PKTN_INI) should not bigger than 1 message length 64kb */
+       mtu = get_mtu(ibqp, attr);
+
+       if (attr_mask & IB_QP_PATH_MTU) {
+               roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M,
+                              V2_QPC_BYTE_24_MTU_S, mtu);
+               roce_set_field(qpc_mask->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M,
+                              V2_QPC_BYTE_24_MTU_S, 0);
+       }
+
+#define MAX_LP_MSG_LEN 65536
+       /* MTU*(2^LP_PKTN_INI) shouldn't be bigger than 64kb */
        roce_set_field(context->byte_56_dqpn_err, V2_QPC_BYTE_56_LP_PKTN_INI_M,
                       V2_QPC_BYTE_56_LP_PKTN_INI_S,
-                      ilog2(hr_dev->caps.max_sq_inline / IB_MTU_4096));
+                      ilog2(MAX_LP_MSG_LEN / ib_mtu_enum_to_int(mtu)));
        roce_set_field(qpc_mask->byte_56_dqpn_err, V2_QPC_BYTE_56_LP_PKTN_INI_M,
                       V2_QPC_BYTE_56_LP_PKTN_INI_S, 0);
 
-       if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_UD)
-               roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M,
-                              V2_QPC_BYTE_24_MTU_S, IB_MTU_4096);
-       else if (attr_mask & IB_QP_PATH_MTU)
-               roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M,
-                              V2_QPC_BYTE_24_MTU_S, attr->path_mtu);
-
-       roce_set_field(qpc_mask->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M,
-                      V2_QPC_BYTE_24_MTU_S, 0);
-
        roce_set_bit(qpc_mask->byte_108_rx_reqepsn,
                     V2_QPC_BYTE_108_RX_REQ_PSN_ERR_S, 0);
        roce_set_field(qpc_mask->byte_96_rx_reqmsn, V2_QPC_BYTE_96_RX_REQ_MSN_M,
index 4c0bbb1..6b226a5 100644 (file)
@@ -120,7 +120,7 @@ static int alloc_mr_pbl(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr,
 
        mr->pbl_hop_num = is_fast ? 1 : hr_dev->caps.pbl_hop_num;
        buf_attr.page_shift = is_fast ? PAGE_SHIFT :
-                             hr_dev->caps.pbl_buf_pg_sz + HNS_HW_PAGE_SHIFT;
+                             hr_dev->caps.pbl_buf_pg_sz + PAGE_SHIFT;
        buf_attr.region[0].size = length;
        buf_attr.region[0].hopnum = mr->pbl_hop_num;
        buf_attr.region_count = 1;
@@ -180,9 +180,10 @@ static int hns_roce_mr_enable(struct hns_roce_dev *hr_dev,
        }
 
        if (mr->type != MR_TYPE_FRMR)
-               ret = hr_dev->hw->write_mtpt(mailbox->buf, mr, mtpt_idx);
+               ret = hr_dev->hw->write_mtpt(hr_dev, mailbox->buf, mr,
+                                            mtpt_idx);
        else
-               ret = hr_dev->hw->frmr_write_mtpt(mailbox->buf, mr);
+               ret = hr_dev->hw->frmr_write_mtpt(hr_dev, mailbox->buf, mr);
        if (ret) {
                dev_err(dev, "Write mtpt fail!\n");
                goto err_page;
index 343a8b8..6f99ed0 100644 (file)
@@ -511,7 +511,7 @@ static int mlx5_query_port_roce(struct ib_device *device, u8 port_num,
                                           mdev_port_num);
        if (err)
                goto out;
-       ext = MLX5_CAP_PCAM_FEATURE(dev->mdev, ptys_extended_ethernet);
+       ext = !!MLX5_GET_ETH_PROTO(ptys_reg, out, true, eth_proto_capability);
        eth_prot_oper = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_oper);
 
        props->active_width     = IB_WIDTH_4X;
index 7d2ec9e..77dca1e 100644 (file)
@@ -601,6 +601,23 @@ void mlx5_ib_free_implicit_mr(struct mlx5_ib_mr *imr)
         */
        synchronize_srcu(&dev->odp_srcu);
 
+       /*
+        * All work on the prefetch list must be completed, xa_erase() prevented
+        * new work from being created.
+        */
+       wait_event(imr->q_deferred_work, !atomic_read(&imr->num_deferred_work));
+
+       /*
+        * At this point it is forbidden for any other thread to enter
+        * pagefault_mr() on this imr. It is already forbidden to call
+        * pagefault_mr() on an implicit child. Due to this additions to
+        * implicit_children are prevented.
+        */
+
+       /*
+        * Block destroy_unused_implicit_child_mr() from incrementing
+        * num_deferred_work.
+        */
        xa_lock(&imr->implicit_children);
        xa_for_each (&imr->implicit_children, idx, mtt) {
                __xa_erase(&imr->implicit_children, idx);
@@ -609,9 +626,8 @@ void mlx5_ib_free_implicit_mr(struct mlx5_ib_mr *imr)
        xa_unlock(&imr->implicit_children);
 
        /*
-        * num_deferred_work can only be incremented inside the odp_srcu, or
-        * under xa_lock while the child is in the xarray. Thus at this point
-        * it is only decreasing, and all work holding it is now on the wq.
+        * Wait for any concurrent destroy_unused_implicit_child_mr() to
+        * complete.
         */
        wait_event(imr->q_deferred_work, !atomic_read(&imr->num_deferred_work));
 
@@ -1781,9 +1797,7 @@ static bool init_prefetch_work(struct ib_pd *pd,
                work->frags[i].mr =
                        get_prefetchable_mr(pd, advice, sg_list[i].lkey);
                if (!work->frags[i].mr) {
-                       work->num_sge = i - 1;
-                       if (i)
-                               destroy_prefetch_work(work);
+                       work->num_sge = i;
                        return false;
                }
 
@@ -1849,6 +1863,7 @@ int mlx5_ib_advise_mr_prefetch(struct ib_pd *pd,
        srcu_key = srcu_read_lock(&dev->odp_srcu);
        if (!init_prefetch_work(pd, advice, pf_flags, work, sg_list, num_sge)) {
                srcu_read_unlock(&dev->odp_srcu, srcu_key);
+               destroy_prefetch_work(work);
                return -EINVAL;
        }
        queue_work(system_unbound_wq, &work->work);
index 81bf6b9..1225b8d 100644 (file)
@@ -1766,15 +1766,14 @@ err:
 }
 
 static void configure_requester_scat_cqe(struct mlx5_ib_dev *dev,
+                                        struct mlx5_ib_qp *qp,
                                         struct ib_qp_init_attr *init_attr,
-                                        struct mlx5_ib_create_qp *ucmd,
                                         void *qpc)
 {
        int scqe_sz;
        bool allow_scat_cqe = false;
 
-       if (ucmd)
-               allow_scat_cqe = ucmd->flags & MLX5_QP_FLAG_ALLOW_SCATTER_CQE;
+       allow_scat_cqe = qp->flags_en & MLX5_QP_FLAG_ALLOW_SCATTER_CQE;
 
        if (!allow_scat_cqe && init_attr->sq_sig_type != IB_SIGNAL_ALL_WR)
                return;
@@ -1853,8 +1852,6 @@ static int create_xrc_tgt_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
        u32 *in;
        int err;
 
-       mutex_init(&qp->mutex);
-
        if (attr->sq_sig_type == IB_SIGNAL_ALL_WR)
                qp->sq_signal_bits = MLX5_WQE_CTRL_CQ_UPDATE;
 
@@ -1862,7 +1859,7 @@ static int create_xrc_tgt_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
        if (!in)
                return -ENOMEM;
 
-       if (MLX5_CAP_GEN(mdev, ece_support))
+       if (MLX5_CAP_GEN(mdev, ece_support) && ucmd)
                MLX5_SET(create_qp_in, in, ece, ucmd->ece_options);
        qpc = MLX5_ADDR_OF(create_qp_in, in, qpc);
 
@@ -1938,7 +1935,6 @@ static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
        u32 *in;
        int err;
 
-       mutex_init(&qp->mutex);
        spin_lock_init(&qp->sq.lock);
        spin_lock_init(&qp->rq.lock);
 
@@ -2012,7 +2008,7 @@ static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
        }
        if ((qp->flags_en & MLX5_QP_FLAG_SCATTER_CQE) &&
            (qp->type == MLX5_IB_QPT_DCI || qp->type == IB_QPT_RC))
-               configure_requester_scat_cqe(dev, init_attr, ucmd, qpc);
+               configure_requester_scat_cqe(dev, qp, init_attr, qpc);
 
        if (qp->rq.wqe_cnt) {
                MLX5_SET(qpc, qpc, log_rq_stride, qp->rq.wqe_shift - 4);
@@ -2129,7 +2125,6 @@ static int create_kernel_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
        u32 *in;
        int err;
 
-       mutex_init(&qp->mutex);
        spin_lock_init(&qp->sq.lock);
        spin_lock_init(&qp->rq.lock);
 
@@ -2341,18 +2336,18 @@ static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
        unsigned long flags;
        int err;
 
-       if (qp->ibqp.rwq_ind_tbl) {
+       if (qp->is_rss) {
                destroy_rss_raw_qp_tir(dev, qp);
                return;
        }
 
-       base = (qp->ibqp.qp_type == IB_QPT_RAW_PACKET ||
+       base = (qp->type == IB_QPT_RAW_PACKET ||
                qp->flags & IB_QP_CREATE_SOURCE_QPN) ?
-              &qp->raw_packet_qp.rq.base :
-              &qp->trans_qp.base;
+                      &qp->raw_packet_qp.rq.base :
+                      &qp->trans_qp.base;
 
        if (qp->state != IB_QPS_RESET) {
-               if (qp->ibqp.qp_type != IB_QPT_RAW_PACKET &&
+               if (qp->type != IB_QPT_RAW_PACKET &&
                    !(qp->flags & IB_QP_CREATE_SOURCE_QPN)) {
                        err = mlx5_core_qp_modify(dev, MLX5_CMD_OP_2RST_QP, 0,
                                                  NULL, &base->mqp, NULL);
@@ -2368,8 +2363,8 @@ static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
                                     base->mqp.qpn);
        }
 
-       get_cqs(qp->ibqp.qp_type, qp->ibqp.send_cq, qp->ibqp.recv_cq,
-               &send_cq, &recv_cq);
+       get_cqs(qp->type, qp->ibqp.send_cq, qp->ibqp.recv_cq, &send_cq,
+               &recv_cq);
 
        spin_lock_irqsave(&dev->reset_flow_resource_lock, flags);
        mlx5_ib_lock_cqs(send_cq, recv_cq);
@@ -2391,7 +2386,7 @@ static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
        mlx5_ib_unlock_cqs(send_cq, recv_cq);
        spin_unlock_irqrestore(&dev->reset_flow_resource_lock, flags);
 
-       if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET ||
+       if (qp->type == IB_QPT_RAW_PACKET ||
            qp->flags & IB_QP_CREATE_SOURCE_QPN) {
                destroy_raw_packet_qp(dev, qp);
        } else {
@@ -2543,13 +2538,18 @@ static void process_vendor_flag(struct mlx5_ib_dev *dev, int *flags, int flag,
                return;
        }
 
-       if (flag == MLX5_QP_FLAG_SCATTER_CQE) {
+       switch (flag) {
+       case MLX5_QP_FLAG_SCATTER_CQE:
+       case MLX5_QP_FLAG_ALLOW_SCATTER_CQE:
                /*
-                * We don't return error if this flag was provided,
-                * and mlx5 doesn't have right capability.
-                */
-               *flags &= ~MLX5_QP_FLAG_SCATTER_CQE;
+                        * We don't return error if these flags were provided,
+                        * and mlx5 doesn't have right capability.
+                        */
+               *flags &= ~(MLX5_QP_FLAG_SCATTER_CQE |
+                           MLX5_QP_FLAG_ALLOW_SCATTER_CQE);
                return;
+       default:
+               break;
        }
        mlx5_ib_dbg(dev, "Vendor create QP flag 0x%X is not supported\n", flag);
 }
@@ -2589,6 +2589,8 @@ static int process_vendor_flags(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
        process_vendor_flag(dev, &flags, MLX5_QP_FLAG_SIGNATURE, true, qp);
        process_vendor_flag(dev, &flags, MLX5_QP_FLAG_SCATTER_CQE,
                            MLX5_CAP_GEN(mdev, sctr_data_cqe), qp);
+       process_vendor_flag(dev, &flags, MLX5_QP_FLAG_ALLOW_SCATTER_CQE,
+                           MLX5_CAP_GEN(mdev, sctr_data_cqe), qp);
 
        if (qp->type == IB_QPT_RAW_PACKET) {
                cond = MLX5_CAP_ETH(mdev, tunnel_stateless_vxlan) ||
@@ -2668,6 +2670,13 @@ static int process_create_flags(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
        if (qp_type == IB_QPT_RAW_PACKET && attr->rwq_ind_tbl)
                return (create_flags) ? -EINVAL : 0;
 
+       process_create_flag(dev, &create_flags, IB_QP_CREATE_NETIF_QP,
+                           mlx5_get_flow_namespace(dev->mdev,
+                                                   MLX5_FLOW_NAMESPACE_BYPASS),
+                           qp);
+       process_create_flag(dev, &create_flags,
+                           IB_QP_CREATE_INTEGRITY_EN,
+                           MLX5_CAP_GEN(mdev, sho), qp);
        process_create_flag(dev, &create_flags,
                            IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK,
                            MLX5_CAP_GEN(mdev, block_lb_mc), qp);
@@ -2873,7 +2882,6 @@ static int mlx5_ib_destroy_dct(struct mlx5_ib_qp *mqp)
 static int check_ucmd_data(struct mlx5_ib_dev *dev,
                           struct mlx5_create_qp_params *params)
 {
-       struct ib_qp_init_attr *attr = params->attr;
        struct ib_udata *udata = params->udata;
        size_t size, last;
        int ret;
@@ -2885,14 +2893,7 @@ static int check_ucmd_data(struct mlx5_ib_dev *dev,
                 */
                last = sizeof(struct mlx5_ib_create_qp_rss);
        else
-               /* IB_QPT_RAW_PACKET doesn't have ECE data */
-               switch (attr->qp_type) {
-               case IB_QPT_RAW_PACKET:
-                       last = offsetof(struct mlx5_ib_create_qp, ece_options);
-                       break;
-               default:
-                       last = offsetof(struct mlx5_ib_create_qp, reserved);
-               }
+               last = offsetof(struct mlx5_ib_create_qp, reserved);
 
        if (udata->inlen <= last)
                return 0;
@@ -2907,7 +2908,7 @@ static int check_ucmd_data(struct mlx5_ib_dev *dev,
        if (!ret)
                mlx5_ib_dbg(
                        dev,
-                       "udata is not cleared, inlen = %lu, ucmd = %lu, last = %lu, size = %lu\n",
+                       "udata is not cleared, inlen = %zu, ucmd = %zu, last = %zu, size = %zu\n",
                        udata->inlen, params->ucmd_size, last, size);
        return ret ? 0 : -EINVAL;
 }
@@ -2964,6 +2965,7 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attr,
                goto free_ucmd;
        }
 
+       mutex_init(&qp->mutex);
        qp->type = type;
        if (udata) {
                err = process_vendor_flags(dev, qp, params.ucmd, attr);
@@ -3002,10 +3004,19 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attr,
        return &qp->ibqp;
 
 destroy_qp:
-       if (qp->type == MLX5_IB_QPT_DCT)
+       if (qp->type == MLX5_IB_QPT_DCT) {
                mlx5_ib_destroy_dct(qp);
-       else
+       } else {
+               /*
+                * These lines below are temp solution till QP allocation
+                * will be moved to be under IB/core responsiblity.
+                */
+               qp->ibqp.send_cq = attr->send_cq;
+               qp->ibqp.recv_cq = attr->recv_cq;
+               qp->ibqp.pd = pd;
                destroy_qp_common(dev, qp, udata);
+       }
+
        qp = NULL;
 free_qp:
        kfree(qp);
@@ -4162,8 +4173,6 @@ static int mlx5_ib_modify_dct(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 
                if (udata->outlen < min_resp_len)
                        return -EINVAL;
-               resp.response_length = min_resp_len;
-
                /*
                 * If we don't have enough space for the ECE options,
                 * simply indicate it with resp.response_length.
@@ -4384,8 +4393,7 @@ static void to_rdma_ah_attr(struct mlx5_ib_dev *ibdev,
                                MLX5_GET(ads, path, src_addr_index),
                                MLX5_GET(ads, path, hop_limit),
                                MLX5_GET(ads, path, tclass));
-               memcpy(ah_attr, MLX5_ADDR_OF(ads, path, rgid_rip),
-                      MLX5_FLD_SZ_BYTES(ads, rgid_rip));
+               rdma_ah_set_dgid_raw(ah_attr, MLX5_ADDR_OF(ads, path, rgid_rip));
        }
 }
 
index c19d91d..7c3968e 100644 (file)
@@ -346,6 +346,9 @@ static int get_ece_from_mbox(void *out, u16 opcode)
        int ece = 0;
 
        switch (opcode) {
+       case MLX5_CMD_OP_INIT2INIT_QP:
+               ece = MLX5_GET(init2init_qp_out, out, ece);
+               break;
        case MLX5_CMD_OP_INIT2RTR_QP:
                ece = MLX5_GET(init2rtr_qp_out, out, ece);
                break;
@@ -355,6 +358,9 @@ static int get_ece_from_mbox(void *out, u16 opcode)
        case MLX5_CMD_OP_RTS2RTS_QP:
                ece = MLX5_GET(rts2rts_qp_out, out, ece);
                break;
+       case MLX5_CMD_OP_RST2INIT_QP:
+               ece = MLX5_GET(rst2init_qp_out, out, ece);
+               break;
        default:
                break;
        }
@@ -406,6 +412,7 @@ static int modify_qp_mbox_alloc(struct mlx5_core_dev *dev, u16 opcode, int qpn,
                        return -ENOMEM;
                MOD_QP_IN_SET_QPC(rst2init_qp, mbox->in, opcode, qpn,
                                  opt_param_mask, qpc, uid);
+               MLX5_SET(rst2init_qp_in, mbox->in, ece, ece);
                break;
        case MLX5_CMD_OP_INIT2RTR_QP:
                if (MBOX_ALLOC(mbox, init2rtr_qp))
@@ -439,6 +446,7 @@ static int modify_qp_mbox_alloc(struct mlx5_core_dev *dev, u16 opcode, int qpn,
                        return -ENOMEM;
                MOD_QP_IN_SET_QPC(init2init_qp, mbox->in, opcode, qpn,
                                  opt_param_mask, qpc, uid);
+               MLX5_SET(init2init_qp_in, mbox->in, ece, ece);
                break;
        default:
                return -EINVAL;
index 6f5eadc..37aaace 100644 (file)
@@ -83,11 +83,11 @@ struct mlx5_core_srq *mlx5_cmd_get_srq(struct mlx5_ib_dev *dev, u32 srqn)
        struct mlx5_srq_table *table = &dev->srq_table;
        struct mlx5_core_srq *srq;
 
-       xa_lock(&table->array);
+       xa_lock_irq(&table->array);
        srq = xa_load(&table->array, srqn);
        if (srq)
                refcount_inc(&srq->common.refcount);
-       xa_unlock(&table->array);
+       xa_unlock_irq(&table->array);
 
        return srq;
 }
index 792eecd..97fc7dd 100644 (file)
@@ -150,8 +150,17 @@ qedr_iw_issue_event(void *context,
        if (params->cm_info) {
                event.ird = params->cm_info->ird;
                event.ord = params->cm_info->ord;
-               event.private_data_len = params->cm_info->private_data_len;
-               event.private_data = (void *)params->cm_info->private_data;
+               /* Only connect_request and reply have valid private data
+                * the rest of the events this may be left overs from
+                * connection establishment. CONNECT_REQUEST is issued via
+                * qedr_iw_mpa_request
+                */
+               if (event_type == IW_CM_EVENT_CONNECT_REPLY) {
+                       event.private_data_len =
+                               params->cm_info->private_data_len;
+                       event.private_data =
+                               (void *)params->cm_info->private_data;
+               }
        }
 
        if (ep->cm_id)
index 511b728..332a8ba 100644 (file)
@@ -901,8 +901,6 @@ static void rvt_init_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp,
        qp->s_tail_ack_queue = 0;
        qp->s_acked_ack_queue = 0;
        qp->s_num_rd_atomic = 0;
-       if (qp->r_rq.kwq)
-               qp->r_rq.kwq->count = qp->r_rq.size;
        qp->r_sge.num_sge = 0;
        atomic_set(&qp->s_reserved_used, 0);
 }
@@ -1204,7 +1202,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
                err = alloc_ud_wq_attr(qp, rdi->dparms.node);
                if (err) {
                        ret = (ERR_PTR(err));
-                       goto bail_driver_priv;
+                       goto bail_rq_rvt;
                }
 
                if (init_attr->create_flags & IB_QP_CREATE_NETDEV_USE)
@@ -1314,9 +1312,11 @@ bail_qpn:
        rvt_free_qpn(&rdi->qp_dev->qpn_table, qp->ibqp.qp_num);
 
 bail_rq_wq:
-       rvt_free_rq(&qp->r_rq);
        free_ud_wq_attr(qp);
 
+bail_rq_rvt:
+       rvt_free_rq(&qp->r_rq);
+
 bail_driver_priv:
        rdi->driver_f.qp_priv_free(rdi, qp);
 
@@ -2364,31 +2364,6 @@ bad_lkey:
        return 0;
 }
 
-/**
- * get_count - count numbers of request work queue entries
- * in circular buffer
- * @rq: data structure for request queue entry
- * @tail: tail indices of the circular buffer
- * @head: head indices of the circular buffer
- *
- * Return - total number of entries in the circular buffer
- */
-static u32 get_count(struct rvt_rq *rq, u32 tail, u32 head)
-{
-       u32 count;
-
-       count = head;
-
-       if (count >= rq->size)
-               count = 0;
-       if (count < tail)
-               count += rq->size - tail;
-       else
-               count -= tail;
-
-       return count;
-}
-
 /**
  * get_rvt_head - get head indices of the circular buffer
  * @rq: data structure for request queue entry
@@ -2463,7 +2438,7 @@ int rvt_get_rwqe(struct rvt_qp *qp, bool wr_id_only)
 
        if (kwq->count < RVT_RWQ_COUNT_THRESHOLD) {
                head = get_rvt_head(rq, ip);
-               kwq->count = get_count(rq, tail, head);
+               kwq->count = rvt_get_rq_count(rq, head, tail);
        }
        if (unlikely(kwq->count == 0)) {
                ret = 0;
@@ -2498,7 +2473,9 @@ int rvt_get_rwqe(struct rvt_qp *qp, bool wr_id_only)
                 * the number of remaining WQEs.
                 */
                if (kwq->count < srq->limit) {
-                       kwq->count = get_count(rq, tail, get_rvt_head(rq, ip));
+                       kwq->count =
+                               rvt_get_rq_count(rq,
+                                                get_rvt_head(rq, ip), tail);
                        if (kwq->count < srq->limit) {
                                struct ib_event ev;
 
index 977906c..c58735f 100644 (file)
@@ -127,9 +127,7 @@ __be32 rvt_compute_aeth(struct rvt_qp *qp)
                         * not atomic, which is OK, since the fuzziness is
                         * resolved as further ACKs go out.
                         */
-                       credits = head - tail;
-                       if ((int)credits < 0)
-                               credits += qp->r_rq.size;
+                       credits = rvt_get_rq_count(&qp->r_rq, head, tail);
                }
                /*
                 * Binary search the credit table to find the code to
index a0b8cc6..ed60c9e 100644 (file)
@@ -67,12 +67,13 @@ static int siw_device_register(struct siw_device *sdev, const char *name)
        static int dev_id = 1;
        int rv;
 
+       sdev->vendor_part_id = dev_id++;
+
        rv = ib_register_device(base_dev, name);
        if (rv) {
                pr_warn("siw: device registration error %d\n", rv);
                return rv;
        }
-       sdev->vendor_part_id = dev_id++;
 
        siw_dbg(base_dev, "HWaddr=%pM\n", sdev->netdev->dev_addr);
 
index 6505202..7271d70 100644 (file)
@@ -139,7 +139,8 @@ static int siw_rx_pbl(struct siw_rx_stream *srx, int *pbl_idx,
                        break;
 
                bytes = min(bytes, len);
-               if (siw_rx_kva(srx, (void *)buf_addr, bytes) == bytes) {
+               if (siw_rx_kva(srx, (void *)(uintptr_t)buf_addr, bytes) ==
+                   bytes) {
                        copied += bytes;
                        offset += bytes;
                        len -= bytes;
index 3f9354b..6291fb5 100644 (file)
@@ -951,6 +951,8 @@ static void elan_report_absolute(struct elan_tp_data *data, u8 *packet)
        u8 hover_info = packet[ETP_HOVER_INFO_OFFSET];
        bool contact_valid, hover_event;
 
+       pm_wakeup_event(&data->client->dev, 0);
+
        hover_event = hover_info & 0x40;
        for (i = 0; i < ETP_MAX_FINGERS; i++) {
                contact_valid = tp_info & (1U << (3 + i));
@@ -974,6 +976,8 @@ static void elan_report_trackpoint(struct elan_tp_data *data, u8 *report)
        u8 *packet = &report[ETP_REPORT_ID_OFFSET + 1];
        int x, y;
 
+       pm_wakeup_event(&data->client->dev, 0);
+
        if (!data->tp_input) {
                dev_warn_once(&data->client->dev,
                              "received a trackpoint report while no trackpoint device has been created. Please report upstream.\n");
@@ -998,7 +1002,6 @@ static void elan_report_trackpoint(struct elan_tp_data *data, u8 *report)
 static irqreturn_t elan_isr(int irq, void *dev_id)
 {
        struct elan_tp_data *data = dev_id;
-       struct device *dev = &data->client->dev;
        int error;
        u8 report[ETP_MAX_REPORT_LEN];
 
@@ -1016,8 +1019,6 @@ static irqreturn_t elan_isr(int irq, void *dev_id)
        if (error)
                goto out;
 
-       pm_wakeup_event(dev, 0);
-
        switch (report[ETP_REPORT_ID_OFFSET]) {
        case ETP_REPORT_ID:
                elan_report_absolute(data, report);
@@ -1026,7 +1027,7 @@ static irqreturn_t elan_isr(int irq, void *dev_id)
                elan_report_trackpoint(data, report);
                break;
        default:
-               dev_err(dev, "invalid report id data (%x)\n",
+               dev_err(&data->client->dev, "invalid report id data (%x)\n",
                        report[ETP_REPORT_ID_OFFSET]);
        }
 
index 758dae8..4b81b2d 100644 (file)
@@ -179,6 +179,7 @@ static const char * const smbus_pnp_ids[] = {
        "LEN0093", /* T480 */
        "LEN0096", /* X280 */
        "LEN0097", /* X280 -> ALPS trackpoint */
+       "LEN0099", /* X1 Extreme 1st */
        "LEN009b", /* T580 */
        "LEN200f", /* T450s */
        "LEN2044", /* L470  */
index 6542523..13eacf6 100644 (file)
@@ -1021,7 +1021,7 @@ static int __init hp_sdc_register(void)
        hp_sdc.base_io   = (unsigned long) 0xf0428000;
        hp_sdc.data_io   = (unsigned long) hp_sdc.base_io + 1;
        hp_sdc.status_io = (unsigned long) hp_sdc.base_io + 3;
-       if (!probe_kernel_read(&i, (unsigned char *)hp_sdc.data_io, 1))
+       if (!copy_from_kernel_nofault(&i, (unsigned char *)hp_sdc.data_io, 1))
                hp_sdc.dev = (void *)1;
        hp_sdc.dev_err   = hp_sdc_init();
 #endif
index 7b08ff8..7d7f737 100644 (file)
@@ -425,6 +425,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "076804U"),
                },
        },
+       {
+               /* Lenovo XiaoXin Air 12 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "80UN"),
+               },
+       },
        {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
index 233cb10..5477a57 100644 (file)
@@ -1325,7 +1325,6 @@ static int elants_i2c_probe(struct i2c_client *client,
                             0, MT_TOOL_PALM, 0, 0);
        input_abs_set_res(ts->input, ABS_MT_POSITION_X, ts->x_res);
        input_abs_set_res(ts->input, ABS_MT_POSITION_Y, ts->y_res);
-       input_abs_set_res(ts->input, ABS_MT_TOUCH_MAJOR, 1);
 
        touchscreen_parse_properties(ts->input, true, &ts->prop);
 
index e5f9987..9e1ab70 100644 (file)
@@ -243,6 +243,7 @@ static int aggregate_requests(struct icc_node *node)
 {
        struct icc_provider *p = node->provider;
        struct icc_req *r;
+       u32 avg_bw, peak_bw;
 
        node->avg_bw = 0;
        node->peak_bw = 0;
@@ -251,9 +252,14 @@ static int aggregate_requests(struct icc_node *node)
                p->pre_aggregate(node);
 
        hlist_for_each_entry(r, &node->req_list, req_node) {
-               if (!r->enabled)
-                       continue;
-               p->aggregate(node, r->tag, r->avg_bw, r->peak_bw,
+               if (r->enabled) {
+                       avg_bw = r->avg_bw;
+                       peak_bw = r->peak_bw;
+               } else {
+                       avg_bw = 0;
+                       peak_bw = 0;
+               }
+               p->aggregate(node, r->tag, avg_bw, peak_bw,
                             &node->avg_bw, &node->peak_bw);
        }
 
index e94f3c5..42c6c55 100644 (file)
@@ -197,13 +197,13 @@ DEFINE_QNODE(pcnoc_int_0, MSM8916_PNOC_INT_0, 8, -1, -1, MSM8916_PNOC_SNOC_MAS,
 DEFINE_QNODE(pcnoc_int_1, MSM8916_PNOC_INT_1, 8, -1, -1, MSM8916_PNOC_SNOC_MAS);
 DEFINE_QNODE(pcnoc_m_0, MSM8916_PNOC_MAS_0, 8, -1, -1, MSM8916_PNOC_INT_0);
 DEFINE_QNODE(pcnoc_m_1, MSM8916_PNOC_MAS_1, 8, -1, -1, MSM8916_PNOC_SNOC_MAS);
-DEFINE_QNODE(pcnoc_s_0, MSM8916_PNOC_SLV_0, 8, -1, -1, MSM8916_SLAVE_CLK_CTL, MSM8916_SLAVE_TLMM, MSM8916_SLAVE_TCSR, MSM8916_SLAVE_SECURITY, MSM8916_SLAVE_MSS);
-DEFINE_QNODE(pcnoc_s_1, MSM8916_PNOC_SLV_1, 8, -1, -1, MSM8916_SLAVE_IMEM_CFG, MSM8916_SLAVE_CRYPTO_0_CFG, MSM8916_SLAVE_MSG_RAM, MSM8916_SLAVE_PDM, MSM8916_SLAVE_PRNG);
-DEFINE_QNODE(pcnoc_s_2, MSM8916_PNOC_SLV_2, 8, -1, -1, MSM8916_SLAVE_SPDM, MSM8916_SLAVE_BOOT_ROM, MSM8916_SLAVE_BIMC_CFG, MSM8916_SLAVE_PNOC_CFG, MSM8916_SLAVE_PMIC_ARB);
-DEFINE_QNODE(pcnoc_s_3, MSM8916_PNOC_SLV_3, 8, -1, -1, MSM8916_SLAVE_MPM, MSM8916_SLAVE_SNOC_CFG, MSM8916_SLAVE_RBCPR_CFG, MSM8916_SLAVE_QDSS_CFG, MSM8916_SLAVE_DEHR_CFG);
-DEFINE_QNODE(pcnoc_s_4, MSM8916_PNOC_SLV_4, 8, -1, -1, MSM8916_SLAVE_VENUS_CFG, MSM8916_SLAVE_CAMERA_CFG, MSM8916_SLAVE_DISPLAY_CFG);
-DEFINE_QNODE(pcnoc_s_8, MSM8916_PNOC_SLV_8, 8, -1, -1, MSM8916_SLAVE_USB_HS, MSM8916_SLAVE_SDCC_1, MSM8916_SLAVE_BLSP_1);
-DEFINE_QNODE(pcnoc_s_9, MSM8916_PNOC_SLV_9, 8, -1, -1, MSM8916_SLAVE_SDCC_2, MSM8916_SLAVE_LPASS, MSM8916_SLAVE_GRAPHICS_3D_CFG);
+DEFINE_QNODE(pcnoc_s_0, MSM8916_PNOC_SLV_0, 4, -1, -1, MSM8916_SLAVE_CLK_CTL, MSM8916_SLAVE_TLMM, MSM8916_SLAVE_TCSR, MSM8916_SLAVE_SECURITY, MSM8916_SLAVE_MSS);
+DEFINE_QNODE(pcnoc_s_1, MSM8916_PNOC_SLV_1, 4, -1, -1, MSM8916_SLAVE_IMEM_CFG, MSM8916_SLAVE_CRYPTO_0_CFG, MSM8916_SLAVE_MSG_RAM, MSM8916_SLAVE_PDM, MSM8916_SLAVE_PRNG);
+DEFINE_QNODE(pcnoc_s_2, MSM8916_PNOC_SLV_2, 4, -1, -1, MSM8916_SLAVE_SPDM, MSM8916_SLAVE_BOOT_ROM, MSM8916_SLAVE_BIMC_CFG, MSM8916_SLAVE_PNOC_CFG, MSM8916_SLAVE_PMIC_ARB);
+DEFINE_QNODE(pcnoc_s_3, MSM8916_PNOC_SLV_3, 4, -1, -1, MSM8916_SLAVE_MPM, MSM8916_SLAVE_SNOC_CFG, MSM8916_SLAVE_RBCPR_CFG, MSM8916_SLAVE_QDSS_CFG, MSM8916_SLAVE_DEHR_CFG);
+DEFINE_QNODE(pcnoc_s_4, MSM8916_PNOC_SLV_4, 4, -1, -1, MSM8916_SLAVE_VENUS_CFG, MSM8916_SLAVE_CAMERA_CFG, MSM8916_SLAVE_DISPLAY_CFG);
+DEFINE_QNODE(pcnoc_s_8, MSM8916_PNOC_SLV_8, 4, -1, -1, MSM8916_SLAVE_USB_HS, MSM8916_SLAVE_SDCC_1, MSM8916_SLAVE_BLSP_1);
+DEFINE_QNODE(pcnoc_s_9, MSM8916_PNOC_SLV_9, 4, -1, -1, MSM8916_SLAVE_SDCC_2, MSM8916_SLAVE_LPASS, MSM8916_SLAVE_GRAPHICS_3D_CFG);
 DEFINE_QNODE(pcnoc_snoc_mas, MSM8916_PNOC_SNOC_MAS, 8, 29, -1, MSM8916_PNOC_SNOC_SLV);
 DEFINE_QNODE(pcnoc_snoc_slv, MSM8916_PNOC_SNOC_SLV, 8, -1, 45, MSM8916_SNOC_INT_0, MSM8916_SNOC_INT_BIMC, MSM8916_SNOC_INT_1);
 DEFINE_QNODE(qdss_int, MSM8916_SNOC_QDSS_INT, 8, -1, -1, MSM8916_SNOC_INT_0, MSM8916_SNOC_INT_BIMC);
index b510f67..b0f308c 100644 (file)
@@ -211,7 +211,7 @@ config INTEL_IOMMU_DEBUGFS
 
 config INTEL_IOMMU_SVM
        bool "Support for Shared Virtual Memory with Intel IOMMU"
-       depends on INTEL_IOMMU && X86
+       depends on INTEL_IOMMU && X86_64
        select PCI_PASID
        select PCI_PRI
        select MMU_NOTIFIER
@@ -305,6 +305,7 @@ config ROCKCHIP_IOMMU
 
 config SUN50I_IOMMU
        bool "Allwinner H6 IOMMU Support"
+       depends on HAS_DMA
        depends on ARCH_SUNXI || COMPILE_TEST
        select ARM_DMA_USE_IOMMU
        select IOMMU_API
index f892992..5730971 100644 (file)
@@ -102,7 +102,7 @@ extern int __init add_special_device(u8 type, u8 id, u16 *devid,
 #ifdef CONFIG_DMI
 void amd_iommu_apply_ivrs_quirks(void);
 #else
-static void amd_iommu_apply_ivrs_quirks(void) { }
+static inline void amd_iommu_apply_ivrs_quirks(void) { }
 #endif
 
 #endif
index 74cca17..2f22326 100644 (file)
@@ -3985,9 +3985,10 @@ int amd_iommu_create_irq_domain(struct amd_iommu *iommu)
        if (!fn)
                return -ENOMEM;
        iommu->ir_domain = irq_domain_create_tree(fn, &amd_ir_domain_ops, iommu);
-       irq_domain_free_fwnode(fn);
-       if (!iommu->ir_domain)
+       if (!iommu->ir_domain) {
+               irq_domain_free_fwnode(fn);
                return -ENOMEM;
+       }
 
        iommu->ir_domain->parent = arch_get_ir_parent_domain();
        iommu->msi_domain = arch_create_remap_msi_irq_domain(iommu->ir_domain,
index cf01d02..be43180 100644 (file)
@@ -12,7 +12,7 @@ struct qcom_smmu {
        struct arm_smmu_device smmu;
 };
 
-static const struct of_device_id qcom_smmu_client_of_match[] = {
+static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = {
        { .compatible = "qcom,adreno" },
        { .compatible = "qcom,mdp4" },
        { .compatible = "qcom,mdss" },
index 3c0c67a..8919c1c 100644 (file)
@@ -155,7 +155,10 @@ static int __init hyperv_prepare_irq_remapping(void)
                                0, IOAPIC_REMAPPING_ENTRY, fn,
                                &hyperv_ir_domain_ops, NULL);
 
-       irq_domain_free_fwnode(fn);
+       if (!ioapic_ir_domain) {
+               irq_domain_free_fwnode(fn);
+               return -ENOMEM;
+       }
 
        /*
         * Hyper-V doesn't provide irq remapping function for
index cc46dff..683b812 100644 (file)
@@ -898,7 +898,8 @@ int __init detect_intel_iommu(void)
        if (!ret)
                ret = dmar_walk_dmar_table((struct acpi_table_dmar *)dmar_tbl,
                                           &validate_drhd_cb);
-       if (!ret && !no_iommu && !iommu_detected && !dmar_disabled) {
+       if (!ret && !no_iommu && !iommu_detected &&
+           (!dmar_disabled || dmar_platform_optin())) {
                iommu_detected = 1;
                /* Make sure ACS will be enabled */
                pci_request_acs();
index 9129663..d759e72 100644 (file)
@@ -612,6 +612,12 @@ struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
        return g_iommus[iommu_id];
 }
 
+static inline bool iommu_paging_structure_coherency(struct intel_iommu *iommu)
+{
+       return sm_supported(iommu) ?
+                       ecap_smpwc(iommu->ecap) : ecap_coherent(iommu->ecap);
+}
+
 static void domain_update_iommu_coherency(struct dmar_domain *domain)
 {
        struct dmar_drhd_unit *drhd;
@@ -623,7 +629,7 @@ static void domain_update_iommu_coherency(struct dmar_domain *domain)
 
        for_each_domain_iommu(i, domain) {
                found = true;
-               if (!ecap_coherent(g_iommus[i]->ecap)) {
+               if (!iommu_paging_structure_coherency(g_iommus[i])) {
                        domain->iommu_coherency = 0;
                        break;
                }
@@ -634,7 +640,7 @@ static void domain_update_iommu_coherency(struct dmar_domain *domain)
        /* No hardware attached; use lowest common denominator */
        rcu_read_lock();
        for_each_active_iommu(iommu, drhd) {
-               if (!ecap_coherent(iommu->ecap)) {
+               if (!iommu_paging_structure_coherency(iommu)) {
                        domain->iommu_coherency = 0;
                        break;
                }
@@ -921,7 +927,7 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
                        domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
                        pteval = ((uint64_t)virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE;
                        if (domain_use_first_level(domain))
-                               pteval |= DMA_FL_PTE_XD;
+                               pteval |= DMA_FL_PTE_XD | DMA_FL_PTE_US;
                        if (cmpxchg64(&pte->val, 0ULL, pteval))
                                /* Someone else set it while we were thinking; use theirs. */
                                free_pgtable_page(tmp_page);
@@ -1951,7 +1957,6 @@ static inline void
 context_set_sm_rid2pasid(struct context_entry *context, unsigned long pasid)
 {
        context->hi |= pasid & ((1 << 20) - 1);
-       context->hi |= (1 << 20);
 }
 
 /*
@@ -2095,7 +2100,8 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
 
        context_set_fault_enable(context);
        context_set_present(context);
-       domain_flush_cache(domain, context, sizeof(*context));
+       if (!ecap_coherent(iommu->ecap))
+               clflush_cache_range(context, sizeof(*context));
 
        /*
         * It's a non-present to present mapping. If hardware doesn't cache
@@ -2243,7 +2249,7 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
 
        attr = prot & (DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP);
        if (domain_use_first_level(domain))
-               attr |= DMA_FL_PTE_PRESENT | DMA_FL_PTE_XD;
+               attr |= DMA_FL_PTE_PRESENT | DMA_FL_PTE_XD | DMA_FL_PTE_US;
 
        if (!sg) {
                sg_res = nr_pages;
@@ -2695,7 +2701,9 @@ static int __init si_domain_init(int hw)
                                    end >> agaw_to_width(si_domain->agaw)))
                                continue;
 
-                       ret = iommu_domain_identity_map(si_domain, start, end);
+                       ret = iommu_domain_identity_map(si_domain,
+                                       mm_to_dma_pfn(start >> PAGE_SHIFT),
+                                       mm_to_dma_pfn(end >> PAGE_SHIFT));
                        if (ret)
                                return ret;
                }
@@ -6021,6 +6029,23 @@ intel_iommu_domain_set_attr(struct iommu_domain *domain,
        return ret;
 }
 
+/*
+ * Check that the device does not live on an external facing PCI port that is
+ * marked as untrusted. Such devices should not be able to apply quirks and
+ * thus not be able to bypass the IOMMU restrictions.
+ */
+static bool risky_device(struct pci_dev *pdev)
+{
+       if (pdev->untrusted) {
+               pci_info(pdev,
+                        "Skipping IOMMU quirk for dev [%04X:%04X] on untrusted PCI link\n",
+                        pdev->vendor, pdev->device);
+               pci_info(pdev, "Please check with your BIOS/Platform vendor about this\n");
+               return true;
+       }
+       return false;
+}
+
 const struct iommu_ops intel_iommu_ops = {
        .capable                = intel_iommu_capable,
        .domain_alloc           = intel_iommu_domain_alloc,
@@ -6060,6 +6085,9 @@ const struct iommu_ops intel_iommu_ops = {
 
 static void quirk_iommu_igfx(struct pci_dev *dev)
 {
+       if (risky_device(dev))
+               return;
+
        pci_info(dev, "Disabling IOMMU for graphics on this chipset\n");
        dmar_map_gfx = 0;
 }
@@ -6101,6 +6129,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163D, quirk_iommu_igfx);
 
 static void quirk_iommu_rwbf(struct pci_dev *dev)
 {
+       if (risky_device(dev))
+               return;
+
        /*
         * Mobile 4 Series Chipset neglects to set RWBF capability,
         * but needs it. Same seems to hold for the desktop versions.
@@ -6131,6 +6162,9 @@ static void quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
 {
        unsigned short ggc;
 
+       if (risky_device(dev))
+               return;
+
        if (pci_read_config_word(dev, GGC, &ggc))
                return;
 
@@ -6164,6 +6198,12 @@ static void __init check_tylersburg_isoch(void)
        pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3a3e, NULL);
        if (!pdev)
                return;
+
+       if (risky_device(pdev)) {
+               pci_dev_put(pdev);
+               return;
+       }
+
        pci_dev_put(pdev);
 
        /* System Management Registers. Might be hidden, in which case
@@ -6173,6 +6213,11 @@ static void __init check_tylersburg_isoch(void)
        if (!pdev)
                return;
 
+       if (risky_device(pdev)) {
+               pci_dev_put(pdev);
+               return;
+       }
+
        if (pci_read_config_dword(pdev, 0x188, &vtisochctrl)) {
                pci_dev_put(pdev);
                return;
index 7f87698..9564d23 100644 (file)
@@ -563,8 +563,8 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu)
                                            0, INTR_REMAP_TABLE_ENTRIES,
                                            fn, &intel_ir_domain_ops,
                                            iommu);
-       irq_domain_free_fwnode(fn);
        if (!iommu->ir_domain) {
+               irq_domain_free_fwnode(fn);
                pr_err("IR%d: failed to allocate irqdomain\n", iommu->seq_id);
                goto out_free_bitmap;
        }
index d43120e..b6858ad 100644 (file)
@@ -295,10 +295,10 @@ void iommu_release_device(struct device *dev)
                return;
 
        iommu_device_unlink(dev->iommu->iommu_dev, dev);
-       iommu_group_remove_device(dev);
 
        ops->release_device(dev);
 
+       iommu_group_remove_device(dev);
        module_put(ops->owner);
        dev_iommu_free(dev);
 }
index c3e1fbd..d176df5 100644 (file)
@@ -65,6 +65,7 @@ struct qcom_iommu_domain {
        struct mutex             init_mutex; /* Protects iommu pointer */
        struct iommu_domain      domain;
        struct qcom_iommu_dev   *iommu;
+       struct iommu_fwspec     *fwspec;
 };
 
 static struct qcom_iommu_domain *to_qcom_iommu_domain(struct iommu_domain *dom)
@@ -84,9 +85,9 @@ static struct qcom_iommu_dev * to_iommu(struct device *dev)
        return dev_iommu_priv_get(dev);
 }
 
-static struct qcom_iommu_ctx * to_ctx(struct device *dev, unsigned asid)
+static struct qcom_iommu_ctx * to_ctx(struct qcom_iommu_domain *d, unsigned asid)
 {
-       struct qcom_iommu_dev *qcom_iommu = to_iommu(dev);
+       struct qcom_iommu_dev *qcom_iommu = d->iommu;
        if (!qcom_iommu)
                return NULL;
        return qcom_iommu->ctxs[asid - 1];
@@ -118,14 +119,12 @@ iommu_readq(struct qcom_iommu_ctx *ctx, unsigned reg)
 
 static void qcom_iommu_tlb_sync(void *cookie)
 {
-       struct iommu_fwspec *fwspec;
-       struct device *dev = cookie;
+       struct qcom_iommu_domain *qcom_domain = cookie;
+       struct iommu_fwspec *fwspec = qcom_domain->fwspec;
        unsigned i;
 
-       fwspec = dev_iommu_fwspec_get(dev);
-
        for (i = 0; i < fwspec->num_ids; i++) {
-               struct qcom_iommu_ctx *ctx = to_ctx(dev, fwspec->ids[i]);
+               struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]);
                unsigned int val, ret;
 
                iommu_writel(ctx, ARM_SMMU_CB_TLBSYNC, 0);
@@ -139,14 +138,12 @@ static void qcom_iommu_tlb_sync(void *cookie)
 
 static void qcom_iommu_tlb_inv_context(void *cookie)
 {
-       struct device *dev = cookie;
-       struct iommu_fwspec *fwspec;
+       struct qcom_iommu_domain *qcom_domain = cookie;
+       struct iommu_fwspec *fwspec = qcom_domain->fwspec;
        unsigned i;
 
-       fwspec = dev_iommu_fwspec_get(dev);
-
        for (i = 0; i < fwspec->num_ids; i++) {
-               struct qcom_iommu_ctx *ctx = to_ctx(dev, fwspec->ids[i]);
+               struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]);
                iommu_writel(ctx, ARM_SMMU_CB_S1_TLBIASID, ctx->asid);
        }
 
@@ -156,16 +153,14 @@ static void qcom_iommu_tlb_inv_context(void *cookie)
 static void qcom_iommu_tlb_inv_range_nosync(unsigned long iova, size_t size,
                                            size_t granule, bool leaf, void *cookie)
 {
-       struct device *dev = cookie;
-       struct iommu_fwspec *fwspec;
+       struct qcom_iommu_domain *qcom_domain = cookie;
+       struct iommu_fwspec *fwspec = qcom_domain->fwspec;
        unsigned i, reg;
 
        reg = leaf ? ARM_SMMU_CB_S1_TLBIVAL : ARM_SMMU_CB_S1_TLBIVA;
 
-       fwspec = dev_iommu_fwspec_get(dev);
-
        for (i = 0; i < fwspec->num_ids; i++) {
-               struct qcom_iommu_ctx *ctx = to_ctx(dev, fwspec->ids[i]);
+               struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]);
                size_t s = size;
 
                iova = (iova >> 12) << 12;
@@ -256,7 +251,9 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain,
        };
 
        qcom_domain->iommu = qcom_iommu;
-       pgtbl_ops = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &pgtbl_cfg, dev);
+       qcom_domain->fwspec = fwspec;
+
+       pgtbl_ops = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &pgtbl_cfg, qcom_domain);
        if (!pgtbl_ops) {
                dev_err(qcom_iommu->dev, "failed to allocate pagetable ops\n");
                ret = -ENOMEM;
@@ -269,7 +266,7 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain,
        domain->geometry.force_aperture = true;
 
        for (i = 0; i < fwspec->num_ids; i++) {
-               struct qcom_iommu_ctx *ctx = to_ctx(dev, fwspec->ids[i]);
+               struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]);
 
                if (!ctx->secure_init) {
                        ret = qcom_scm_restore_sec_cfg(qcom_iommu->sec_id, ctx->asid);
@@ -419,7 +416,7 @@ static void qcom_iommu_detach_dev(struct iommu_domain *domain, struct device *de
 
        pm_runtime_get_sync(qcom_iommu->dev);
        for (i = 0; i < fwspec->num_ids; i++) {
-               struct qcom_iommu_ctx *ctx = to_ctx(dev, fwspec->ids[i]);
+               struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]);
 
                /* Disable the context bank: */
                iommu_writel(ctx, ARM_SMMU_CB_SCTLR, 0);
index fce605e..3b1bf2f 100644 (file)
@@ -313,9 +313,9 @@ static int sun50i_iommu_flush_all_tlb(struct sun50i_iommu *iommu)
                    IOMMU_TLB_FLUSH_MICRO_TLB(1) |
                    IOMMU_TLB_FLUSH_MICRO_TLB(0));
 
-       ret = readl_poll_timeout(iommu->base + IOMMU_TLB_FLUSH_REG,
-                                reg, !reg,
-                                1, 2000);
+       ret = readl_poll_timeout_atomic(iommu->base + IOMMU_TLB_FLUSH_REG,
+                                       reg, !reg,
+                                       1, 2000);
        if (ret)
                dev_warn(iommu->dev, "TLB Flush timed out!\n");
 
@@ -556,7 +556,6 @@ static size_t sun50i_iommu_unmap(struct iommu_domain *domain, unsigned long iova
 {
        struct sun50i_iommu_domain *sun50i_domain = to_sun50i_domain(domain);
        phys_addr_t pt_phys;
-       dma_addr_t pte_dma;
        u32 *pte_addr;
        u32 dte;
 
@@ -566,7 +565,6 @@ static size_t sun50i_iommu_unmap(struct iommu_domain *domain, unsigned long iova
 
        pt_phys = sun50i_dte_get_pt_address(dte);
        pte_addr = (u32 *)phys_to_virt(pt_phys) + sun50i_iova_get_pte_index(iova);
-       pte_dma = pt_phys + sun50i_iova_get_pte_index(iova) * PT_ENTRY_SIZE;
 
        if (!sun50i_pte_is_page_valid(*pte_addr))
                return 0;
index 29fead2..216b3b8 100644 (file)
@@ -563,7 +563,7 @@ config LOONGSON_PCH_PIC
          Support for the Loongson PCH PIC Controller.
 
 config LOONGSON_PCH_MSI
-       bool "Loongson PCH PIC Controller"
+       bool "Loongson PCH MSI Controller"
        depends on MACH_LOONGSON64 || COMPILE_TEST
        depends on PCI
        default MACH_LOONGSON64
index cd685f5..beac4ca 100644 (file)
@@ -3797,10 +3797,10 @@ static void its_wait_vpt_parse_complete(void)
        if (!gic_rdists->has_vpend_valid_dirty)
                return;
 
-       WARN_ON_ONCE(readq_relaxed_poll_timeout(vlpi_base + GICR_VPENDBASER,
-                                               val,
-                                               !(val & GICR_VPENDBASER_Dirty),
-                                               10, 500));
+       WARN_ON_ONCE(readq_relaxed_poll_timeout_atomic(vlpi_base + GICR_VPENDBASER,
+                                                      val,
+                                                      !(val & GICR_VPENDBASER_Dirty),
+                                                      10, 500));
 }
 
 static void its_vpe_schedule(struct its_vpe *vpe)
@@ -4054,16 +4054,24 @@ static void its_vpe_4_1_deschedule(struct its_vpe *vpe,
        u64 val;
 
        if (info->req_db) {
+               unsigned long flags;
+
                /*
                 * vPE is going to block: make the vPE non-resident with
                 * PendingLast clear and DB set. The GIC guarantees that if
                 * we read-back PendingLast clear, then a doorbell will be
                 * delivered when an interrupt comes.
+                *
+                * Note the locking to deal with the concurrent update of
+                * pending_last from the doorbell interrupt handler that can
+                * run concurrently.
                 */
+               raw_spin_lock_irqsave(&vpe->vpe_lock, flags);
                val = its_clear_vpend_valid(vlpi_base,
                                            GICR_VPENDBASER_PendingLast,
                                            GICR_VPENDBASER_4_1_DB);
                vpe->pending_last = !!(val & GICR_VPENDBASER_PendingLast);
+               raw_spin_unlock_irqrestore(&vpe->vpe_lock, flags);
        } else {
                /*
                 * We're not blocking, so just make the vPE non-resident
index 00de05a..c17fabd 100644 (file)
@@ -329,10 +329,8 @@ static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
 static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
                            bool force)
 {
-       void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
-       unsigned int cpu, shift = (gic_irq(d) % 4) * 8;
-       u32 val, mask, bit;
-       unsigned long flags;
+       void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + gic_irq(d);
+       unsigned int cpu;
 
        if (!force)
                cpu = cpumask_any_and(mask_val, cpu_online_mask);
@@ -342,13 +340,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
        if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
                return -EINVAL;
 
-       gic_lock_irqsave(flags);
-       mask = 0xff << shift;
-       bit = gic_cpu_map[cpu] << shift;
-       val = readl_relaxed(reg) & ~mask;
-       writel_relaxed(val | bit, reg);
-       gic_unlock_irqrestore(flags);
-
+       writeb_relaxed(gic_cpu_map[cpu], reg);
        irq_data_update_effective_affinity(d, cpumask_of(cpu));
 
        return IRQ_SET_MASK_OK_DONE;
index a6f97fa..8017f6d 100644 (file)
@@ -99,7 +99,7 @@ static int __init riscv_intc_init(struct device_node *node,
 
        hartid = riscv_of_parent_hartid(node);
        if (hartid < 0) {
-               pr_warn("unable to fine hart id for %pOF\n", node);
+               pr_warn("unable to find hart id for %pOF\n", node);
                return 0;
        }
 
index 39de94e..6548a60 100644 (file)
@@ -1389,7 +1389,7 @@ static int btree_gc_coalesce(struct btree *b, struct btree_op *op,
                        if (__set_blocks(n1, n1->keys + n2->keys,
                                         block_bytes(b->c)) >
                            btree_blocks(new_nodes[i]))
-                               goto out_nocoalesce;
+                               goto out_unlock_nocoalesce;
 
                        keys = n2->keys;
                        /* Take the key of the node we're getting rid of */
@@ -1418,7 +1418,7 @@ static int btree_gc_coalesce(struct btree *b, struct btree_op *op,
 
                if (__bch_keylist_realloc(&keylist,
                                          bkey_u64s(&new_nodes[i]->key)))
-                       goto out_nocoalesce;
+                       goto out_unlock_nocoalesce;
 
                bch_btree_node_write(new_nodes[i], &cl);
                bch_keylist_add(&keylist, &new_nodes[i]->key);
@@ -1464,6 +1464,10 @@ static int btree_gc_coalesce(struct btree *b, struct btree_op *op,
        /* Invalidated our iterator */
        return -EINTR;
 
+out_unlock_nocoalesce:
+       for (i = 0; i < nodes; i++)
+               mutex_unlock(&new_nodes[i]->write_lock);
+
 out_nocoalesce:
        closure_sync(&cl);
 
index f9975c2..2014016 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/genhd.h>
 #include <linux/idr.h>
 #include <linux/kthread.h>
+#include <linux/workqueue.h>
 #include <linux/module.h>
 #include <linux/random.h>
 #include <linux/reboot.h>
@@ -819,7 +820,8 @@ static void bcache_device_free(struct bcache_device *d)
 }
 
 static int bcache_device_init(struct bcache_device *d, unsigned int block_size,
-                             sector_t sectors, make_request_fn make_request_fn)
+                             sector_t sectors, make_request_fn make_request_fn,
+                             struct block_device *cached_bdev)
 {
        struct request_queue *q;
        const size_t max_stripes = min_t(size_t, INT_MAX,
@@ -885,6 +887,20 @@ static int bcache_device_init(struct bcache_device *d, unsigned int block_size,
        q->limits.io_min                = block_size;
        q->limits.logical_block_size    = block_size;
        q->limits.physical_block_size   = block_size;
+
+       if (q->limits.logical_block_size > PAGE_SIZE && cached_bdev) {
+               /*
+                * This should only happen with BCACHE_SB_VERSION_BDEV.
+                * Block/page size is checked for BCACHE_SB_VERSION_CDEV.
+                */
+               pr_info("%s: sb/logical block size (%u) greater than page size (%lu) falling back to device logical block size (%u)\n",
+                       d->disk->disk_name, q->limits.logical_block_size,
+                       PAGE_SIZE, bdev_logical_block_size(cached_bdev));
+
+               /* This also adjusts physical block size/min io size if needed */
+               blk_queue_logical_block_size(q, bdev_logical_block_size(cached_bdev));
+       }
+
        blk_queue_flag_set(QUEUE_FLAG_NONROT, d->disk->queue);
        blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, d->disk->queue);
        blk_queue_flag_set(QUEUE_FLAG_DISCARD, d->disk->queue);
@@ -1340,7 +1356,7 @@ static int cached_dev_init(struct cached_dev *dc, unsigned int block_size)
 
        ret = bcache_device_init(&dc->disk, block_size,
                         dc->bdev->bd_part->nr_sects - dc->sb.data_offset,
-                        cached_dev_make_request);
+                        cached_dev_make_request, dc->bdev);
        if (ret)
                return ret;
 
@@ -1453,7 +1469,7 @@ static int flash_dev_run(struct cache_set *c, struct uuid_entry *u)
        kobject_init(&d->kobj, &bch_flash_dev_ktype);
 
        if (bcache_device_init(d, block_bytes(c), u->sectors,
-                       flash_dev_make_request))
+                       flash_dev_make_request, NULL))
                goto err;
 
        bcache_device_attach(d, c, u - c->uuids);
@@ -2364,7 +2380,7 @@ static bool bch_is_open(struct block_device *bdev)
 }
 
 struct async_reg_args {
-       struct work_struct reg_work;
+       struct delayed_work reg_work;
        char *path;
        struct cache_sb *sb;
        struct cache_sb_disk *sb_disk;
@@ -2375,7 +2391,7 @@ static void register_bdev_worker(struct work_struct *work)
 {
        int fail = false;
        struct async_reg_args *args =
-               container_of(work, struct async_reg_args, reg_work);
+               container_of(work, struct async_reg_args, reg_work.work);
        struct cached_dev *dc;
 
        dc = kzalloc(sizeof(*dc), GFP_KERNEL);
@@ -2405,7 +2421,7 @@ static void register_cache_worker(struct work_struct *work)
 {
        int fail = false;
        struct async_reg_args *args =
-               container_of(work, struct async_reg_args, reg_work);
+               container_of(work, struct async_reg_args, reg_work.work);
        struct cache *ca;
 
        ca = kzalloc(sizeof(*ca), GFP_KERNEL);
@@ -2433,11 +2449,12 @@ out:
 static void register_device_aync(struct async_reg_args *args)
 {
        if (SB_IS_BDEV(args->sb))
-               INIT_WORK(&args->reg_work, register_bdev_worker);
+               INIT_DELAYED_WORK(&args->reg_work, register_bdev_worker);
        else
-               INIT_WORK(&args->reg_work, register_cache_worker);
+               INIT_DELAYED_WORK(&args->reg_work, register_cache_worker);
 
-       queue_work(system_wq, &args->reg_work);
+       /* 10 jiffies is enough for a delay */
+       queue_delayed_work(system_wq, &args->reg_work, 10);
 }
 
 static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
index 81dc5ff..a83a1de 100644 (file)
@@ -2420,7 +2420,7 @@ static void integrity_writer(struct work_struct *w)
        unsigned prev_free_sectors;
 
        /* the following test is not needed, but it tests the replay code */
-       if (unlikely(dm_suspended(ic->ti)) && !ic->meta_dev)
+       if (unlikely(dm_post_suspending(ic->ti)) && !ic->meta_dev)
                return;
 
        spin_lock_irq(&ic->endio_wait.lock);
@@ -2481,7 +2481,7 @@ static void integrity_recalc(struct work_struct *w)
 
 next_chunk:
 
-       if (unlikely(dm_suspended(ic->ti)))
+       if (unlikely(dm_post_suspending(ic->ti)))
                goto unlock_ret;
 
        range.logical_sector = le64_to_cpu(ic->sb->recalc_sector);
index ac83f50..489935d 100644 (file)
@@ -1471,7 +1471,7 @@ static void retrieve_deps(struct dm_table *table,
        /*
         * Check we have enough space.
         */
-       needed = sizeof(*deps) + (sizeof(*deps->dev) * count);
+       needed = struct_size(deps, dev, count);
        if (len < needed) {
                param->flags |= DM_BUFFER_FULL_FLAG;
                return;
index f60c025..85e0daa 100644 (file)
@@ -146,10 +146,6 @@ 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(wq_has_sleeper(&md->wait)))
-               wake_up(&md->wait);
-
        /*
         * dm_put() must be at the end of this function. See the comment above
         */
index 74f3c50..5358894 100644 (file)
@@ -282,6 +282,8 @@ static int persistent_memory_claim(struct dm_writecache *wc)
                        while (daa-- && i < p) {
                                pages[i++] = pfn_t_to_page(pfn);
                                pfn.val++;
+                               if (!(i & 15))
+                                       cond_resched();
                        }
                } while (i < p);
                wc->memory_map = vmap(pages, p, VM_MAP, PAGE_KERNEL);
@@ -849,10 +851,14 @@ static void writecache_discard(struct dm_writecache *wc, sector_t start, sector_
 
                if (likely(!e->write_in_progress)) {
                        if (!discarded_something) {
-                               writecache_wait_for_ios(wc, READ);
-                               writecache_wait_for_ios(wc, WRITE);
+                               if (!WC_MODE_PMEM(wc)) {
+                                       writecache_wait_for_ios(wc, READ);
+                                       writecache_wait_for_ios(wc, WRITE);
+                               }
                                discarded_something = true;
                        }
+                       if (!writecache_entry_is_committed(wc, e))
+                               wc->uncommitted_blocks--;
                        writecache_free_entry(wc, e);
                }
 
@@ -2260,6 +2266,12 @@ invalid_optional:
        }
 
        if (WC_MODE_PMEM(wc)) {
+               if (!dax_synchronous(wc->ssd_dev->dax_dev)) {
+                       r = -EOPNOTSUPP;
+                       ti->error = "Asynchronous persistent memory not supported as pmem cache";
+                       goto bad;
+               }
+
                r = persistent_memory_claim(wc);
                if (r) {
                        ti->error = "Unable to map persistent memory for cache";
index 130b5a6..b298fef 100644 (file)
@@ -1078,7 +1078,8 @@ static int dmz_check_sb(struct dmz_metadata *zmd, struct dmz_sb *dsb,
        nr_meta_zones = (le32_to_cpu(sb->nr_meta_blocks) + zmd->zone_nr_blocks - 1)
                >> zmd->zone_nr_blocks_shift;
        if (!nr_meta_zones ||
-           nr_meta_zones >= zmd->nr_rnd_zones) {
+           (zmd->nr_devs <= 1 && nr_meta_zones >= zmd->nr_rnd_zones) ||
+           (zmd->nr_devs > 1 && nr_meta_zones >= zmd->nr_cache_zones)) {
                dmz_dev_err(dev, "Invalid number of metadata blocks");
                return -ENXIO;
        }
@@ -1949,7 +1950,7 @@ static struct dm_zone *dmz_get_rnd_zone_for_reclaim(struct dmz_metadata *zmd,
                                                    unsigned int idx, bool idle)
 {
        struct dm_zone *dzone = NULL;
-       struct dm_zone *zone, *last = NULL;
+       struct dm_zone *zone, *maxw_z = NULL;
        struct list_head *zone_list;
 
        /* If we have cache zones select from the cache zone list */
@@ -1961,18 +1962,37 @@ static struct dm_zone *dmz_get_rnd_zone_for_reclaim(struct dmz_metadata *zmd,
        } else
                zone_list = &zmd->dev[idx].map_rnd_list;
 
+       /*
+        * Find the buffer zone with the heaviest weight or the first (oldest)
+        * data zone that can be reclaimed.
+        */
        list_for_each_entry(zone, zone_list, link) {
                if (dmz_is_buf(zone)) {
                        dzone = zone->bzone;
-                       if (dzone->dev->dev_idx != idx)
-                               continue;
-                       if (!last) {
-                               last = dzone;
+                       if (dmz_is_rnd(dzone) && dzone->dev->dev_idx != idx)
                                continue;
-                       }
-                       if (last->weight < dzone->weight)
+                       if (!maxw_z || maxw_z->weight < dzone->weight)
+                               maxw_z = dzone;
+               } else {
+                       dzone = zone;
+                       if (dmz_lock_zone_reclaim(dzone))
+                               return dzone;
+               }
+       }
+
+       if (maxw_z && dmz_lock_zone_reclaim(maxw_z))
+               return maxw_z;
+
+       /*
+        * If we come here, none of the zones inspected could be locked for
+        * reclaim. Try again, being more aggressive, that is, find the
+        * first zone that can be reclaimed regardless of its weitght.
+        */
+       list_for_each_entry(zone, zone_list, link) {
+               if (dmz_is_buf(zone)) {
+                       dzone = zone->bzone;
+                       if (dmz_is_rnd(dzone) && dzone->dev->dev_idx != idx)
                                continue;
-                       dzone = last;
                } else
                        dzone = zone;
                if (dmz_lock_zone_reclaim(dzone))
@@ -2006,7 +2026,7 @@ static struct dm_zone *dmz_get_seq_zone_for_reclaim(struct dmz_metadata *zmd,
 struct dm_zone *dmz_get_zone_for_reclaim(struct dmz_metadata *zmd,
                                         unsigned int dev_idx, bool idle)
 {
-       struct dm_zone *zone;
+       struct dm_zone *zone = NULL;
 
        /*
         * Search for a zone candidate to reclaim: 2 cases are possible.
@@ -2019,7 +2039,7 @@ struct dm_zone *dmz_get_zone_for_reclaim(struct dmz_metadata *zmd,
        dmz_lock_map(zmd);
        if (list_empty(&zmd->reserved_seq_zones_list))
                zone = dmz_get_seq_zone_for_reclaim(zmd, dev_idx);
-       else
+       if (!zone)
                zone = dmz_get_rnd_zone_for_reclaim(zmd, dev_idx, idle);
        dmz_unlock_map(zmd);
 
@@ -2197,8 +2217,15 @@ struct dm_zone *dmz_alloc_zone(struct dmz_metadata *zmd, unsigned int dev_idx,
 {
        struct list_head *list;
        struct dm_zone *zone;
-       int i = 0;
+       int i;
+
+       /* Schedule reclaim to ensure free zones are available */
+       if (!(flags & DMZ_ALLOC_RECLAIM)) {
+               for (i = 0; i < zmd->nr_devs; i++)
+                       dmz_schedule_reclaim(zmd->dev[i].reclaim);
+       }
 
+       i = 0;
 again:
        if (flags & DMZ_ALLOC_CACHE)
                list = &zmd->unmap_cache_list;
index 2261b4d..9c0ecc9 100644 (file)
@@ -377,6 +377,7 @@ static int dmz_do_reclaim(struct dmz_reclaim *zrc)
                        dmz_metadata_label(zmd), zrc->dev_idx);
                return -EBUSY;
        }
+       rzone = dzone;
 
        start = jiffies;
        if (dmz_is_cache(dzone) || dmz_is_rnd(dzone)) {
@@ -391,8 +392,6 @@ static int dmz_do_reclaim(struct dmz_reclaim *zrc)
                         */
                        ret = dmz_reclaim_rnd_data(zrc, dzone);
                }
-               rzone = dzone;
-
        } else {
                struct dm_zone *bzone = dzone->bzone;
                sector_t chunk_block = 0;
@@ -415,7 +414,6 @@ static int dmz_do_reclaim(struct dmz_reclaim *zrc)
                         * be later reclaimed.
                         */
                        ret = dmz_reclaim_seq_data(zrc, dzone);
-                       rzone = dzone;
                }
        }
 out:
@@ -458,6 +456,8 @@ static unsigned int dmz_reclaim_percentage(struct dmz_reclaim *zrc)
                nr_zones = dmz_nr_rnd_zones(zmd, zrc->dev_idx);
                nr_unmap = dmz_nr_unmap_rnd_zones(zmd, zrc->dev_idx);
        }
+       if (nr_unmap <= 1)
+               return 0;
        return nr_unmap * 100 / nr_zones;
 }
 
@@ -503,7 +503,7 @@ static void dmz_reclaim_work(struct work_struct *work)
 {
        struct dmz_reclaim *zrc = container_of(work, struct dmz_reclaim, work.work);
        struct dmz_metadata *zmd = zrc->metadata;
-       unsigned int p_unmap, nr_unmap_rnd = 0, nr_rnd = 0;
+       unsigned int p_unmap;
        int ret;
 
        if (dmz_dev_is_dying(zmd))
@@ -529,9 +529,6 @@ static void dmz_reclaim_work(struct work_struct *work)
                zrc->kc_throttle.throttle = min(75U, 100U - p_unmap / 2);
        }
 
-       nr_unmap_rnd = dmz_nr_unmap_rnd_zones(zmd, zrc->dev_idx);
-       nr_rnd = dmz_nr_rnd_zones(zmd, zrc->dev_idx);
-
        DMDEBUG("(%s/%u): Reclaim (%u): %s, %u%% free zones (%u/%u cache %u/%u random)",
                dmz_metadata_label(zmd), zrc->dev_idx,
                zrc->kc_throttle.throttle,
index a907a94..42aa513 100644 (file)
@@ -400,15 +400,7 @@ static void dmz_handle_bio(struct dmz_target *dmz, struct dm_chunk_work *cw,
                dm_per_bio_data(bio, sizeof(struct dmz_bioctx));
        struct dmz_metadata *zmd = dmz->metadata;
        struct dm_zone *zone;
-       int i, ret;
-
-       /*
-        * Write may trigger a zone allocation. So make sure the
-        * allocation can succeed.
-        */
-       if (bio_op(bio) == REQ_OP_WRITE)
-               for (i = 0; i < dmz->nr_ddevs; i++)
-                       dmz_schedule_reclaim(dmz->dev[i].reclaim);
+       int ret;
 
        dmz_lock_metadata(zmd);
 
@@ -890,7 +882,7 @@ static int dmz_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        }
 
        /* Set target (no write same support) */
-       ti->max_io_len = dmz_zone_nr_sectors(dmz->metadata) << 9;
+       ti->max_io_len = dmz_zone_nr_sectors(dmz->metadata);
        ti->num_flush_bios = 1;
        ti->num_discard_bios = 1;
        ti->num_write_zeroes_bios = 1;
index 109e81f..5b9de2f 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/sched/mm.h>
 #include <linux/sched/signal.h>
 #include <linux/blkpg.h>
 #include <linux/bio.h>
@@ -142,6 +143,7 @@ EXPORT_SYMBOL_GPL(dm_bio_get_target_bio_nr);
 #define DMF_NOFLUSH_SUSPENDING 5
 #define DMF_DEFERRED_REMOVE 6
 #define DMF_SUSPENDED_INTERNALLY 7
+#define DMF_POST_SUSPENDING 8
 
 #define DM_NUMA_NODE NUMA_NO_NODE
 static int dm_numa_node = DM_NUMA_NODE;
@@ -654,28 +656,6 @@ static void free_tio(struct dm_target_io *tio)
        bio_put(&tio->clone);
 }
 
-static bool md_in_flight_bios(struct mapped_device *md)
-{
-       int cpu;
-       struct hd_struct *part = &dm_disk(md)->part0;
-       long sum = 0;
-
-       for_each_possible_cpu(cpu) {
-               sum += part_stat_local_read_cpu(part, in_flight[0], cpu);
-               sum += part_stat_local_read_cpu(part, in_flight[1], cpu);
-       }
-
-       return sum != 0;
-}
-
-static bool md_in_flight(struct mapped_device *md)
-{
-       if (queue_is_mq(md->queue))
-               return blk_mq_queue_inflight(md->queue);
-       else
-               return md_in_flight_bios(md);
-}
-
 u64 dm_start_time_ns_from_clone(struct bio *bio)
 {
        struct dm_target_io *tio = container_of(bio, struct dm_target_io, clone);
@@ -1009,6 +989,7 @@ static void clone_endio(struct bio *bio)
        struct dm_io *io = tio->io;
        struct mapped_device *md = tio->io->md;
        dm_endio_fn endio = tio->ti->type->end_io;
+       struct bio *orig_bio = io->orig_bio;
 
        if (unlikely(error == BLK_STS_TARGET) && md->type != DM_TYPE_NVME_BIO_BASED) {
                if (bio_op(bio) == REQ_OP_DISCARD &&
@@ -1022,6 +1003,18 @@ static void clone_endio(struct bio *bio)
                        disable_write_zeroes(md);
        }
 
+       /*
+        * For zone-append bios get offset in zone of the written
+        * sector and add that to the original bio sector pos.
+        */
+       if (bio_op(orig_bio) == REQ_OP_ZONE_APPEND) {
+               sector_t written_sector = bio->bi_iter.bi_sector;
+               struct request_queue *q = orig_bio->bi_disk->queue;
+               u64 mask = (u64)blk_queue_zone_sectors(q) - 1;
+
+               orig_bio->bi_iter.bi_sector += written_sector & mask;
+       }
+
        if (endio) {
                int r = endio(tio->ti, bio, &error);
                switch (r) {
@@ -1452,9 +1445,6 @@ static int __send_empty_flush(struct clone_info *ci)
        BUG_ON(bio_has_data(ci->bio));
        while ((ti = dm_table_get_target(ci->map, target_nr++)))
                __send_duplicate_bios(ci, ti, ti->num_flush_bios, NULL);
-
-       bio_disassociate_blkg(ci->bio);
-
        return 0;
 }
 
@@ -1642,6 +1632,7 @@ static blk_qc_t __split_and_process_bio(struct mapped_device *md,
                ci.bio = &flush_bio;
                ci.sector_count = 0;
                error = __send_empty_flush(&ci);
+               bio_uninit(ci.bio);
                /* dec_pending submits any data associated with flush */
        } else if (op_is_zone_mgmt(bio_op(bio))) {
                ci.bio = bio;
@@ -1716,6 +1707,7 @@ static blk_qc_t __process_bio(struct mapped_device *md, struct dm_table *map,
                ci.bio = &flush_bio;
                ci.sector_count = 0;
                error = __send_empty_flush(&ci);
+               bio_uninit(ci.bio);
                /* dec_pending submits any data associated with flush */
        } else {
                struct dm_target_io *tio;
@@ -2417,6 +2409,7 @@ static void __dm_destroy(struct mapped_device *md, bool wait)
        if (!dm_suspended_md(md)) {
                dm_table_presuspend_targets(map);
                set_bit(DMF_SUSPENDED, &md->flags);
+               set_bit(DMF_POST_SUSPENDING, &md->flags);
                dm_table_postsuspend_targets(map);
        }
        /* dm_put_live_table must be before msleep, otherwise deadlock is possible */
@@ -2457,15 +2450,29 @@ void dm_put(struct mapped_device *md)
 }
 EXPORT_SYMBOL_GPL(dm_put);
 
-static int dm_wait_for_completion(struct mapped_device *md, long task_state)
+static bool md_in_flight_bios(struct mapped_device *md)
+{
+       int cpu;
+       struct hd_struct *part = &dm_disk(md)->part0;
+       long sum = 0;
+
+       for_each_possible_cpu(cpu) {
+               sum += part_stat_local_read_cpu(part, in_flight[0], cpu);
+               sum += part_stat_local_read_cpu(part, in_flight[1], cpu);
+       }
+
+       return sum != 0;
+}
+
+static int dm_wait_for_bios_completion(struct mapped_device *md, long task_state)
 {
        int r = 0;
        DEFINE_WAIT(wait);
 
-       while (1) {
+       while (true) {
                prepare_to_wait(&md->wait, &wait, task_state);
 
-               if (!md_in_flight(md))
+               if (!md_in_flight_bios(md))
                        break;
 
                if (signal_pending_state(task_state, current)) {
@@ -2480,6 +2487,28 @@ static int dm_wait_for_completion(struct mapped_device *md, long task_state)
        return r;
 }
 
+static int dm_wait_for_completion(struct mapped_device *md, long task_state)
+{
+       int r = 0;
+
+       if (!queue_is_mq(md->queue))
+               return dm_wait_for_bios_completion(md, task_state);
+
+       while (true) {
+               if (!blk_mq_queue_inflight(md->queue))
+                       break;
+
+               if (signal_pending_state(task_state, current)) {
+                       r = -EINTR;
+                       break;
+               }
+
+               msleep(5);
+       }
+
+       return r;
+}
+
 /*
  * Process the deferred bios
  */
@@ -2739,7 +2768,9 @@ retry:
        if (r)
                goto out_unlock;
 
+       set_bit(DMF_POST_SUSPENDING, &md->flags);
        dm_table_postsuspend_targets(map);
+       clear_bit(DMF_POST_SUSPENDING, &md->flags);
 
 out_unlock:
        mutex_unlock(&md->suspend_lock);
@@ -2836,7 +2867,9 @@ static void __dm_internal_suspend(struct mapped_device *md, unsigned suspend_fla
        (void) __dm_suspend(md, map, suspend_flags, TASK_UNINTERRUPTIBLE,
                            DMF_SUSPENDED_INTERNALLY);
 
+       set_bit(DMF_POST_SUSPENDING, &md->flags);
        dm_table_postsuspend_targets(map);
+       clear_bit(DMF_POST_SUSPENDING, &md->flags);
 }
 
 static void __dm_internal_resume(struct mapped_device *md)
@@ -2913,17 +2946,25 @@ EXPORT_SYMBOL_GPL(dm_internal_resume_fast);
 int dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
                       unsigned cookie)
 {
+       int r;
+       unsigned noio_flag;
        char udev_cookie[DM_COOKIE_LENGTH];
        char *envp[] = { udev_cookie, NULL };
 
+       noio_flag = memalloc_noio_save();
+
        if (!cookie)
-               return kobject_uevent(&disk_to_dev(md->disk)->kobj, action);
+               r = kobject_uevent(&disk_to_dev(md->disk)->kobj, action);
        else {
                snprintf(udev_cookie, DM_COOKIE_LENGTH, "%s=%u",
                         DM_COOKIE_ENV_VAR_NAME, cookie);
-               return kobject_uevent_env(&disk_to_dev(md->disk)->kobj,
-                                         action, envp);
+               r = kobject_uevent_env(&disk_to_dev(md->disk)->kobj,
+                                      action, envp);
        }
+
+       memalloc_noio_restore(noio_flag);
+
+       return r;
 }
 
 uint32_t dm_next_uevent_seq(struct mapped_device *md)
@@ -2989,6 +3030,11 @@ int dm_suspended_md(struct mapped_device *md)
        return test_bit(DMF_SUSPENDED, &md->flags);
 }
 
+static int dm_post_suspending_md(struct mapped_device *md)
+{
+       return test_bit(DMF_POST_SUSPENDING, &md->flags);
+}
+
 int dm_suspended_internally_md(struct mapped_device *md)
 {
        return test_bit(DMF_SUSPENDED_INTERNALLY, &md->flags);
@@ -3005,6 +3051,12 @@ int dm_suspended(struct dm_target *ti)
 }
 EXPORT_SYMBOL_GPL(dm_suspended);
 
+int dm_post_suspending(struct dm_target *ti)
+{
+       return dm_post_suspending_md(dm_table_get_md(ti->table));
+}
+EXPORT_SYMBOL_GPL(dm_post_suspending);
+
 int dm_noflush_suspending(struct dm_target *ti)
 {
        return __noflush_suspending(dm_table_get_md(ti->table));
index a4ee6b8..b91e472 100644 (file)
@@ -39,8 +39,6 @@
  *     Troy Laramy <t-laramy@ti.com>
  */
 
-#include <asm/cacheflush.h>
-
 #include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/delay.h>
index 10c214b..1ac9aef 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#include <asm/cacheflush.h>
 
 #include <media/v4l2-dev.h>
 #include <media/v4l2-ioctl.h>
index 3362962..b02a3c7 100644 (file)
@@ -193,7 +193,7 @@ struct pwc_raw_frame {
                                   decompressor) */
        __u8   cmd[4];          /* the four byte of the command (in case of
                                   nala, only the first 3 bytes is filled) */
-       __u8   rawframe[0];     /* frame_size = H / 4 * vbandlength */
+       __u8   rawframe[];      /* frame_size = H / 4 * vbandlength */
 } __packed;
 
 /* intermediate buffers with raw data from the USB cam */
index 68aea22..5216487 100644 (file)
@@ -1324,13 +1324,13 @@ mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
                        return 0; /* fw doesn't need any host buffers */
 
                /* spin till we get enough memory */
-               while(host_page_buffer_sz > 0) {
-
-                       if((ioc->HostPageBuffer = pci_alloc_consistent(
-                           ioc->pcidev,
-                           host_page_buffer_sz,
-                           &ioc->HostPageBuffer_dma)) != NULL) {
-
+               while (host_page_buffer_sz > 0) {
+                       ioc->HostPageBuffer =
+                               dma_alloc_coherent(&ioc->pcidev->dev,
+                                               host_page_buffer_sz,
+                                               &ioc->HostPageBuffer_dma,
+                                               GFP_KERNEL);
+                       if (ioc->HostPageBuffer) {
                                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
                                    "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
                                    ioc->name, ioc->HostPageBuffer,
@@ -2741,8 +2741,8 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
                sz = ioc->alloc_sz;
                dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "free  @ %p, sz=%d bytes\n",
                    ioc->name, ioc->alloc, ioc->alloc_sz));
-               pci_free_consistent(ioc->pcidev, sz,
-                               ioc->alloc, ioc->alloc_dma);
+               dma_free_coherent(&ioc->pcidev->dev, sz, ioc->alloc,
+                               ioc->alloc_dma);
                ioc->reply_frames = NULL;
                ioc->req_frames = NULL;
                ioc->alloc = NULL;
@@ -2751,8 +2751,8 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
 
        if (ioc->sense_buf_pool != NULL) {
                sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
-               pci_free_consistent(ioc->pcidev, sz,
-                               ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
+               dma_free_coherent(&ioc->pcidev->dev, sz, ioc->sense_buf_pool,
+                               ioc->sense_buf_pool_dma);
                ioc->sense_buf_pool = NULL;
                ioc->alloc_total -= sz;
        }
@@ -2802,7 +2802,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
                        "HostPageBuffer free  @ %p, sz=%d bytes\n",
                        ioc->name, ioc->HostPageBuffer,
                        ioc->HostPageBuffer_sz));
-               pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
+               dma_free_coherent(&ioc->pcidev->dev, ioc->HostPageBuffer_sz,
                    ioc->HostPageBuffer, ioc->HostPageBuffer_dma);
                ioc->HostPageBuffer = NULL;
                ioc->HostPageBuffer_sz = 0;
@@ -4497,7 +4497,8 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
                                ioc->name, sz, sz, num_chain));
 
                total_size += sz;
-               mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
+               mem = dma_alloc_coherent(&ioc->pcidev->dev, total_size,
+                               &alloc_dma, GFP_KERNEL);
                if (mem == NULL) {
                        printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
                                ioc->name);
@@ -4574,8 +4575,8 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
                spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
                sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
-               ioc->sense_buf_pool =
-                       pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
+               ioc->sense_buf_pool = dma_alloc_coherent(&ioc->pcidev->dev, sz,
+                               &ioc->sense_buf_pool_dma, GFP_KERNEL);
                if (ioc->sense_buf_pool == NULL) {
                        printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
                                ioc->name);
@@ -4613,18 +4614,16 @@ out_fail:
 
        if (ioc->alloc != NULL) {
                sz = ioc->alloc_sz;
-               pci_free_consistent(ioc->pcidev,
-                               sz,
-                               ioc->alloc, ioc->alloc_dma);
+               dma_free_coherent(&ioc->pcidev->dev, sz, ioc->alloc,
+                               ioc->alloc_dma);
                ioc->reply_frames = NULL;
                ioc->req_frames = NULL;
                ioc->alloc_total -= sz;
        }
        if (ioc->sense_buf_pool != NULL) {
                sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
-               pci_free_consistent(ioc->pcidev,
-                               sz,
-                               ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
+               dma_free_coherent(&ioc->pcidev->dev, sz, ioc->sense_buf_pool,
+                               ioc->sense_buf_pool_dma);
                ioc->sense_buf_pool = NULL;
        }
 
index f0737c5..1491561 100644 (file)
@@ -118,8 +118,6 @@ int                 mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
 int            mptscsih_resume(struct pci_dev *pdev);
 #endif
 
-#define SNS_LEN(scp)   SCSI_SENSE_BUFFERSIZE
-
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -2422,7 +2420,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
                /* Copy the sense received into the scsi command block. */
                req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
                sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
-               memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
+               memcpy(sc->sense_buffer, sense_data, MPT_SENSE_BUFFER_ALLOC);
 
                /* Log SMART data (asc = 0x5D, non-IM case only) if required.
                 */
index 02998d4..74cee7c 100644 (file)
@@ -142,10 +142,11 @@ static int ioc3_irq_domain_setup(struct ioc3_priv_data *ipd, int irq)
                goto err;
 
        domain = irq_domain_create_linear(fn, 24, &ioc3_irq_domain_ops, ipd);
-       if (!domain)
+       if (!domain) {
+               irq_domain_free_fwnode(fn);
                goto err;
+       }
 
-       irq_domain_free_fwnode(fn);
        ipd->domain = domain;
 
        irq_set_chained_handler_and_data(irq, ioc3_irq_handler, domain);
index db8cdf5..e9cacc2 100644 (file)
@@ -412,6 +412,7 @@ MODULE_DEVICE_TABLE(of, mt6360_pmu_of_id);
 
 static struct i2c_driver mt6360_pmu_driver = {
        .driver = {
+               .name = "mt6360_pmu",
                .pm = &mt6360_pmu_pm_ops,
                .of_match_table = of_match_ptr(mt6360_pmu_of_id),
        },
index ab4144e..d6cd553 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
-#include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/atmel-ssc.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -20,7 +20,7 @@
 #include "../../sound/soc/atmel/atmel_ssc_dai.h"
 
 /* Serialize access to ssc_list and user count */
-static DEFINE_SPINLOCK(user_lock);
+static DEFINE_MUTEX(user_lock);
 static LIST_HEAD(ssc_list);
 
 struct ssc_device *ssc_request(unsigned int ssc_num)
@@ -28,7 +28,7 @@ struct ssc_device *ssc_request(unsigned int ssc_num)
        int ssc_valid = 0;
        struct ssc_device *ssc;
 
-       spin_lock(&user_lock);
+       mutex_lock(&user_lock);
        list_for_each_entry(ssc, &ssc_list, list) {
                if (ssc->pdev->dev.of_node) {
                        if (of_alias_get_id(ssc->pdev->dev.of_node, "ssc")
@@ -44,18 +44,18 @@ struct ssc_device *ssc_request(unsigned int ssc_num)
        }
 
        if (!ssc_valid) {
-               spin_unlock(&user_lock);
+               mutex_unlock(&user_lock);
                pr_err("ssc: ssc%d platform device is missing\n", ssc_num);
                return ERR_PTR(-ENODEV);
        }
 
        if (ssc->user) {
-               spin_unlock(&user_lock);
+               mutex_unlock(&user_lock);
                dev_dbg(&ssc->pdev->dev, "module busy\n");
                return ERR_PTR(-EBUSY);
        }
        ssc->user++;
-       spin_unlock(&user_lock);
+       mutex_unlock(&user_lock);
 
        clk_prepare(ssc->clk);
 
@@ -67,14 +67,14 @@ void ssc_free(struct ssc_device *ssc)
 {
        bool disable_clk = true;
 
-       spin_lock(&user_lock);
+       mutex_lock(&user_lock);
        if (ssc->user)
                ssc->user--;
        else {
                disable_clk = false;
                dev_dbg(&ssc->pdev->dev, "device already free\n");
        }
-       spin_unlock(&user_lock);
+       mutex_unlock(&user_lock);
 
        if (disable_clk)
                clk_unprepare(ssc->clk);
@@ -237,9 +237,9 @@ static int ssc_probe(struct platform_device *pdev)
                return -ENXIO;
        }
 
-       spin_lock(&user_lock);
+       mutex_lock(&user_lock);
        list_add_tail(&ssc->list, &ssc_list);
-       spin_unlock(&user_lock);
+       mutex_unlock(&user_lock);
 
        platform_set_drvdata(pdev, ssc);
 
@@ -258,9 +258,9 @@ static int ssc_remove(struct platform_device *pdev)
 
        ssc_sound_dai_remove(ssc);
 
-       spin_lock(&user_lock);
+       mutex_lock(&user_lock);
        list_del(&ssc->list);
-       spin_unlock(&user_lock);
+       mutex_unlock(&user_lock);
 
        return 0;
 }
index f82974a..f3a8f11 100644 (file)
@@ -62,6 +62,12 @@ static void hl_fence_release(struct dma_fence *fence)
                container_of(fence, struct hl_cs_compl, base_fence);
        struct hl_device *hdev = hl_cs_cmpl->hdev;
 
+       /* EBUSY means the CS was never submitted and hence we don't have
+        * an attached hw_sob object that we should handle here
+        */
+       if (fence->error == -EBUSY)
+               goto free;
+
        if ((hl_cs_cmpl->type == CS_TYPE_SIGNAL) ||
                        (hl_cs_cmpl->type == CS_TYPE_WAIT)) {
 
@@ -92,6 +98,7 @@ static void hl_fence_release(struct dma_fence *fence)
                kref_put(&hl_cs_cmpl->hw_sob->kref, hl_sob_reset);
        }
 
+free:
        kfree_rcu(hl_cs_cmpl, base_fence.rcu);
 }
 
@@ -328,10 +335,16 @@ static void cs_do_release(struct kref *ref)
 
        hl_ctx_put(cs->ctx);
 
+       /* We need to mark an error for not submitted because in that case
+        * the dma fence release flow is different. Mainly, we don't need
+        * to handle hw_sob for signal/wait
+        */
        if (cs->timedout)
                dma_fence_set_error(cs->fence, -ETIMEDOUT);
        else if (cs->aborted)
                dma_fence_set_error(cs->fence, -EIO);
+       else if (!cs->submitted)
+               dma_fence_set_error(cs->fence, -EBUSY);
 
        dma_fence_signal(cs->fence);
        dma_fence_put(cs->fence);
@@ -486,11 +499,19 @@ static int validate_queue_index(struct hl_device *hdev,
        struct asic_fixed_properties *asic = &hdev->asic_prop;
        struct hw_queue_properties *hw_queue_prop;
 
+       /* This must be checked here to prevent out-of-bounds access to
+        * hw_queues_props array
+        */
+       if (chunk->queue_index >= HL_MAX_QUEUES) {
+               dev_err(hdev->dev, "Queue index %d is invalid\n",
+                       chunk->queue_index);
+               return -EINVAL;
+       }
+
        hw_queue_prop = &asic->hw_queues_props[chunk->queue_index];
 
-       if ((chunk->queue_index >= HL_MAX_QUEUES) ||
-                       (hw_queue_prop->type == QUEUE_TYPE_NA)) {
-               dev_err(hdev->dev, "Queue index %d is invalid\n",
+       if (hw_queue_prop->type == QUEUE_TYPE_NA) {
+               dev_err(hdev->dev, "Queue index %d is not applicable\n",
                        chunk->queue_index);
                return -EINVAL;
        }
index 3c8dcdf..0bc036e 100644 (file)
@@ -36,7 +36,7 @@ static int hl_debugfs_i2c_read(struct hl_device *hdev, u8 i2c_bus, u8 i2c_addr,
        pkt.i2c_reg = i2c_reg;
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
-                                       HL_DEVICE_TIMEOUT_USEC, (long *) val);
+                                               0, (long *) val);
 
        if (rc)
                dev_err(hdev->dev, "Failed to read from I2C, error %d\n", rc);
@@ -63,7 +63,7 @@ static int hl_debugfs_i2c_write(struct hl_device *hdev, u8 i2c_bus, u8 i2c_addr,
        pkt.value = cpu_to_le64(val);
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
-                                       HL_DEVICE_TIMEOUT_USEC, NULL);
+                                               0, NULL);
 
        if (rc)
                dev_err(hdev->dev, "Failed to write to I2C, error %d\n", rc);
@@ -87,7 +87,7 @@ static void hl_debugfs_led_set(struct hl_device *hdev, u8 led, u8 state)
        pkt.value = cpu_to_le64(state);
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
-                                               HL_DEVICE_TIMEOUT_USEC, NULL);
+                                               0, NULL);
 
        if (rc)
                dev_err(hdev->dev, "Failed to set LED %d, error %d\n", led, rc);
@@ -480,7 +480,7 @@ out:
        return 0;
 }
 
-static ssize_t mmu_write(struct file *file, const char __user *buf,
+static ssize_t mmu_asid_va_write(struct file *file, const char __user *buf,
                size_t count, loff_t *f_pos)
 {
        struct seq_file *s = file->private_data;
@@ -981,7 +981,7 @@ static ssize_t hl_clk_gate_read(struct file *f, char __user *buf,
        if (*ppos)
                return 0;
 
-       sprintf(tmp_buf, "%d\n", hdev->clock_gating);
+       sprintf(tmp_buf, "0x%llx\n", hdev->clock_gating_mask);
        rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf,
                        strlen(tmp_buf) + 1);
 
@@ -993,7 +993,7 @@ static ssize_t hl_clk_gate_write(struct file *f, const char __user *buf,
 {
        struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
        struct hl_device *hdev = entry->hdev;
-       u32 value;
+       u64 value;
        ssize_t rc;
 
        if (atomic_read(&hdev->in_reset)) {
@@ -1002,19 +1002,12 @@ static ssize_t hl_clk_gate_write(struct file *f, const char __user *buf,
                return 0;
        }
 
-       rc = kstrtouint_from_user(buf, count, 10, &value);
+       rc = kstrtoull_from_user(buf, count, 16, &value);
        if (rc)
                return rc;
 
-       if (value) {
-               hdev->clock_gating = 1;
-               if (hdev->asic_funcs->enable_clock_gating)
-                       hdev->asic_funcs->enable_clock_gating(hdev);
-       } else {
-               if (hdev->asic_funcs->disable_clock_gating)
-                       hdev->asic_funcs->disable_clock_gating(hdev);
-               hdev->clock_gating = 0;
-       }
+       hdev->clock_gating_mask = value;
+       hdev->asic_funcs->set_clock_gating(hdev);
 
        return count;
 }
@@ -1125,7 +1118,7 @@ static const struct hl_info_list hl_debugfs_list[] = {
        {"command_submission_jobs", command_submission_jobs_show, NULL},
        {"userptr", userptr_show, NULL},
        {"vm", vm_show, NULL},
-       {"mmu", mmu_show, mmu_write},
+       {"mmu", mmu_show, mmu_asid_va_write},
        {"engines", engines_show, NULL}
 };
 
index 2b38a11..59608d1 100644 (file)
@@ -608,7 +608,7 @@ int hl_device_set_debug_mode(struct hl_device *hdev, bool enable)
                hdev->in_debug = 0;
 
                if (!hdev->hard_reset_pending)
-                       hdev->asic_funcs->enable_clock_gating(hdev);
+                       hdev->asic_funcs->set_clock_gating(hdev);
 
                goto out;
        }
index baf790c..d27841c 100644 (file)
@@ -61,7 +61,7 @@ int hl_fw_send_pci_access_msg(struct hl_device *hdev, u32 opcode)
        pkt.ctl = cpu_to_le32(opcode << ARMCP_PKT_CTL_OPCODE_SHIFT);
 
        return hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt,
-                               sizeof(pkt), HL_DEVICE_TIMEOUT_USEC, NULL);
+                                               sizeof(pkt), 0, NULL);
 }
 
 int hl_fw_send_cpu_message(struct hl_device *hdev, u32 hw_queue_id, u32 *msg,
@@ -144,7 +144,7 @@ int hl_fw_unmask_irq(struct hl_device *hdev, u16 event_type)
        pkt.value = cpu_to_le64(event_type);
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
-                       HL_DEVICE_TIMEOUT_USEC, &result);
+                                               0, &result);
 
        if (rc)
                dev_err(hdev->dev, "failed to unmask RAZWI IRQ %d", event_type);
@@ -183,7 +183,7 @@ int hl_fw_unmask_irq_arr(struct hl_device *hdev, const u32 *irq_arr,
                                                ARMCP_PKT_CTL_OPCODE_SHIFT);
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) pkt,
-                       total_pkt_size, HL_DEVICE_TIMEOUT_USEC, &result);
+                                               total_pkt_size, 0, &result);
 
        if (rc)
                dev_err(hdev->dev, "failed to unmask IRQ array\n");
@@ -204,7 +204,7 @@ int hl_fw_test_cpu_queue(struct hl_device *hdev)
        test_pkt.value = cpu_to_le64(ARMCP_PACKET_FENCE_VAL);
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &test_pkt,
-                       sizeof(test_pkt), HL_DEVICE_TIMEOUT_USEC, &result);
+                                               sizeof(test_pkt), 0, &result);
 
        if (!rc) {
                if (result != ARMCP_PACKET_FENCE_VAL)
@@ -248,7 +248,7 @@ int hl_fw_send_heartbeat(struct hl_device *hdev)
        hb_pkt.value = cpu_to_le64(ARMCP_PACKET_FENCE_VAL);
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &hb_pkt,
-                       sizeof(hb_pkt), HL_DEVICE_TIMEOUT_USEC, &result);
+                                               sizeof(hb_pkt), 0, &result);
 
        if ((rc) || (result != ARMCP_PACKET_FENCE_VAL))
                rc = -EIO;
index 61f88e9..637a9d6 100644 (file)
@@ -80,6 +80,7 @@
 #define GAUDI_PLDM_QMAN0_TIMEOUT_USEC  (HL_DEVICE_TIMEOUT_USEC * 30)
 #define GAUDI_PLDM_TPC_KERNEL_WAIT_USEC        (HL_DEVICE_TIMEOUT_USEC * 30)
 #define GAUDI_BOOT_FIT_REQ_TIMEOUT_USEC        1000000         /* 1s */
+#define GAUDI_MSG_TO_CPU_TIMEOUT_USEC  4000000         /* 4s */
 
 #define GAUDI_QMAN0_FENCE_VAL          0x72E91AB9
 
 
 #define GAUDI_NUM_OF_QM_ARB_ERR_CAUSE  3
 
-#define GAUDI_ARB_WDT_TIMEOUT          0x400000
+#define GAUDI_ARB_WDT_TIMEOUT          0x1000000
+
+#define GAUDI_CLK_GATE_DEBUGFS_MASK    (\
+               BIT(GAUDI_ENGINE_ID_MME_0) |\
+               BIT(GAUDI_ENGINE_ID_MME_2) |\
+               GENMASK_ULL(GAUDI_ENGINE_ID_TPC_7, GAUDI_ENGINE_ID_TPC_0))
 
 static const char gaudi_irq_name[GAUDI_MSI_ENTRIES][GAUDI_MAX_STRING_LEN] = {
                "gaudi cq 0_0", "gaudi cq 0_1", "gaudi cq 0_2", "gaudi cq 0_3",
@@ -106,14 +112,14 @@ static const char gaudi_irq_name[GAUDI_MSI_ENTRIES][GAUDI_MAX_STRING_LEN] = {
 };
 
 static const u8 gaudi_dma_assignment[GAUDI_DMA_MAX] = {
-       [GAUDI_PCI_DMA_1] = 0,
-       [GAUDI_PCI_DMA_2] = 1,
-       [GAUDI_PCI_DMA_3] = 5,
-       [GAUDI_HBM_DMA_1] = 2,
-       [GAUDI_HBM_DMA_2] = 3,
-       [GAUDI_HBM_DMA_3] = 4,
-       [GAUDI_HBM_DMA_4] = 6,
-       [GAUDI_HBM_DMA_5] = 7
+       [GAUDI_PCI_DMA_1] = GAUDI_ENGINE_ID_DMA_0,
+       [GAUDI_PCI_DMA_2] = GAUDI_ENGINE_ID_DMA_1,
+       [GAUDI_PCI_DMA_3] = GAUDI_ENGINE_ID_DMA_5,
+       [GAUDI_HBM_DMA_1] = GAUDI_ENGINE_ID_DMA_2,
+       [GAUDI_HBM_DMA_2] = GAUDI_ENGINE_ID_DMA_3,
+       [GAUDI_HBM_DMA_3] = GAUDI_ENGINE_ID_DMA_4,
+       [GAUDI_HBM_DMA_4] = GAUDI_ENGINE_ID_DMA_6,
+       [GAUDI_HBM_DMA_5] = GAUDI_ENGINE_ID_DMA_7
 };
 
 static const u8 gaudi_cq_assignment[NUMBER_OF_CMPLT_QUEUES] = {
@@ -1819,7 +1825,7 @@ static void gaudi_init_golden_registers(struct hl_device *hdev)
 
        gaudi_init_rate_limiter(hdev);
 
-       gaudi_disable_clock_gating(hdev);
+       hdev->asic_funcs->disable_clock_gating(hdev);
 
        for (tpc_id = 0, tpc_offset = 0;
                                tpc_id < TPC_NUMBER_OF_ENGINES;
@@ -1893,6 +1899,8 @@ static void gaudi_init_pci_dma_qman(struct hl_device *hdev, int dma_id,
        WREG32(mmDMA0_QM_CP_MSG_BASE3_ADDR_LO_0 + q_off, so_base_ws_lo);
        WREG32(mmDMA0_QM_CP_MSG_BASE3_ADDR_HI_0 + q_off, so_base_ws_hi);
 
+       WREG32(mmDMA0_QM_CP_BARRIER_CFG_0 + q_off, 0x100);
+
        /* The following configuration is needed only once per QMAN */
        if (qman_id == 0) {
                /* Configure RAZWI IRQ */
@@ -2529,46 +2537,55 @@ static void gaudi_tpc_stall(struct hl_device *hdev)
        WREG32(mmTPC7_CFG_TPC_STALL, 1 << TPC0_CFG_TPC_STALL_V_SHIFT);
 }
 
-static void gaudi_enable_clock_gating(struct hl_device *hdev)
+static void gaudi_set_clock_gating(struct hl_device *hdev)
 {
        struct gaudi_device *gaudi = hdev->asic_specific;
        u32 qman_offset;
        int i;
 
-       if (!hdev->clock_gating)
-               return;
-
-       if (gaudi->hw_cap_initialized & HW_CAP_CLK_GATE)
-               return;
-
        /* In case we are during debug session, don't enable the clock gate
         * as it may interfere
         */
        if (hdev->in_debug)
                return;
 
-       for (i = 0, qman_offset = 0 ; i < PCI_DMA_NUMBER_OF_CHNLS ; i++) {
+       for (i = GAUDI_PCI_DMA_1, qman_offset = 0 ; i < GAUDI_HBM_DMA_1 ; i++) {
+               if (!(hdev->clock_gating_mask &
+                                       (BIT_ULL(gaudi_dma_assignment[i]))))
+                       continue;
+
                qman_offset = gaudi_dma_assignment[i] * DMA_QMAN_OFFSET;
                WREG32(mmDMA0_QM_CGM_CFG1 + qman_offset, QMAN_CGM1_PWR_GATE_EN);
                WREG32(mmDMA0_QM_CGM_CFG + qman_offset,
                                QMAN_UPPER_CP_CGM_PWR_GATE_EN);
        }
 
-       for (; i < HBM_DMA_NUMBER_OF_CHNLS ; i++) {
+       for (i = GAUDI_HBM_DMA_1 ; i < GAUDI_DMA_MAX ; i++) {
+               if (!(hdev->clock_gating_mask &
+                                       (BIT_ULL(gaudi_dma_assignment[i]))))
+                       continue;
+
                qman_offset = gaudi_dma_assignment[i] * DMA_QMAN_OFFSET;
                WREG32(mmDMA0_QM_CGM_CFG1 + qman_offset, QMAN_CGM1_PWR_GATE_EN);
                WREG32(mmDMA0_QM_CGM_CFG + qman_offset,
                                QMAN_COMMON_CP_CGM_PWR_GATE_EN);
        }
 
-       WREG32(mmMME0_QM_CGM_CFG1, QMAN_CGM1_PWR_GATE_EN);
-       WREG32(mmMME0_QM_CGM_CFG,
-                       QMAN_COMMON_CP_CGM_PWR_GATE_EN);
-       WREG32(mmMME2_QM_CGM_CFG1, QMAN_CGM1_PWR_GATE_EN);
-       WREG32(mmMME2_QM_CGM_CFG,
-                       QMAN_COMMON_CP_CGM_PWR_GATE_EN);
+       if (hdev->clock_gating_mask & (BIT_ULL(GAUDI_ENGINE_ID_MME_0))) {
+               WREG32(mmMME0_QM_CGM_CFG1, QMAN_CGM1_PWR_GATE_EN);
+               WREG32(mmMME0_QM_CGM_CFG, QMAN_COMMON_CP_CGM_PWR_GATE_EN);
+       }
+
+       if (hdev->clock_gating_mask & (BIT_ULL(GAUDI_ENGINE_ID_MME_2))) {
+               WREG32(mmMME2_QM_CGM_CFG1, QMAN_CGM1_PWR_GATE_EN);
+               WREG32(mmMME2_QM_CGM_CFG, QMAN_COMMON_CP_CGM_PWR_GATE_EN);
+       }
 
        for (i = 0, qman_offset = 0 ; i < TPC_NUMBER_OF_ENGINES ; i++) {
+               if (!(hdev->clock_gating_mask &
+                                       (BIT_ULL(GAUDI_ENGINE_ID_TPC_0 + i))))
+                       continue;
+
                WREG32(mmTPC0_QM_CGM_CFG1 + qman_offset,
                                QMAN_CGM1_PWR_GATE_EN);
                WREG32(mmTPC0_QM_CGM_CFG + qman_offset,
@@ -2661,7 +2678,7 @@ static void gaudi_halt_engines(struct hl_device *hdev, bool hard_reset)
        gaudi_stop_hbm_dma_qmans(hdev);
        gaudi_stop_pci_dma_qmans(hdev);
 
-       gaudi_disable_clock_gating(hdev);
+       hdev->asic_funcs->disable_clock_gating(hdev);
 
        msleep(wait_timeout_ms);
 
@@ -2725,6 +2742,12 @@ static int gaudi_mmu_init(struct hl_device *hdev)
        WREG32(mmSTLB_HOP_CONFIGURATION,
                        hdev->mmu_huge_page_opt ? 0x30440 : 0x40440);
 
+       /*
+        * The H/W expects the first PI after init to be 1. After wraparound
+        * we'll write 0.
+        */
+       gaudi->mmu_cache_inv_pi = 1;
+
        gaudi->hw_cap_initialized |= HW_CAP_MMU;
 
        return 0;
@@ -2995,7 +3018,7 @@ static int gaudi_hw_init(struct hl_device *hdev)
 
        gaudi_init_tpc_qmans(hdev);
 
-       gaudi_enable_clock_gating(hdev);
+       hdev->asic_funcs->set_clock_gating(hdev);
 
        gaudi_enable_timestamp(hdev);
 
@@ -3104,7 +3127,9 @@ static void gaudi_hw_fini(struct hl_device *hdev, bool hard_reset)
                                        HW_CAP_HBM_DMA | HW_CAP_PLL |
                                        HW_CAP_MMU |
                                        HW_CAP_SRAM_SCRAMBLER |
-                                       HW_CAP_HBM_SCRAMBLER);
+                                       HW_CAP_HBM_SCRAMBLER |
+                                       HW_CAP_CLK_GATE);
+
        memset(gaudi->events_stat, 0, sizeof(gaudi->events_stat));
 }
 
@@ -3455,6 +3480,9 @@ static int gaudi_send_cpu_message(struct hl_device *hdev, u32 *msg,
                return 0;
        }
 
+       if (!timeout)
+               timeout = GAUDI_MSG_TO_CPU_TIMEOUT_USEC;
+
        return hl_fw_send_cpu_message(hdev, GAUDI_QUEUE_ID_CPU_PQ, msg, len,
                                                timeout, result);
 }
@@ -3790,6 +3818,25 @@ static int gaudi_validate_dma_pkt_no_mmu(struct hl_device *hdev,
                                                src_in_host);
 }
 
+static int gaudi_validate_load_and_exe_pkt(struct hl_device *hdev,
+                                       struct hl_cs_parser *parser,
+                                       struct packet_load_and_exe *user_pkt)
+{
+       u32 cfg;
+
+       cfg = le32_to_cpu(user_pkt->cfg);
+
+       if (cfg & GAUDI_PKT_LOAD_AND_EXE_CFG_DST_MASK) {
+               dev_err(hdev->dev,
+                       "User not allowed to use Load and Execute\n");
+               return -EPERM;
+       }
+
+       parser->patched_cb_size += sizeof(struct packet_load_and_exe);
+
+       return 0;
+}
+
 static int gaudi_validate_cb(struct hl_device *hdev,
                        struct hl_cs_parser *parser, bool is_mmu)
 {
@@ -3838,6 +3885,17 @@ static int gaudi_validate_cb(struct hl_device *hdev,
                        rc = -EPERM;
                        break;
 
+               case PACKET_WREG_BULK:
+                       dev_err(hdev->dev,
+                               "User not allowed to use WREG_BULK\n");
+                       rc = -EPERM;
+                       break;
+
+               case PACKET_LOAD_AND_EXE:
+                       rc = gaudi_validate_load_and_exe_pkt(hdev, parser,
+                               (struct packet_load_and_exe *) user_pkt);
+                       break;
+
                case PACKET_LIN_DMA:
                        parser->contains_dma_pkt = true;
                        if (is_mmu)
@@ -3848,14 +3906,12 @@ static int gaudi_validate_cb(struct hl_device *hdev,
                        break;
 
                case PACKET_WREG_32:
-               case PACKET_WREG_BULK:
                case PACKET_MSG_LONG:
                case PACKET_MSG_SHORT:
                case PACKET_REPEAT:
                case PACKET_FENCE:
                case PACKET_NOP:
                case PACKET_ARB_POINT:
-               case PACKET_LOAD_AND_EXE:
                        parser->patched_cb_size += pkt_size;
                        break;
 
@@ -4490,13 +4546,18 @@ static int gaudi_debugfs_read32(struct hl_device *hdev, u64 addr, u32 *val)
        int rc = 0;
 
        if ((addr >= CFG_BASE) && (addr < CFG_BASE + CFG_SIZE)) {
-               if (gaudi->hw_cap_initialized & HW_CAP_CLK_GATE) {
+
+               if ((gaudi->hw_cap_initialized & HW_CAP_CLK_GATE) &&
+                               (hdev->clock_gating_mask &
+                                               GAUDI_CLK_GATE_DEBUGFS_MASK)) {
+
                        dev_err_ratelimited(hdev->dev,
                                "Can't read register - clock gating is enabled!\n");
                        rc = -EFAULT;
                } else {
                        *val = RREG32(addr - CFG_BASE);
                }
+
        } else if ((addr >= SRAM_BASE_ADDR) &&
                        (addr < SRAM_BASE_ADDR + SRAM_BAR_SIZE)) {
                *val = readl(hdev->pcie_bar[SRAM_BAR_ID] +
@@ -4532,13 +4593,18 @@ static int gaudi_debugfs_write32(struct hl_device *hdev, u64 addr, u32 val)
        int rc = 0;
 
        if ((addr >= CFG_BASE) && (addr < CFG_BASE + CFG_SIZE)) {
-               if (gaudi->hw_cap_initialized & HW_CAP_CLK_GATE) {
+
+               if ((gaudi->hw_cap_initialized & HW_CAP_CLK_GATE) &&
+                               (hdev->clock_gating_mask &
+                                               GAUDI_CLK_GATE_DEBUGFS_MASK)) {
+
                        dev_err_ratelimited(hdev->dev,
                                "Can't write register - clock gating is enabled!\n");
                        rc = -EFAULT;
                } else {
                        WREG32(addr - CFG_BASE, val);
                }
+
        } else if ((addr >= SRAM_BASE_ADDR) &&
                        (addr < SRAM_BASE_ADDR + SRAM_BAR_SIZE)) {
                writel(val, hdev->pcie_bar[SRAM_BAR_ID] +
@@ -4574,7 +4640,11 @@ static int gaudi_debugfs_read64(struct hl_device *hdev, u64 addr, u64 *val)
        int rc = 0;
 
        if ((addr >= CFG_BASE) && (addr <= CFG_BASE + CFG_SIZE - sizeof(u64))) {
-               if (gaudi->hw_cap_initialized & HW_CAP_CLK_GATE) {
+
+               if ((gaudi->hw_cap_initialized & HW_CAP_CLK_GATE) &&
+                               (hdev->clock_gating_mask &
+                                               GAUDI_CLK_GATE_DEBUGFS_MASK)) {
+
                        dev_err_ratelimited(hdev->dev,
                                "Can't read register - clock gating is enabled!\n");
                        rc = -EFAULT;
@@ -4584,6 +4654,7 @@ static int gaudi_debugfs_read64(struct hl_device *hdev, u64 addr, u64 *val)
 
                        *val = (((u64) val_h) << 32) | val_l;
                }
+
        } else if ((addr >= SRAM_BASE_ADDR) &&
                   (addr <= SRAM_BASE_ADDR + SRAM_BAR_SIZE - sizeof(u64))) {
                *val = readq(hdev->pcie_bar[SRAM_BAR_ID] +
@@ -4620,7 +4691,11 @@ static int gaudi_debugfs_write64(struct hl_device *hdev, u64 addr, u64 val)
        int rc = 0;
 
        if ((addr >= CFG_BASE) && (addr <= CFG_BASE + CFG_SIZE - sizeof(u64))) {
-               if (gaudi->hw_cap_initialized & HW_CAP_CLK_GATE) {
+
+               if ((gaudi->hw_cap_initialized & HW_CAP_CLK_GATE) &&
+                               (hdev->clock_gating_mask &
+                                               GAUDI_CLK_GATE_DEBUGFS_MASK)) {
+
                        dev_err_ratelimited(hdev->dev,
                                "Can't write register - clock gating is enabled!\n");
                        rc = -EFAULT;
@@ -4629,6 +4704,7 @@ static int gaudi_debugfs_write64(struct hl_device *hdev, u64 addr, u64 val)
                        WREG32(addr + sizeof(u32) - CFG_BASE,
                                upper_32_bits(val));
                }
+
        } else if ((addr >= SRAM_BASE_ADDR) &&
                   (addr <= SRAM_BASE_ADDR + SRAM_BAR_SIZE - sizeof(u64))) {
                writeq(val, hdev->pcie_bar[SRAM_BAR_ID] +
@@ -4850,7 +4926,7 @@ static void gaudi_mmu_prepare(struct hl_device *hdev, u32 asid)
        gaudi_mmu_prepare_reg(hdev, mmPSOC_GLOBAL_CONF_TRACE_ARUSER, asid);
        gaudi_mmu_prepare_reg(hdev, mmPSOC_GLOBAL_CONF_TRACE_AWUSER, asid);
 
-       hdev->asic_funcs->enable_clock_gating(hdev);
+       hdev->asic_funcs->set_clock_gating(hdev);
 
        mutex_unlock(&gaudi->clk_gate_mutex);
 }
@@ -5231,7 +5307,7 @@ static void gaudi_print_ecc_info_generic(struct hl_device *hdev,
        }
 
        if (disable_clock_gating) {
-               hdev->asic_funcs->enable_clock_gating(hdev);
+               hdev->asic_funcs->set_clock_gating(hdev);
                mutex_unlock(&gaudi->clk_gate_mutex);
        }
 }
@@ -5718,7 +5794,7 @@ static bool gaudi_tpc_read_interrupts(struct hl_device *hdev, u8 tpc_id,
        /* Clear interrupts */
        WREG32(mmTPC0_CFG_TPC_INTR_CAUSE + tpc_offset, 0);
 
-       hdev->asic_funcs->enable_clock_gating(hdev);
+       hdev->asic_funcs->set_clock_gating(hdev);
 
        mutex_unlock(&gaudi->clk_gate_mutex);
 
@@ -5994,6 +6070,8 @@ static int gaudi_mmu_invalidate_cache(struct hl_device *hdev, bool is_hard,
        mutex_lock(&hdev->mmu_cache_lock);
 
        /* L0 & L1 invalidation */
+       WREG32(mmSTLB_INV_PS, 3);
+       WREG32(mmSTLB_CACHE_INV, gaudi->mmu_cache_inv_pi++);
        WREG32(mmSTLB_INV_PS, 2);
 
        rc = hl_poll_timeout(
@@ -6232,7 +6310,7 @@ static bool gaudi_is_device_idle(struct hl_device *hdev, u32 *mask,
        if (s)
                seq_puts(s, "\n");
 
-       hdev->asic_funcs->enable_clock_gating(hdev);
+       hdev->asic_funcs->set_clock_gating(hdev);
 
        mutex_unlock(&gaudi->clk_gate_mutex);
 
@@ -6333,7 +6411,7 @@ static int gaudi_run_tpc_kernel(struct hl_device *hdev, u64 tpc_kernel,
                dev_err(hdev->dev,
                        "Timeout while waiting for TPC%d icache prefetch\n",
                        tpc_id);
-               hdev->asic_funcs->enable_clock_gating(hdev);
+               hdev->asic_funcs->set_clock_gating(hdev);
                mutex_unlock(&gaudi->clk_gate_mutex);
                return -EIO;
        }
@@ -6362,7 +6440,7 @@ static int gaudi_run_tpc_kernel(struct hl_device *hdev, u64 tpc_kernel,
                1000,
                kernel_timeout);
 
-       hdev->asic_funcs->enable_clock_gating(hdev);
+       hdev->asic_funcs->set_clock_gating(hdev);
        mutex_unlock(&gaudi->clk_gate_mutex);
 
        if (rc) {
@@ -6703,7 +6781,7 @@ static const struct hl_asic_funcs gaudi_funcs = {
        .mmu_invalidate_cache = gaudi_mmu_invalidate_cache,
        .mmu_invalidate_cache_range = gaudi_mmu_invalidate_cache_range,
        .send_heartbeat = gaudi_send_heartbeat,
-       .enable_clock_gating = gaudi_enable_clock_gating,
+       .set_clock_gating = gaudi_set_clock_gating,
        .disable_clock_gating = gaudi_disable_clock_gating,
        .debug_coresight = gaudi_debug_coresight,
        .is_device_idle = gaudi_is_device_idle,
index a46530d..41a8d9b 100644 (file)
@@ -229,6 +229,8 @@ struct gaudi_internal_qman_info {
  * @multi_msi_mode: whether we are working in multi MSI single MSI mode.
  *                  Multi MSI is possible only with IOMMU enabled.
  * @ext_queue_idx: helper index for external queues initialization.
+ * @mmu_cache_inv_pi: PI for MMU cache invalidation flow. The H/W expects an
+ *                    8-bit value so use u8.
  */
 struct gaudi_device {
        int (*armcp_info_get)(struct hl_device *hdev);
@@ -248,6 +250,7 @@ struct gaudi_device {
        u32                             hw_cap_initialized;
        u8                              multi_msi_mode;
        u8                              ext_queue_idx;
+       u8                              mmu_cache_inv_pi;
 };
 
 void gaudi_init_security(struct hl_device *hdev);
index 0d2952b..88460b2 100644 (file)
@@ -88,6 +88,7 @@
 #define GOYA_PLDM_MMU_TIMEOUT_USEC     (MMU_CONFIG_TIMEOUT_USEC * 100)
 #define GOYA_PLDM_QMAN0_TIMEOUT_USEC   (HL_DEVICE_TIMEOUT_USEC * 30)
 #define GOYA_BOOT_FIT_REQ_TIMEOUT_USEC 1000000         /* 1s */
+#define GOYA_MSG_TO_CPU_TIMEOUT_USEC   4000000         /* 4s */
 
 #define GOYA_QMAN0_FENCE_VAL           0xD169B243
 
@@ -2830,6 +2831,9 @@ int goya_send_cpu_message(struct hl_device *hdev, u32 *msg, u16 len,
                return 0;
        }
 
+       if (!timeout)
+               timeout = GOYA_MSG_TO_CPU_TIMEOUT_USEC;
+
        return hl_fw_send_cpu_message(hdev, GOYA_QUEUE_ID_CPU_PQ, msg, len,
                                        timeout, result);
 }
@@ -4431,8 +4435,8 @@ static int goya_unmask_irq_arr(struct hl_device *hdev, u32 *irq_arr,
        pkt->armcp_pkt.ctl = cpu_to_le32(ARMCP_PACKET_UNMASK_RAZWI_IRQ_ARRAY <<
                                                ARMCP_PKT_CTL_OPCODE_SHIFT);
 
-       rc = goya_send_cpu_message(hdev, (u32 *) pkt, total_pkt_size,
-                       HL_DEVICE_TIMEOUT_USEC, &result);
+       rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) pkt,
+                                               total_pkt_size, 0, &result);
 
        if (rc)
                dev_err(hdev->dev, "failed to unmask IRQ array\n");
@@ -4464,8 +4468,8 @@ static int goya_unmask_irq(struct hl_device *hdev, u16 event_type)
                                ARMCP_PKT_CTL_OPCODE_SHIFT);
        pkt.value = cpu_to_le64(event_type);
 
-       rc = goya_send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
-                       HL_DEVICE_TIMEOUT_USEC, &result);
+       rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
+                                               0, &result);
 
        if (rc)
                dev_err(hdev->dev, "failed to unmask RAZWI IRQ %d", event_type);
@@ -5028,14 +5032,14 @@ int goya_armcp_info_get(struct hl_device *hdev)
        return 0;
 }
 
-static void goya_enable_clock_gating(struct hl_device *hdev)
+static void goya_set_clock_gating(struct hl_device *hdev)
 {
-
+       /* clock gating not supported in Goya */
 }
 
 static void goya_disable_clock_gating(struct hl_device *hdev)
 {
-
+       /* clock gating not supported in Goya */
 }
 
 static bool goya_is_device_idle(struct hl_device *hdev, u32 *mask,
@@ -5259,7 +5263,7 @@ static const struct hl_asic_funcs goya_funcs = {
        .mmu_invalidate_cache = goya_mmu_invalidate_cache,
        .mmu_invalidate_cache_range = goya_mmu_invalidate_cache_range,
        .send_heartbeat = goya_send_heartbeat,
-       .enable_clock_gating = goya_enable_clock_gating,
+       .set_clock_gating = goya_set_clock_gating,
        .disable_clock_gating = goya_disable_clock_gating,
        .debug_coresight = goya_debug_coresight,
        .is_device_idle = goya_is_device_idle,
index 1ecdcf8..194d833 100644 (file)
@@ -578,8 +578,9 @@ enum hl_pll_frequency {
  * @mmu_invalidate_cache_range: flush specific MMU STLB cache lines with
  *                              ASID-VA-size mask.
  * @send_heartbeat: send is-alive packet to ArmCP and verify response.
- * @enable_clock_gating: enable clock gating for reducing power consumption.
- * @disable_clock_gating: disable clock for accessing registers on HBW.
+ * @set_clock_gating: enable/disable clock gating per engine according to
+ *                    clock gating mask in hdev
+ * @disable_clock_gating: disable clock gating completely
  * @debug_coresight: perform certain actions on Coresight for debugging.
  * @is_device_idle: return true if device is idle, false otherwise.
  * @soft_reset_late_init: perform certain actions needed after soft reset.
@@ -587,7 +588,11 @@ enum hl_pll_frequency {
  * @hw_queues_unlock: release H/W queues lock.
  * @get_pci_id: retrieve PCI ID.
  * @get_eeprom_data: retrieve EEPROM data from F/W.
- * @send_cpu_message: send buffer to ArmCP.
+ * @send_cpu_message: send message to F/W. If the message is timedout, the
+ *                    driver will eventually reset the device. The timeout can
+ *                    be determined by the calling function or it can be 0 and
+ *                    then the timeout is the default timeout for the specific
+ *                    ASIC
  * @get_hw_state: retrieve the H/W state
  * @pci_bars_map: Map PCI BARs.
  * @set_dram_bar_base: Set DRAM BAR to map specific device address. Returns
@@ -680,7 +685,7 @@ struct hl_asic_funcs {
        int (*mmu_invalidate_cache_range)(struct hl_device *hdev, bool is_hard,
                        u32 asid, u64 va, u64 size);
        int (*send_heartbeat)(struct hl_device *hdev);
-       void (*enable_clock_gating)(struct hl_device *hdev);
+       void (*set_clock_gating)(struct hl_device *hdev);
        void (*disable_clock_gating)(struct hl_device *hdev);
        int (*debug_coresight)(struct hl_device *hdev, void *data);
        bool (*is_device_idle)(struct hl_device *hdev, u32 *mask,
@@ -1398,6 +1403,9 @@ struct hl_device_idle_busy_ts {
  * @max_power: the max power of the device, as configured by the sysadmin. This
  *             value is saved so in case of hard-reset, the driver will restore
  *             this value and update the F/W after the re-initialization
+ * @clock_gating_mask: is clock gating enabled. bitmask that represents the
+ *                     different engines. See debugfs-driver-habanalabs for
+ *                     details.
  * @in_reset: is device in reset flow.
  * @curr_pll_profile: current PLL profile.
  * @cs_active_cnt: number of active command submissions on this device (active
@@ -1425,7 +1433,6 @@ struct hl_device_idle_busy_ts {
  * @init_done: is the initialization of the device done.
  * @mmu_enable: is MMU enabled.
  * @mmu_huge_page_opt: is MMU huge pages optimization enabled.
- * @clock_gating: is clock gating enabled.
  * @device_cpu_disabled: is the device CPU disabled (due to timeouts)
  * @dma_mask: the dma mask that was set for this device
  * @in_debug: is device under debug. This, together with fpriv_list, enforces
@@ -1493,6 +1500,7 @@ struct hl_device {
        atomic64_t                      dram_used_mem;
        u64                             timeout_jiffies;
        u64                             max_power;
+       u64                             clock_gating_mask;
        atomic_t                        in_reset;
        enum hl_pll_frequency           curr_pll_profile;
        int                             cs_active_cnt;
@@ -1514,7 +1522,6 @@ struct hl_device {
        u8                              dram_default_page_mapping;
        u8                              pmmu_huge_range;
        u8                              init_done;
-       u8                              clock_gating;
        u8                              device_cpu_disabled;
        u8                              dma_mask;
        u8                              in_debug;
index 8652c7e..22716da 100644 (file)
@@ -232,7 +232,7 @@ static void set_driver_behavior_per_device(struct hl_device *hdev)
        hdev->fw_loading = 1;
        hdev->cpu_queues_enable = 1;
        hdev->heartbeat = 1;
-       hdev->clock_gating = 1;
+       hdev->clock_gating_mask = ULONG_MAX;
 
        hdev->reset_pcilink = 0;
        hdev->axi_drain = 0;
index 8c6cd77..b997336 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/pci.h>
 #include <linux/hwmon.h>
 
-#define SENSORS_PKT_TIMEOUT            1000000 /* 1s */
 #define HWMON_NR_SENSOR_TYPES          (hwmon_pwm + 1)
 
 int hl_build_hwmon_channel_info(struct hl_device *hdev,
@@ -323,7 +322,7 @@ int hl_get_temperature(struct hl_device *hdev,
        pkt.type = __cpu_to_le16(attr);
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
-                       SENSORS_PKT_TIMEOUT, value);
+                                               0, value);
 
        if (rc) {
                dev_err(hdev->dev,
@@ -350,7 +349,7 @@ int hl_set_temperature(struct hl_device *hdev,
        pkt.value = __cpu_to_le64(value);
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
-                                               SENSORS_PKT_TIMEOUT, NULL);
+                                               0, NULL);
 
        if (rc)
                dev_err(hdev->dev,
@@ -374,7 +373,7 @@ int hl_get_voltage(struct hl_device *hdev,
        pkt.type = __cpu_to_le16(attr);
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
-                                       SENSORS_PKT_TIMEOUT, value);
+                                               0, value);
 
        if (rc) {
                dev_err(hdev->dev,
@@ -400,7 +399,7 @@ int hl_get_current(struct hl_device *hdev,
        pkt.type = __cpu_to_le16(attr);
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
-                                       SENSORS_PKT_TIMEOUT, value);
+                                               0, value);
 
        if (rc) {
                dev_err(hdev->dev,
@@ -426,7 +425,7 @@ int hl_get_fan_speed(struct hl_device *hdev,
        pkt.type = __cpu_to_le16(attr);
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
-                                       SENSORS_PKT_TIMEOUT, value);
+                                               0, value);
 
        if (rc) {
                dev_err(hdev->dev,
@@ -452,7 +451,7 @@ int hl_get_pwm_info(struct hl_device *hdev,
        pkt.type = __cpu_to_le16(attr);
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
-                                       SENSORS_PKT_TIMEOUT, value);
+                                               0, value);
 
        if (rc) {
                dev_err(hdev->dev,
@@ -479,7 +478,7 @@ void hl_set_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr,
        pkt.value = cpu_to_le64(value);
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
-                                       SENSORS_PKT_TIMEOUT, NULL);
+                                               0, NULL);
 
        if (rc)
                dev_err(hdev->dev,
@@ -502,7 +501,7 @@ int hl_set_voltage(struct hl_device *hdev,
        pkt.value = __cpu_to_le64(value);
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
-                                               SENSORS_PKT_TIMEOUT, NULL);
+                                               0, NULL);
 
        if (rc)
                dev_err(hdev->dev,
@@ -527,7 +526,7 @@ int hl_set_current(struct hl_device *hdev,
        pkt.value = __cpu_to_le64(value);
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
-                                               SENSORS_PKT_TIMEOUT, NULL);
+                                               0, NULL);
 
        if (rc)
                dev_err(hdev->dev,
index 9a5800b..0f0cd06 100644 (file)
@@ -197,6 +197,9 @@ struct packet_wait {
        __le32 ctl;
 };
 
+#define GAUDI_PKT_LOAD_AND_EXE_CFG_DST_SHIFT   0
+#define GAUDI_PKT_LOAD_AND_EXE_CFG_DST_MASK    0x00000001
+
 struct packet_load_and_exe {
        __le32 cfg;
        __le32 ctl;
index 5d78d5e..70b6b18 100644 (file)
@@ -9,9 +9,6 @@
 
 #include <linux/pci.h>
 
-#define SET_CLK_PKT_TIMEOUT    1000000 /* 1s */
-#define SET_PWR_PKT_TIMEOUT    1000000 /* 1s */
-
 long hl_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr)
 {
        struct armcp_packet pkt;
@@ -29,7 +26,7 @@ long hl_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr)
        pkt.pll_index = cpu_to_le32(pll_index);
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
-                                               SET_CLK_PKT_TIMEOUT, &result);
+                                               0, &result);
 
        if (rc) {
                dev_err(hdev->dev,
@@ -54,7 +51,7 @@ void hl_set_frequency(struct hl_device *hdev, u32 pll_index, u64 freq)
        pkt.value = cpu_to_le64(freq);
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
-                                       SET_CLK_PKT_TIMEOUT, NULL);
+                                               0, NULL);
 
        if (rc)
                dev_err(hdev->dev,
@@ -74,7 +71,7 @@ u64 hl_get_max_power(struct hl_device *hdev)
                                ARMCP_PKT_CTL_OPCODE_SHIFT);
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
-                                               SET_PWR_PKT_TIMEOUT, &result);
+                                               0, &result);
 
        if (rc) {
                dev_err(hdev->dev, "Failed to get max power, error %d\n", rc);
@@ -96,7 +93,7 @@ void hl_set_max_power(struct hl_device *hdev, u64 value)
        pkt.value = cpu_to_le64(value);
 
        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
-                                       SET_PWR_PKT_TIMEOUT, NULL);
+                                               0, NULL);
 
        if (rc)
                dev_err(hdev->dev, "Failed to set max power, error %d\n", rc);
index bccd341..d5d2af4 100644 (file)
@@ -828,7 +828,7 @@ static void run_plant_and_detach_test(int is_early)
        char before[BREAK_INSTR_SIZE];
        char after[BREAK_INSTR_SIZE];
 
-       probe_kernel_read(before, (char *)kgdbts_break_test,
+       copy_from_kernel_nofault(before, (char *)kgdbts_break_test,
          BREAK_INSTR_SIZE);
        init_simple_test();
        ts.tst = plant_and_detach_test;
@@ -836,8 +836,8 @@ static void run_plant_and_detach_test(int is_early)
        /* Activate test with initial breakpoint */
        if (!is_early)
                kgdb_breakpoint();
-       probe_kernel_read(after, (char *)kgdbts_break_test,
-         BREAK_INSTR_SIZE);
+       copy_from_kernel_nofault(after, (char *)kgdbts_break_test,
+                       BREAK_INSTR_SIZE);
        if (memcmp(before, after, BREAK_INSTR_SIZE)) {
                printk(KERN_CRIT "kgdbts: ERROR kgdb corrupted memory\n");
                panic("kgdb memory corruption");
index 8d468e0..f476dbc 100644 (file)
@@ -745,9 +745,8 @@ static int mei_cl_device_remove(struct device *dev)
 
        mei_cl_bus_module_put(cldev);
        module_put(THIS_MODULE);
-       dev->driver = NULL;
-       return ret;
 
+       return ret;
 }
 
 static ssize_t name_show(struct device *dev, struct device_attribute *a,
index 9392934..7becfc7 100644 (file)
@@ -94,6 +94,7 @@
 #define MEI_DEV_ID_JSP_N      0x4DE0  /* Jasper Lake Point N */
 
 #define MEI_DEV_ID_TGP_LP     0xA0E0  /* Tiger Lake Point LP */
+#define MEI_DEV_ID_TGP_H      0x43E0  /* Tiger Lake Point H */
 
 #define MEI_DEV_ID_MCC        0x4B70  /* Mule Creek Canyon (EHL) */
 #define MEI_DEV_ID_MCC_4      0x4B75  /* Mule Creek Canyon 4 (EHL) */
 #  define PCI_CFG_HFS_1_D0I3_MSK     0x80000000
 #define PCI_CFG_HFS_2         0x48
 #define PCI_CFG_HFS_3         0x60
+#  define PCI_CFG_HFS_3_FW_SKU_MSK   0x00000070
+#  define PCI_CFG_HFS_3_FW_SKU_SPS   0x00000060
 #define PCI_CFG_HFS_4         0x64
 #define PCI_CFG_HFS_5         0x68
 #define PCI_CFG_HFS_6         0x6C
index f620442..7649710 100644 (file)
@@ -1366,7 +1366,7 @@ static bool mei_me_fw_type_nm(struct pci_dev *pdev)
 #define MEI_CFG_FW_NM                           \
        .quirk_probe = mei_me_fw_type_nm
 
-static bool mei_me_fw_type_sps(struct pci_dev *pdev)
+static bool mei_me_fw_type_sps_4(struct pci_dev *pdev)
 {
        u32 reg;
        unsigned int devfn;
@@ -1382,7 +1382,36 @@ static bool mei_me_fw_type_sps(struct pci_dev *pdev)
        return (reg & 0xf0000) == 0xf0000;
 }
 
-#define MEI_CFG_FW_SPS                           \
+#define MEI_CFG_FW_SPS_4                          \
+       .quirk_probe = mei_me_fw_type_sps_4
+
+/**
+ * mei_me_fw_sku_sps() - check for sps sku
+ *
+ * Read ME FW Status register to check for SPS Firmware.
+ * The SPS FW is only signaled in pci function 0
+ *
+ * @pdev: pci device
+ *
+ * Return: true in case of SPS firmware
+ */
+static bool mei_me_fw_type_sps(struct pci_dev *pdev)
+{
+       u32 reg;
+       u32 fw_type;
+       unsigned int devfn;
+
+       devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
+       pci_bus_read_config_dword(pdev->bus, devfn, PCI_CFG_HFS_3, &reg);
+       trace_mei_pci_cfg_read(&pdev->dev, "PCI_CFG_HFS_3", PCI_CFG_HFS_3, reg);
+       fw_type = (reg & PCI_CFG_HFS_3_FW_SKU_MSK);
+
+       dev_dbg(&pdev->dev, "fw type is %d\n", fw_type);
+
+       return fw_type == PCI_CFG_HFS_3_FW_SKU_SPS;
+}
+
+#define MEI_CFG_FW_SPS                          \
        .quirk_probe = mei_me_fw_type_sps
 
 #define MEI_CFG_FW_VER_SUPP                     \
@@ -1452,10 +1481,17 @@ static const struct mei_cfg mei_me_pch8_cfg = {
 };
 
 /* PCH8 Lynx Point with quirk for SPS Firmware exclusion */
-static const struct mei_cfg mei_me_pch8_sps_cfg = {
+static const struct mei_cfg mei_me_pch8_sps_4_cfg = {
        MEI_CFG_PCH8_HFS,
        MEI_CFG_FW_VER_SUPP,
-       MEI_CFG_FW_SPS,
+       MEI_CFG_FW_SPS_4,
+};
+
+/* LBG with quirk for SPS (4.0) Firmware exclusion */
+static const struct mei_cfg mei_me_pch12_sps_4_cfg = {
+       MEI_CFG_PCH8_HFS,
+       MEI_CFG_FW_VER_SUPP,
+       MEI_CFG_FW_SPS_4,
 };
 
 /* Cannon Lake and newer devices */
@@ -1465,8 +1501,18 @@ static const struct mei_cfg mei_me_pch12_cfg = {
        MEI_CFG_DMA_128,
 };
 
-/* LBG with quirk for SPS Firmware exclusion */
+/* Cannon Lake with quirk for SPS 5.0 and newer Firmware exclusion */
 static const struct mei_cfg mei_me_pch12_sps_cfg = {
+       MEI_CFG_PCH8_HFS,
+       MEI_CFG_FW_VER_SUPP,
+       MEI_CFG_DMA_128,
+       MEI_CFG_FW_SPS,
+};
+
+/* Cannon Lake with quirk for SPS 5.0 and newer Firmware exclusion
+ * w/o DMA support
+ */
+static const struct mei_cfg mei_me_pch12_nodma_sps_cfg = {
        MEI_CFG_PCH8_HFS,
        MEI_CFG_FW_VER_SUPP,
        MEI_CFG_FW_SPS,
@@ -1480,6 +1526,15 @@ static const struct mei_cfg mei_me_pch15_cfg = {
        MEI_CFG_TRC,
 };
 
+/* Tiger Lake with quirk for SPS 5.0 and newer Firmware exclusion */
+static const struct mei_cfg mei_me_pch15_sps_cfg = {
+       MEI_CFG_PCH8_HFS,
+       MEI_CFG_FW_VER_SUPP,
+       MEI_CFG_DMA_128,
+       MEI_CFG_TRC,
+       MEI_CFG_FW_SPS,
+};
+
 /*
  * mei_cfg_list - A list of platform platform specific configurations.
  * Note: has to be synchronized with  enum mei_cfg_idx.
@@ -1492,10 +1547,13 @@ static const struct mei_cfg *const mei_cfg_list[] = {
        [MEI_ME_PCH7_CFG] = &mei_me_pch7_cfg,
        [MEI_ME_PCH_CPT_PBG_CFG] = &mei_me_pch_cpt_pbg_cfg,
        [MEI_ME_PCH8_CFG] = &mei_me_pch8_cfg,
-       [MEI_ME_PCH8_SPS_CFG] = &mei_me_pch8_sps_cfg,
+       [MEI_ME_PCH8_SPS_4_CFG] = &mei_me_pch8_sps_4_cfg,
        [MEI_ME_PCH12_CFG] = &mei_me_pch12_cfg,
+       [MEI_ME_PCH12_SPS_4_CFG] = &mei_me_pch12_sps_4_cfg,
        [MEI_ME_PCH12_SPS_CFG] = &mei_me_pch12_sps_cfg,
+       [MEI_ME_PCH12_SPS_NODMA_CFG] = &mei_me_pch12_nodma_sps_cfg,
        [MEI_ME_PCH15_CFG] = &mei_me_pch15_cfg,
+       [MEI_ME_PCH15_SPS_CFG] = &mei_me_pch15_sps_cfg,
 };
 
 const struct mei_cfg *mei_me_get_cfg(kernel_ulong_t idx)
index b6b94e2..6a89736 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Copyright (c) 2012-2019, Intel Corporation. All rights reserved.
+ * Copyright (c) 2012-2020, Intel Corporation. All rights reserved.
  * Intel Management Engine Interface (Intel MEI) Linux driver
  */
 
@@ -76,14 +76,20 @@ struct mei_me_hw {
  *                         with quirk for Node Manager exclusion.
  * @MEI_ME_PCH8_CFG:       Platform Controller Hub Gen8 and newer
  *                         client platforms.
- * @MEI_ME_PCH8_SPS_CFG:   Platform Controller Hub Gen8 and newer
+ * @MEI_ME_PCH8_SPS_4_CFG: Platform Controller Hub Gen8 and newer
  *                         servers platforms with quirk for
  *                         SPS firmware exclusion.
  * @MEI_ME_PCH12_CFG:      Platform Controller Hub Gen12 and newer
- * @MEI_ME_PCH12_SPS_CFG:  Platform Controller Hub Gen12 and newer
+ * @MEI_ME_PCH12_SPS_4_CFG:Platform Controller Hub Gen12 up to 4.0
+ *                         servers platforms with quirk for
+ *                         SPS firmware exclusion.
+ * @MEI_ME_PCH12_SPS_CFG:  Platform Controller Hub Gen12 5.0 and newer
  *                         servers platforms with quirk for
  *                         SPS firmware exclusion.
  * @MEI_ME_PCH15_CFG:      Platform Controller Hub Gen15 and newer
+ * @MEI_ME_PCH15_SPS_CFG:  Platform Controller Hub Gen15 and newer
+ *                         servers platforms with quirk for
+ *                         SPS firmware exclusion.
  * @MEI_ME_NUM_CFG:        Upper Sentinel.
  */
 enum mei_cfg_idx {
@@ -94,10 +100,13 @@ enum mei_cfg_idx {
        MEI_ME_PCH7_CFG,
        MEI_ME_PCH_CPT_PBG_CFG,
        MEI_ME_PCH8_CFG,
-       MEI_ME_PCH8_SPS_CFG,
+       MEI_ME_PCH8_SPS_4_CFG,
        MEI_ME_PCH12_CFG,
+       MEI_ME_PCH12_SPS_4_CFG,
        MEI_ME_PCH12_SPS_CFG,
+       MEI_ME_PCH12_SPS_NODMA_CFG,
        MEI_ME_PCH15_CFG,
+       MEI_ME_PCH15_SPS_CFG,
        MEI_ME_NUM_CFG,
 };
 
index 71f795b..2a3f2fd 100644 (file)
@@ -59,18 +59,18 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
        {MEI_PCI_DEVICE(MEI_DEV_ID_PPT_1, MEI_ME_PCH7_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_PPT_2, MEI_ME_PCH7_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_PPT_3, MEI_ME_PCH7_CFG)},
-       {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_H, MEI_ME_PCH8_SPS_CFG)},
-       {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_W, MEI_ME_PCH8_SPS_CFG)},
+       {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_H, MEI_ME_PCH8_SPS_4_CFG)},
+       {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_W, MEI_ME_PCH8_SPS_4_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_LP, MEI_ME_PCH8_CFG)},
-       {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_HR, MEI_ME_PCH8_SPS_CFG)},
+       {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_HR, MEI_ME_PCH8_SPS_4_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP, MEI_ME_PCH8_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP_2, MEI_ME_PCH8_CFG)},
 
        {MEI_PCI_DEVICE(MEI_DEV_ID_SPT, MEI_ME_PCH8_CFG)},
        {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_PCH12_SPS_CFG)},
+       {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, MEI_ME_PCH8_SPS_4_CFG)},
+       {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, MEI_ME_PCH8_SPS_4_CFG)},
+       {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH12_SPS_4_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)},
@@ -84,8 +84,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
 
        {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_LP, MEI_ME_PCH12_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_LP_3, MEI_ME_PCH8_CFG)},
-       {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H, MEI_ME_PCH12_CFG)},
-       {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H_3, MEI_ME_PCH8_CFG)},
+       {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H, MEI_ME_PCH12_SPS_CFG)},
+       {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H_3, MEI_ME_PCH12_SPS_NODMA_CFG)},
 
        {MEI_PCI_DEVICE(MEI_DEV_ID_CMP_LP, MEI_ME_PCH12_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_CMP_LP_3, MEI_ME_PCH8_CFG)},
@@ -96,6 +96,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
        {MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP, MEI_ME_PCH12_CFG)},
 
        {MEI_PCI_DEVICE(MEI_DEV_ID_TGP_LP, MEI_ME_PCH15_CFG)},
+       {MEI_PCI_DEVICE(MEI_DEV_ID_TGP_H, MEI_ME_PCH15_SPS_CFG)},
 
        {MEI_PCI_DEVICE(MEI_DEV_ID_JSP_N, MEI_ME_PCH15_CFG)},
 
index 7eb38d7..08a3b1c 100644 (file)
@@ -1146,9 +1146,11 @@ static int meson_mmc_probe(struct platform_device *pdev)
 
        mmc->caps |= MMC_CAP_CMD23;
        if (host->dram_access_quirk) {
+               /* Limit segments to 1 due to low available sram memory */
+               mmc->max_segs = 1;
                /* Limit to the available sram memory */
-               mmc->max_segs = SD_EMMC_SRAM_DATA_BUF_LEN / mmc->max_blk_size;
-               mmc->max_blk_count = mmc->max_segs;
+               mmc->max_blk_count = SD_EMMC_SRAM_DATA_BUF_LEN /
+                                    mmc->max_blk_size;
        } else {
                mmc->max_blk_count = CMD_CFG_LENGTH_MASK;
                mmc->max_segs = SD_EMMC_DESC_BUF_LEN /
index 5e20c09..df43f42 100644 (file)
@@ -689,7 +689,7 @@ MODULE_DEVICE_TABLE(of, owl_mmc_of_match);
 static struct platform_driver owl_mmc_driver = {
        .driver = {
                .name   = "owl_mmc",
-               .of_match_table = of_match_ptr(owl_mmc_of_match),
+               .of_match_table = owl_mmc_of_match,
        },
        .probe          = owl_mmc_probe,
        .remove         = owl_mmc_remove,
index b277dd7..c0d58e9 100644 (file)
@@ -618,8 +618,9 @@ static int msm_init_cm_dll(struct sdhci_host *host)
        config &= ~CORE_CLK_PWRSAVE;
        writel_relaxed(config, host->ioaddr + msm_offset->core_vendor_spec);
 
-       config = msm_host->dll_config;
-       writel_relaxed(config, host->ioaddr + msm_offset->core_dll_config);
+       if (msm_host->dll_config)
+               writel_relaxed(msm_host->dll_config,
+                               host->ioaddr + msm_offset->core_dll_config);
 
        if (msm_host->use_14lpp_dll_reset) {
                config = readl_relaxed(host->ioaddr +
index 56912e3..a1bcc0f 100644 (file)
@@ -68,7 +68,7 @@ static void aspeed_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
        if (WARN_ON(clock > host->max_clk))
                clock = host->max_clk;
 
-       for (div = 1; div < 256; div *= 2) {
+       for (div = 2; div < 256; div *= 2) {
                if ((parent / div) <= clock)
                        break;
        }
index 76d832a..7d93056 100644 (file)
@@ -1273,8 +1273,8 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
                return -EROFS;
        if (!len)
                return 0;
-       if (!mtd->oops_panic_write)
-               mtd->oops_panic_write = true;
+       if (!master->oops_panic_write)
+               master->oops_panic_write = true;
 
        return master->_panic_write(master, mtd_get_master_ofs(mtd, to), len,
                                    retlen, buf);
index 0a5cb77..f5a53aa 100644 (file)
@@ -1761,7 +1761,7 @@ static void ns_switch_state(struct nandsim *ns)
 
                NS_DBG("switch_state: operation is unknown, try to find it\n");
 
-               if (!ns_find_operation(ns, 0))
+               if (ns_find_operation(ns, 0))
                        return;
 
                if ((ns->state & ACTION_MASK) &&
index 94bfba9..2925547 100644 (file)
@@ -224,7 +224,7 @@ static int xway_nand_remove(struct platform_device *pdev)
        struct nand_chip *chip = &data->chip;
        int ret;
 
-       ret = mtd_device_unregister(mtd);
+       ret = mtd_device_unregister(nand_to_mtd(chip));
        WARN_ON(ret);
        nand_cleanup(chip);
 
index efd1a1d..3dd46cd 100644 (file)
@@ -552,6 +552,8 @@ static int bareudp_validate(struct nlattr *tb[], struct nlattr *data[],
 static int bareudp2info(struct nlattr *data[], struct bareudp_conf *conf,
                        struct netlink_ext_ack *extack)
 {
+       memset(conf, 0, sizeof(*conf));
+
        if (!data[IFLA_BAREUDP_PORT]) {
                NL_SET_ERR_MSG(extack, "port not specified");
                return -EINVAL;
@@ -570,6 +572,9 @@ static int bareudp2info(struct nlattr *data[], struct bareudp_conf *conf,
        if (data[IFLA_BAREUDP_SRCPORT_MIN])
                conf->sport_min =  nla_get_u16(data[IFLA_BAREUDP_SRCPORT_MIN]);
 
+       if (data[IFLA_BAREUDP_MULTIPROTO_MODE])
+               conf->multi_proto_mode = true;
+
        return 0;
 }
 
index 004919a..f88cb09 100644 (file)
@@ -5053,15 +5053,19 @@ int bond_create(struct net *net, const char *name)
        bond_dev->rtnl_link_ops = &bond_link_ops;
 
        res = register_netdevice(bond_dev);
+       if (res < 0) {
+               free_netdev(bond_dev);
+               rtnl_unlock();
+
+               return res;
+       }
 
        netif_carrier_off(bond_dev);
 
        bond_work_init_all(bond);
 
        rtnl_unlock();
-       if (res < 0)
-               free_netdev(bond_dev);
-       return res;
+       return 0;
 }
 
 static int __net_init bond_net_init(struct net *net)
index b43b516..f0f9138 100644 (file)
@@ -456,11 +456,10 @@ static int bond_newlink(struct net *src_net, struct net_device *bond_dev,
                return err;
 
        err = register_netdevice(bond_dev);
-
-       netif_carrier_off(bond_dev);
        if (!err) {
                struct bonding *bond = netdev_priv(bond_dev);
 
+               netif_carrier_off(bond_dev);
                bond_work_init_all(bond);
        }
 
index d08a3d5..6ad83a8 100644 (file)
@@ -146,7 +146,7 @@ struct pciefd_rx_dma {
        __le32 irq_status;
        __le32 sys_time_low;
        __le32 sys_time_high;
-       struct pucan_rx_msg msg[0];
+       struct pucan_rx_msg msg[];
 } __packed __aligned(4);
 
 /* Tx Link record */
@@ -194,7 +194,7 @@ struct pciefd_board {
        struct pci_dev *pci_dev;
        int can_count;
        spinlock_t cmd_lock;            /* 64-bits cmds must be atomic */
-       struct pciefd_can *can[0];      /* array of network devices */
+       struct pciefd_can *can[];       /* array of network devices */
 };
 
 /* supported device ids. */
index c7ac63f..946e41f 100644 (file)
@@ -1147,6 +1147,8 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
        set_bit(0, priv->cfp.used);
        set_bit(0, priv->cfp.unique);
 
+       /* Balance of_node_put() done by of_find_node_by_name() */
+       of_node_get(dn);
        ports = of_find_node_by_name(dn, "ports");
        if (ports) {
                bcm_sf2_identify_ports(priv, ports);
index 47d65b7..7c17b0f 100644 (file)
@@ -1268,6 +1268,9 @@ static int ksz8795_switch_init(struct ksz_device *dev)
                        return -ENOMEM;
        }
 
+       /* set the real number of ports */
+       dev->ds->num_ports = dev->port_cnt;
+
        return 0;
 }
 
index 9a51b8a..4a9239b 100644 (file)
@@ -974,23 +974,6 @@ static void ksz9477_port_mirror_del(struct dsa_switch *ds, int port,
                             PORT_MIRROR_SNIFFER, false);
 }
 
-static void ksz9477_phy_setup(struct ksz_device *dev, int port,
-                             struct phy_device *phy)
-{
-       /* Only apply to port with PHY. */
-       if (port >= dev->phy_port_cnt)
-               return;
-
-       /* The MAC actually cannot run in 1000 half-duplex mode. */
-       phy_remove_link_mode(phy,
-                            ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
-
-       /* PHY does not support gigabit. */
-       if (!(dev->features & GBIT_SUPPORT))
-               phy_remove_link_mode(phy,
-                                    ETHTOOL_LINK_MODE_1000baseT_Full_BIT);
-}
-
 static bool ksz9477_get_gbit(struct ksz_device *dev, u8 data)
 {
        bool gbit;
@@ -1588,6 +1571,9 @@ static int ksz9477_switch_init(struct ksz_device *dev)
                        return -ENOMEM;
        }
 
+       /* set the real number of ports */
+       dev->ds->num_ports = dev->port_cnt;
+
        return 0;
 }
 
@@ -1600,7 +1586,6 @@ static const struct ksz_dev_ops ksz9477_dev_ops = {
        .get_port_addr = ksz9477_get_port_addr,
        .cfg_port_member = ksz9477_cfg_port_member,
        .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
-       .phy_setup = ksz9477_phy_setup,
        .port_setup = ksz9477_port_setup,
        .r_mib_cnt = ksz9477_r_mib_cnt,
        .r_mib_pkt = ksz9477_r_mib_pkt,
@@ -1614,7 +1599,29 @@ static const struct ksz_dev_ops ksz9477_dev_ops = {
 
 int ksz9477_switch_register(struct ksz_device *dev)
 {
-       return ksz_switch_register(dev, &ksz9477_dev_ops);
+       int ret, i;
+       struct phy_device *phydev;
+
+       ret = ksz_switch_register(dev, &ksz9477_dev_ops);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < dev->phy_port_cnt; ++i) {
+               if (!dsa_is_user_port(dev->ds, i))
+                       continue;
+
+               phydev = dsa_to_port(dev->ds, i)->slave->phydev;
+
+               /* The MAC actually cannot run in 1000 half-duplex mode. */
+               phy_remove_link_mode(phydev,
+                                    ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
+
+               /* PHY does not support gigabit. */
+               if (!(dev->features & GBIT_SUPPORT))
+                       phy_remove_link_mode(phydev,
+                                            ETHTOOL_LINK_MODE_1000baseT_Full_BIT);
+       }
+       return ret;
 }
 EXPORT_SYMBOL(ksz9477_switch_register);
 
index 7d050fa..7951f52 100644 (file)
@@ -79,6 +79,7 @@ MODULE_DEVICE_TABLE(i2c, ksz9477_i2c_id);
 static const struct of_device_id ksz9477_dt_ids[] = {
        { .compatible = "microchip,ksz9477" },
        { .compatible = "microchip,ksz9897" },
+       { .compatible = "microchip,ksz9893" },
        { .compatible = "microchip,ksz9567" },
        {},
 };
index fd1d667..7b6c0dc 100644 (file)
@@ -358,8 +358,6 @@ int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy)
 
        /* setup slave port */
        dev->dev_ops->port_setup(dev, port, false);
-       if (dev->dev_ops->phy_setup)
-               dev->dev_ops->phy_setup(dev, port, phy);
 
        /* port_stp_state_set() will be called after to enable the port so
         * there is no need to do anything.
index f2c9bb6..7d11dd3 100644 (file)
@@ -119,8 +119,6 @@ struct ksz_dev_ops {
        u32 (*get_port_addr)(int port, int offset);
        void (*cfg_port_member)(struct ksz_device *dev, int port, u8 member);
        void (*flush_dyn_mac_table)(struct ksz_device *dev, int port);
-       void (*phy_setup)(struct ksz_device *dev, int port,
-                         struct phy_device *phy);
        void (*port_cleanup)(struct ksz_device *dev, int port);
        void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port);
        void (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
index 7627ea6..fee16c9 100644 (file)
@@ -664,8 +664,11 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
                                 const struct phylink_link_state *state)
 {
        struct mv88e6xxx_chip *chip = ds->priv;
+       struct mv88e6xxx_port *p;
        int err;
 
+       p = &chip->ports[port];
+
        /* FIXME: is this the correct test? If we're in fixed mode on an
         * internal port, why should we process this any different from
         * PHY mode? On the other hand, the port may be automedia between
@@ -675,10 +678,14 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
                return;
 
        mv88e6xxx_reg_lock(chip);
-       /* FIXME: should we force the link down here - but if we do, how
-        * do we restore the link force/unforce state? The driver layering
-        * gets in the way.
+       /* In inband mode, the link may come up at any time while the link
+        * is not forced down. Force the link down while we reconfigure the
+        * interface mode.
         */
+       if (mode == MLO_AN_INBAND && p->interface != state->interface &&
+           chip->info->ops->port_set_link)
+               chip->info->ops->port_set_link(chip, port, LINK_FORCED_DOWN);
+
        err = mv88e6xxx_port_config_interface(chip, port, state->interface);
        if (err && err != -EOPNOTSUPP)
                goto err_unlock;
@@ -691,6 +698,15 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
        if (err > 0)
                err = 0;
 
+       /* Undo the forced down state above after completing configuration
+        * irrespective of its state on entry, which allows the link to come up.
+        */
+       if (mode == MLO_AN_INBAND && p->interface != state->interface &&
+           chip->info->ops->port_set_link)
+               chip->info->ops->port_set_link(chip, port, LINK_UNFORCED);
+
+       p->interface = state->interface;
+
 err_unlock:
        mv88e6xxx_reg_unlock(chip);
 
index e5430cf..6476524 100644 (file)
@@ -232,6 +232,7 @@ struct mv88e6xxx_port {
        u64 atu_full_violation;
        u64 vtu_member_violation;
        u64 vtu_miss_violation;
+       phy_interface_t interface;
        u8 cmode;
        bool mirror_ingress;
        bool mirror_egress;
index bc0e47c..1771345 100644 (file)
@@ -891,16 +891,16 @@ void sja1105_ptp_txtstamp_skb(struct dsa_switch *ds, int port,
 
        mutex_lock(&ptp_data->lock);
 
-       rc = sja1105_ptpclkval_read(priv, &ticks, NULL);
+       rc = sja1105_ptpegr_ts_poll(ds, port, &ts);
        if (rc < 0) {
-               dev_err(ds->dev, "Failed to read PTP clock: %d\n", rc);
+               dev_err(ds->dev, "timed out polling for tstamp\n");
                kfree_skb(skb);
                goto out;
        }
 
-       rc = sja1105_ptpegr_ts_poll(ds, port, &ts);
+       rc = sja1105_ptpclkval_read(priv, &ticks, NULL);
        if (rc < 0) {
-               dev_err(ds->dev, "timed out polling for tstamp\n");
+               dev_err(ds->dev, "Failed to read PTP clock: %d\n", rc);
                kfree_skb(skb);
                goto out;
        }
index bdfd6c4..af35651 100644 (file)
@@ -7,6 +7,165 @@
 
 #define SJA1105_SIZE_VL_STATUS                 8
 
+/* Insert into the global gate list, sorted by gate action time. */
+static int sja1105_insert_gate_entry(struct sja1105_gating_config *gating_cfg,
+                                    struct sja1105_rule *rule,
+                                    u8 gate_state, s64 entry_time,
+                                    struct netlink_ext_ack *extack)
+{
+       struct sja1105_gate_entry *e;
+       int rc;
+
+       e = kzalloc(sizeof(*e), GFP_KERNEL);
+       if (!e)
+               return -ENOMEM;
+
+       e->rule = rule;
+       e->gate_state = gate_state;
+       e->interval = entry_time;
+
+       if (list_empty(&gating_cfg->entries)) {
+               list_add(&e->list, &gating_cfg->entries);
+       } else {
+               struct sja1105_gate_entry *p;
+
+               list_for_each_entry(p, &gating_cfg->entries, list) {
+                       if (p->interval == e->interval) {
+                               NL_SET_ERR_MSG_MOD(extack,
+                                                  "Gate conflict");
+                               rc = -EBUSY;
+                               goto err;
+                       }
+
+                       if (e->interval < p->interval)
+                               break;
+               }
+               list_add(&e->list, p->list.prev);
+       }
+
+       gating_cfg->num_entries++;
+
+       return 0;
+err:
+       kfree(e);
+       return rc;
+}
+
+/* The gate entries contain absolute times in their e->interval field. Convert
+ * that to proper intervals (i.e. "0, 5, 10, 15" to "5, 5, 5, 5").
+ */
+static void
+sja1105_gating_cfg_time_to_interval(struct sja1105_gating_config *gating_cfg,
+                                   u64 cycle_time)
+{
+       struct sja1105_gate_entry *last_e;
+       struct sja1105_gate_entry *e;
+       struct list_head *prev;
+
+       list_for_each_entry(e, &gating_cfg->entries, list) {
+               struct sja1105_gate_entry *p;
+
+               prev = e->list.prev;
+
+               if (prev == &gating_cfg->entries)
+                       continue;
+
+               p = list_entry(prev, struct sja1105_gate_entry, list);
+               p->interval = e->interval - p->interval;
+       }
+       last_e = list_last_entry(&gating_cfg->entries,
+                                struct sja1105_gate_entry, list);
+       last_e->interval = cycle_time - last_e->interval;
+}
+
+static void sja1105_free_gating_config(struct sja1105_gating_config *gating_cfg)
+{
+       struct sja1105_gate_entry *e, *n;
+
+       list_for_each_entry_safe(e, n, &gating_cfg->entries, list) {
+               list_del(&e->list);
+               kfree(e);
+       }
+}
+
+static int sja1105_compose_gating_subschedule(struct sja1105_private *priv,
+                                             struct netlink_ext_ack *extack)
+{
+       struct sja1105_gating_config *gating_cfg = &priv->tas_data.gating_cfg;
+       struct sja1105_rule *rule;
+       s64 max_cycle_time = 0;
+       s64 its_base_time = 0;
+       int i, rc = 0;
+
+       sja1105_free_gating_config(gating_cfg);
+
+       list_for_each_entry(rule, &priv->flow_block.rules, list) {
+               if (rule->type != SJA1105_RULE_VL)
+                       continue;
+               if (rule->vl.type != SJA1105_VL_TIME_TRIGGERED)
+                       continue;
+
+               if (max_cycle_time < rule->vl.cycle_time) {
+                       max_cycle_time = rule->vl.cycle_time;
+                       its_base_time = rule->vl.base_time;
+               }
+       }
+
+       if (!max_cycle_time)
+               return 0;
+
+       dev_dbg(priv->ds->dev, "max_cycle_time %lld its_base_time %lld\n",
+               max_cycle_time, its_base_time);
+
+       gating_cfg->base_time = its_base_time;
+       gating_cfg->cycle_time = max_cycle_time;
+       gating_cfg->num_entries = 0;
+
+       list_for_each_entry(rule, &priv->flow_block.rules, list) {
+               s64 time;
+               s64 rbt;
+
+               if (rule->type != SJA1105_RULE_VL)
+                       continue;
+               if (rule->vl.type != SJA1105_VL_TIME_TRIGGERED)
+                       continue;
+
+               /* Calculate the difference between this gating schedule's
+                * base time, and the base time of the gating schedule with the
+                * longest cycle time. We call it the relative base time (rbt).
+                */
+               rbt = future_base_time(rule->vl.base_time, rule->vl.cycle_time,
+                                      its_base_time);
+               rbt -= its_base_time;
+
+               time = rbt;
+
+               for (i = 0; i < rule->vl.num_entries; i++) {
+                       u8 gate_state = rule->vl.entries[i].gate_state;
+                       s64 entry_time = time;
+
+                       while (entry_time < max_cycle_time) {
+                               rc = sja1105_insert_gate_entry(gating_cfg, rule,
+                                                              gate_state,
+                                                              entry_time,
+                                                              extack);
+                               if (rc)
+                                       goto err;
+
+                               entry_time += rule->vl.cycle_time;
+                       }
+                       time += rule->vl.entries[i].interval;
+               }
+       }
+
+       sja1105_gating_cfg_time_to_interval(gating_cfg, max_cycle_time);
+
+       return 0;
+err:
+       sja1105_free_gating_config(gating_cfg);
+       return rc;
+}
+
 /* The switch flow classification core implements TTEthernet, which 'thinks' in
  * terms of Virtual Links (VL), a concept borrowed from ARINC 664 part 7.
  * However it also has one other operating mode (VLLUPFORMAT=0) where it acts
@@ -342,7 +501,9 @@ int sja1105_vl_redirect(struct sja1105_private *priv, int port,
                NL_SET_ERR_MSG_MOD(extack,
                                   "Can only redirect based on DMAC");
                return -EOPNOTSUPP;
-       } else if (key->type != SJA1105_KEY_VLAN_AWARE_VL) {
+       } else if ((priv->vlan_state == SJA1105_VLAN_BEST_EFFORT ||
+                   priv->vlan_state == SJA1105_VLAN_FILTERING_FULL) &&
+                  key->type != SJA1105_KEY_VLAN_AWARE_VL) {
                NL_SET_ERR_MSG_MOD(extack,
                                   "Can only redirect based on {DMAC, VID, PCP}");
                return -EOPNOTSUPP;
@@ -388,171 +549,19 @@ int sja1105_vl_delete(struct sja1105_private *priv, int port,
                kfree(rule);
        }
 
-       rc = sja1105_init_virtual_links(priv, extack);
+       rc = sja1105_compose_gating_subschedule(priv, extack);
        if (rc)
                return rc;
 
-       return sja1105_static_config_reload(priv, SJA1105_VIRTUAL_LINKS);
-}
-
-/* Insert into the global gate list, sorted by gate action time. */
-static int sja1105_insert_gate_entry(struct sja1105_gating_config *gating_cfg,
-                                    struct sja1105_rule *rule,
-                                    u8 gate_state, s64 entry_time,
-                                    struct netlink_ext_ack *extack)
-{
-       struct sja1105_gate_entry *e;
-       int rc;
-
-       e = kzalloc(sizeof(*e), GFP_KERNEL);
-       if (!e)
-               return -ENOMEM;
-
-       e->rule = rule;
-       e->gate_state = gate_state;
-       e->interval = entry_time;
-
-       if (list_empty(&gating_cfg->entries)) {
-               list_add(&e->list, &gating_cfg->entries);
-       } else {
-               struct sja1105_gate_entry *p;
-
-               list_for_each_entry(p, &gating_cfg->entries, list) {
-                       if (p->interval == e->interval) {
-                               NL_SET_ERR_MSG_MOD(extack,
-                                                  "Gate conflict");
-                               rc = -EBUSY;
-                               goto err;
-                       }
-
-                       if (e->interval < p->interval)
-                               break;
-               }
-               list_add(&e->list, p->list.prev);
-       }
-
-       gating_cfg->num_entries++;
-
-       return 0;
-err:
-       kfree(e);
-       return rc;
-}
-
-/* The gate entries contain absolute times in their e->interval field. Convert
- * that to proper intervals (i.e. "0, 5, 10, 15" to "5, 5, 5, 5").
- */
-static void
-sja1105_gating_cfg_time_to_interval(struct sja1105_gating_config *gating_cfg,
-                                   u64 cycle_time)
-{
-       struct sja1105_gate_entry *last_e;
-       struct sja1105_gate_entry *e;
-       struct list_head *prev;
-
-       list_for_each_entry(e, &gating_cfg->entries, list) {
-               struct sja1105_gate_entry *p;
-
-               prev = e->list.prev;
-
-               if (prev == &gating_cfg->entries)
-                       continue;
-
-               p = list_entry(prev, struct sja1105_gate_entry, list);
-               p->interval = e->interval - p->interval;
-       }
-       last_e = list_last_entry(&gating_cfg->entries,
-                                struct sja1105_gate_entry, list);
-       if (last_e->list.prev != &gating_cfg->entries)
-               last_e->interval = cycle_time - last_e->interval;
-}
-
-static void sja1105_free_gating_config(struct sja1105_gating_config *gating_cfg)
-{
-       struct sja1105_gate_entry *e, *n;
-
-       list_for_each_entry_safe(e, n, &gating_cfg->entries, list) {
-               list_del(&e->list);
-               kfree(e);
-       }
-}
-
-static int sja1105_compose_gating_subschedule(struct sja1105_private *priv,
-                                             struct netlink_ext_ack *extack)
-{
-       struct sja1105_gating_config *gating_cfg = &priv->tas_data.gating_cfg;
-       struct sja1105_rule *rule;
-       s64 max_cycle_time = 0;
-       s64 its_base_time = 0;
-       int i, rc = 0;
-
-       list_for_each_entry(rule, &priv->flow_block.rules, list) {
-               if (rule->type != SJA1105_RULE_VL)
-                       continue;
-               if (rule->vl.type != SJA1105_VL_TIME_TRIGGERED)
-                       continue;
-
-               if (max_cycle_time < rule->vl.cycle_time) {
-                       max_cycle_time = rule->vl.cycle_time;
-                       its_base_time = rule->vl.base_time;
-               }
-       }
-
-       if (!max_cycle_time)
-               return 0;
-
-       dev_dbg(priv->ds->dev, "max_cycle_time %lld its_base_time %lld\n",
-               max_cycle_time, its_base_time);
-
-       sja1105_free_gating_config(gating_cfg);
-
-       gating_cfg->base_time = its_base_time;
-       gating_cfg->cycle_time = max_cycle_time;
-       gating_cfg->num_entries = 0;
-
-       list_for_each_entry(rule, &priv->flow_block.rules, list) {
-               s64 time;
-               s64 rbt;
-
-               if (rule->type != SJA1105_RULE_VL)
-                       continue;
-               if (rule->vl.type != SJA1105_VL_TIME_TRIGGERED)
-                       continue;
-
-               /* Calculate the difference between this gating schedule's
-                * base time, and the base time of the gating schedule with the
-                * longest cycle time. We call it the relative base time (rbt).
-                */
-               rbt = future_base_time(rule->vl.base_time, rule->vl.cycle_time,
-                                      its_base_time);
-               rbt -= its_base_time;
-
-               time = rbt;
-
-               for (i = 0; i < rule->vl.num_entries; i++) {
-                       u8 gate_state = rule->vl.entries[i].gate_state;
-                       s64 entry_time = time;
-
-                       while (entry_time < max_cycle_time) {
-                               rc = sja1105_insert_gate_entry(gating_cfg, rule,
-                                                              gate_state,
-                                                              entry_time,
-                                                              extack);
-                               if (rc)
-                                       goto err;
-
-                               entry_time += rule->vl.cycle_time;
-                       }
-                       time += rule->vl.entries[i].interval;
-               }
-       }
+       rc = sja1105_init_virtual_links(priv, extack);
+       if (rc)
+               return rc;
 
-       sja1105_gating_cfg_time_to_interval(gating_cfg, max_cycle_time);
+       rc = sja1105_init_scheduling(priv);
+       if (rc < 0)
+               return rc;
 
-       return 0;
-err:
-       sja1105_free_gating_config(gating_cfg);
-       return rc;
+       return sja1105_static_config_reload(priv, SJA1105_VIRTUAL_LINKS);
 }
 
 int sja1105_vl_gate(struct sja1105_private *priv, int port,
@@ -588,14 +597,12 @@ int sja1105_vl_gate(struct sja1105_private *priv, int port,
 
        if (priv->vlan_state == SJA1105_VLAN_UNAWARE &&
            key->type != SJA1105_KEY_VLAN_UNAWARE_VL) {
-               dev_err(priv->ds->dev, "1: vlan state %d key type %d\n",
-                       priv->vlan_state, key->type);
                NL_SET_ERR_MSG_MOD(extack,
                                   "Can only gate based on DMAC");
                return -EOPNOTSUPP;
-       } else if (key->type != SJA1105_KEY_VLAN_AWARE_VL) {
-               dev_err(priv->ds->dev, "2: vlan state %d key type %d\n",
-                       priv->vlan_state, key->type);
+       } else if ((priv->vlan_state == SJA1105_VLAN_BEST_EFFORT ||
+                   priv->vlan_state == SJA1105_VLAN_FILTERING_FULL) &&
+                  key->type != SJA1105_KEY_VLAN_AWARE_VL) {
                NL_SET_ERR_MSG_MOD(extack,
                                   "Can only gate based on {DMAC, VID, PCP}");
                return -EOPNOTSUPP;
index ed5b465..992fedb 100644 (file)
@@ -64,6 +64,7 @@ struct aq_hw_caps_s {
        u8 rx_rings;
        bool flow_control;
        bool is_64_dma;
+       u32 quirks;
        u32 priv_data_len;
 };
 
index 4435c63..7c7bf6b 100644 (file)
@@ -415,6 +415,15 @@ int aq_nic_init(struct aq_nic_s *self)
            self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_TP) {
                self->aq_hw->phy_id = HW_ATL_PHY_ID_MAX;
                err = aq_phy_init(self->aq_hw);
+
+               /* Disable the PTP on NICs where it's known to cause datapath
+                * problems.
+                * Ideally this should have been done by PHY provisioning, but
+                * many units have been shipped with enabled PTP block already.
+                */
+               if (self->aq_nic_cfg.aq_hw_caps->quirks & AQ_NIC_QUIRK_BAD_PTP)
+                       if (self->aq_hw->phy_id != HW_ATL_PHY_ID_MAX)
+                               aq_phy_disable_ptp(self->aq_hw);
        }
 
        for (i = 0U; i < self->aq_vecs; i++) {
index 2ab0030..439ce96 100644 (file)
@@ -81,6 +81,8 @@ struct aq_nic_cfg_s {
 #define AQ_NIC_FLAG_ERR_UNPLUG  0x40000000U
 #define AQ_NIC_FLAG_ERR_HW      0x80000000U
 
+#define AQ_NIC_QUIRK_BAD_PTP    BIT(0)
+
 #define AQ_NIC_WOL_MODES        (WAKE_MAGIC |\
                                 WAKE_PHY)
 
index 51ae921..949ac23 100644 (file)
@@ -1,10 +1,14 @@
 // SPDX-License-Identifier: GPL-2.0-only
-/* aQuantia Corporation Network Driver
- * Copyright (C) 2018-2019 aQuantia Corporation. All rights reserved
+/* Atlantic Network Driver
+ *
+ * Copyright (C) 2018-2019 aQuantia Corporation
+ * Copyright (C) 2019-2020 Marvell International Ltd.
  */
 
 #include "aq_phy.h"
 
+#define HW_ATL_PTP_DISABLE_MSK BIT(10)
+
 bool aq_mdio_busy_wait(struct aq_hw_s *aq_hw)
 {
        int err = 0;
@@ -145,3 +149,24 @@ bool aq_phy_init(struct aq_hw_s *aq_hw)
 
        return true;
 }
+
+void aq_phy_disable_ptp(struct aq_hw_s *aq_hw)
+{
+       static const u16 ptp_registers[] = {
+               0x031e,
+               0x031d,
+               0x031c,
+               0x031b,
+       };
+       u16 val;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(ptp_registers); i++) {
+               val = aq_phy_read_reg(aq_hw, MDIO_MMD_VEND1,
+                                     ptp_registers[i]);
+
+               aq_phy_write_reg(aq_hw, MDIO_MMD_VEND1,
+                                ptp_registers[i],
+                                val & ~HW_ATL_PTP_DISABLE_MSK);
+       }
+}
index 84b72ad..86cc1ee 100644 (file)
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
-/* aQuantia Corporation Network Driver
- * Copyright (C) 2018-2019 aQuantia Corporation. All rights reserved
+/* Atlantic Network Driver
+ *
+ * Copyright (C) 2018-2019 aQuantia Corporation
+ * Copyright (C) 2019-2020 Marvell International Ltd.
  */
 
 #ifndef AQ_PHY_H
@@ -29,4 +31,6 @@ bool aq_phy_init_phy_id(struct aq_hw_s *aq_hw);
 
 bool aq_phy_init(struct aq_hw_s *aq_hw);
 
+void aq_phy_disable_ptp(struct aq_hw_s *aq_hw);
+
 #endif /* AQ_PHY_H */
index 14d79f7..2125bc2 100644 (file)
@@ -93,6 +93,25 @@ const struct aq_hw_caps_s hw_atl_b0_caps_aqc109 = {
                          AQ_NIC_RATE_100M,
 };
 
+const struct aq_hw_caps_s hw_atl_b0_caps_aqc111 = {
+       DEFAULT_B0_BOARD_BASIC_CAPABILITIES,
+       .media_type = AQ_HW_MEDIA_TYPE_TP,
+       .link_speed_msk = AQ_NIC_RATE_5G |
+                         AQ_NIC_RATE_2G5 |
+                         AQ_NIC_RATE_1G |
+                         AQ_NIC_RATE_100M,
+       .quirks = AQ_NIC_QUIRK_BAD_PTP,
+};
+
+const struct aq_hw_caps_s hw_atl_b0_caps_aqc112 = {
+       DEFAULT_B0_BOARD_BASIC_CAPABILITIES,
+       .media_type = AQ_HW_MEDIA_TYPE_TP,
+       .link_speed_msk = AQ_NIC_RATE_2G5 |
+                         AQ_NIC_RATE_1G  |
+                         AQ_NIC_RATE_100M,
+       .quirks = AQ_NIC_QUIRK_BAD_PTP,
+};
+
 static int hw_atl_b0_hw_reset(struct aq_hw_s *self)
 {
        int err = 0;
@@ -354,8 +373,13 @@ static int hw_atl_b0_hw_init_tx_tc_rate_limit(struct aq_hw_s *self)
 
        /* WSP, if min_rate is set for at least one TC.
         * RR otherwise.
+        *
+        * NB! MAC FW sets arb mode itself if PTP is enabled. We shouldn't
+        * overwrite it here in that case.
         */
-       hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, min_rate_msk ? 1U : 0U);
+       if (!nic_cfg->is_ptp)
+               hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, min_rate_msk ? 1U : 0U);
+
        /* Data TC Arbiter takes precedence over Descriptor TC Arbiter,
         * leave Descriptor TC Arbiter as RR.
         */
index 30f468f..16091af 100644 (file)
@@ -18,17 +18,15 @@ extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc100;
 extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc107;
 extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc108;
 extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc109;
-
-#define hw_atl_b0_caps_aqc111 hw_atl_b0_caps_aqc108
-#define hw_atl_b0_caps_aqc112 hw_atl_b0_caps_aqc109
+extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc111;
+extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc112;
 
 #define hw_atl_b0_caps_aqc100s hw_atl_b0_caps_aqc100
 #define hw_atl_b0_caps_aqc107s hw_atl_b0_caps_aqc107
 #define hw_atl_b0_caps_aqc108s hw_atl_b0_caps_aqc108
 #define hw_atl_b0_caps_aqc109s hw_atl_b0_caps_aqc109
-
-#define hw_atl_b0_caps_aqc111s hw_atl_b0_caps_aqc108
-#define hw_atl_b0_caps_aqc112s hw_atl_b0_caps_aqc109
+#define hw_atl_b0_caps_aqc111s hw_atl_b0_caps_aqc111
+#define hw_atl_b0_caps_aqc112s hw_atl_b0_caps_aqc112
 
 extern const struct aq_hw_ops hw_atl_ops_b0;
 
index 3c8e804..d775b23 100644 (file)
@@ -1700,7 +1700,7 @@ void hw_atl_rpfl3l4_ipv6_src_addr_set(struct aq_hw_s *aq_hw, u8 location,
        for (i = 0; i < 4; ++i)
                aq_hw_write_reg(aq_hw,
                                HW_ATL_RPF_L3_SRCA_ADR(location + i),
-                               ipv6_src[i]);
+                               ipv6_src[3 - i]);
 }
 
 void hw_atl_rpfl3l4_ipv6_dest_addr_set(struct aq_hw_s *aq_hw, u8 location,
@@ -1711,7 +1711,7 @@ void hw_atl_rpfl3l4_ipv6_dest_addr_set(struct aq_hw_s *aq_hw, u8 location,
        for (i = 0; i < 4; ++i)
                aq_hw_write_reg(aq_hw,
                                HW_ATL_RPF_L3_DSTA_ADR(location + i),
-                               ipv6_dest[i]);
+                               ipv6_dest[3 - i]);
 }
 
 u32 hw_atl_sem_ram_get(struct aq_hw_s *self)
index 0622079..7430ff0 100644 (file)
  */
 
  /* Register address for bitfield pif_rpf_l3_da0_i[31:0] */
-#define HW_ATL_RPF_L3_DSTA_ADR(filter) (0x000053B0 + (filter) * 0x4)
+#define HW_ATL_RPF_L3_DSTA_ADR(filter) (0x000053D0 + (filter) * 0x4)
 /* Bitmask for bitfield l3_da0[1F:0] */
 #define HW_ATL_RPF_L3_DSTA_MSK 0xFFFFFFFFu
 /* Inverted bitmask for bitfield l3_da0[1F:0] */
index 112edbd..38cce66 100644 (file)
@@ -556,7 +556,8 @@ static int ag71xx_mdio_probe(struct ag71xx *ag)
        ag->mdio_reset = of_reset_control_get_exclusive(np, "mdio");
        if (IS_ERR(ag->mdio_reset)) {
                netif_err(ag, probe, ndev, "Failed to get reset mdio.\n");
-               return PTR_ERR(ag->mdio_reset);
+               err = PTR_ERR(ag->mdio_reset);
+               goto mdio_err_put_clk;
        }
 
        mii_bus->name = "ag71xx_mdio";
index b9b4edb..9b7f1af 100644 (file)
@@ -1249,8 +1249,12 @@ out_disable_adv_intr:
 
 static void __alx_stop(struct alx_priv *alx)
 {
-       alx_halt(alx);
        alx_free_irq(alx);
+
+       cancel_work_sync(&alx->link_check_wk);
+       cancel_work_sync(&alx->reset_wk);
+
+       alx_halt(alx);
        alx_free_rings(alx);
        alx_free_napis(alx);
 }
@@ -1855,9 +1859,6 @@ static void alx_remove(struct pci_dev *pdev)
        struct alx_priv *alx = pci_get_drvdata(pdev);
        struct alx_hw *hw = &alx->hw;
 
-       cancel_work_sync(&alx->link_check_wk);
-       cancel_work_sync(&alx->reset_wk);
-
        /* restore permanent mac address */
        alx_set_macaddr(hw, hw->perm_addr);
 
index c62589c..7463a18 100644 (file)
@@ -3418,7 +3418,7 @@ void bnxt_set_tpa_flags(struct bnxt *bp)
  */
 void bnxt_set_ring_params(struct bnxt *bp)
 {
-       u32 ring_size, rx_size, rx_space;
+       u32 ring_size, rx_size, rx_space, max_rx_cmpl;
        u32 agg_factor = 0, agg_ring_size = 0;
 
        /* 8 for CRC and VLAN */
@@ -3474,7 +3474,15 @@ void bnxt_set_ring_params(struct bnxt *bp)
        bp->tx_nr_pages = bnxt_calc_nr_ring_pages(ring_size, TX_DESC_CNT);
        bp->tx_ring_mask = (bp->tx_nr_pages * TX_DESC_CNT) - 1;
 
-       ring_size = bp->rx_ring_size * (2 + agg_factor) + bp->tx_ring_size;
+       max_rx_cmpl = bp->rx_ring_size;
+       /* MAX TPA needs to be added because TPA_START completions are
+        * immediately recycled, so the TPA completions are not bound by
+        * the RX ring size.
+        */
+       if (bp->flags & BNXT_FLAG_TPA)
+               max_rx_cmpl += bp->max_tpa;
+       /* RX and TPA completions are 32-byte, all others are 16-byte */
+       ring_size = max_rx_cmpl * 2 + agg_ring_size + bp->tx_ring_size;
        bp->cp_ring_size = ring_size;
 
        bp->cp_nr_pages = bnxt_calc_nr_ring_pages(ring_size, CP_DESC_CNT);
@@ -6292,6 +6300,7 @@ int bnxt_hwrm_set_coal(struct bnxt *bp)
 
 static void bnxt_hwrm_stat_ctx_free(struct bnxt *bp)
 {
+       struct hwrm_stat_ctx_clr_stats_input req0 = {0};
        struct hwrm_stat_ctx_free_input req = {0};
        int i;
 
@@ -6301,6 +6310,7 @@ static void bnxt_hwrm_stat_ctx_free(struct bnxt *bp)
        if (BNXT_CHIP_TYPE_NITRO_A0(bp))
                return;
 
+       bnxt_hwrm_cmd_hdr_init(bp, &req0, HWRM_STAT_CTX_CLR_STATS, -1, -1);
        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_STAT_CTX_FREE, -1, -1);
 
        mutex_lock(&bp->hwrm_cmd_lock);
@@ -6310,7 +6320,11 @@ static void bnxt_hwrm_stat_ctx_free(struct bnxt *bp)
 
                if (cpr->hw_stats_ctx_id != INVALID_STATS_CTX_ID) {
                        req.stat_ctx_id = cpu_to_le32(cpr->hw_stats_ctx_id);
-
+                       if (BNXT_FW_MAJ(bp) <= 20) {
+                               req0.stat_ctx_id = req.stat_ctx_id;
+                               _hwrm_send_message(bp, &req0, sizeof(req0),
+                                                  HWRM_CMD_TIMEOUT);
+                       }
                        _hwrm_send_message(bp, &req, sizeof(req),
                                           HWRM_CMD_TIMEOUT);
 
@@ -6976,7 +6990,8 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
                bp->fw_cap |= BNXT_FW_CAP_ERR_RECOVER_RELOAD;
 
        bp->tx_push_thresh = 0;
-       if (flags & FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED)
+       if ((flags & FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED) &&
+           BNXT_FW_MAJ(bp) > 217)
                bp->tx_push_thresh = BNXT_TX_PUSH_THRESH;
 
        hw_resc->max_rsscos_ctxs = le16_to_cpu(resp->max_rsscos_ctx);
@@ -7240,8 +7255,9 @@ static int __bnxt_hwrm_ver_get(struct bnxt *bp, bool silent)
 static int bnxt_hwrm_ver_get(struct bnxt *bp)
 {
        struct hwrm_ver_get_output *resp = bp->hwrm_cmd_resp_addr;
+       u16 fw_maj, fw_min, fw_bld, fw_rsv;
        u32 dev_caps_cfg, hwrm_ver;
-       int rc;
+       int rc, len;
 
        bp->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
        mutex_lock(&bp->hwrm_cmd_lock);
@@ -7273,9 +7289,22 @@ static int bnxt_hwrm_ver_get(struct bnxt *bp)
                         resp->hwrm_intf_maj_8b, resp->hwrm_intf_min_8b,
                         resp->hwrm_intf_upd_8b);
 
-       snprintf(bp->fw_ver_str, BC_HWRM_STR_LEN, "%d.%d.%d.%d",
-                resp->hwrm_fw_maj_8b, resp->hwrm_fw_min_8b,
-                resp->hwrm_fw_bld_8b, resp->hwrm_fw_rsvd_8b);
+       fw_maj = le16_to_cpu(resp->hwrm_fw_major);
+       if (bp->hwrm_spec_code > 0x10803 && fw_maj) {
+               fw_min = le16_to_cpu(resp->hwrm_fw_minor);
+               fw_bld = le16_to_cpu(resp->hwrm_fw_build);
+               fw_rsv = le16_to_cpu(resp->hwrm_fw_patch);
+               len = FW_VER_STR_LEN;
+       } else {
+               fw_maj = resp->hwrm_fw_maj_8b;
+               fw_min = resp->hwrm_fw_min_8b;
+               fw_bld = resp->hwrm_fw_bld_8b;
+               fw_rsv = resp->hwrm_fw_rsvd_8b;
+               len = BC_HWRM_STR_LEN;
+       }
+       bp->fw_ver_code = BNXT_FW_VER_CODE(fw_maj, fw_min, fw_bld, fw_rsv);
+       snprintf(bp->fw_ver_str, len, "%d.%d.%d.%d", fw_maj, fw_min, fw_bld,
+                fw_rsv);
 
        if (strlen(resp->active_pkg_name)) {
                int fw_ver_len = strlen(bp->fw_ver_str);
@@ -10037,7 +10066,7 @@ static void bnxt_timer(struct timer_list *t)
        struct bnxt *bp = from_timer(bp, t, timer);
        struct net_device *dev = bp->dev;
 
-       if (!netif_running(dev))
+       if (!netif_running(dev) || !test_bit(BNXT_STATE_OPEN, &bp->state))
                return;
 
        if (atomic_read(&bp->intr_sem) != 0)
@@ -10364,15 +10393,15 @@ static void bnxt_sp_task(struct work_struct *work)
                                       &bp->sp_event))
                        bnxt_hwrm_phy_qcaps(bp);
 
-               if (test_and_clear_bit(BNXT_LINK_CFG_CHANGE_SP_EVENT,
-                                      &bp->sp_event))
-                       bnxt_init_ethtool_link_settings(bp);
-
                rc = bnxt_update_link(bp, true);
-               mutex_unlock(&bp->link_lock);
                if (rc)
                        netdev_err(bp->dev, "SP task can't update link (rc: %x)\n",
                                   rc);
+
+               if (test_and_clear_bit(BNXT_LINK_CFG_CHANGE_SP_EVENT,
+                                      &bp->sp_event))
+                       bnxt_init_ethtool_link_settings(bp);
+               mutex_unlock(&bp->link_lock);
        }
        if (test_and_clear_bit(BNXT_UPDATE_PHY_SP_EVENT, &bp->sp_event)) {
                int rc;
@@ -11892,7 +11921,8 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        dev->ethtool_ops = &bnxt_ethtool_ops;
        pci_set_drvdata(pdev, dev);
 
-       bnxt_vpd_read_info(bp);
+       if (BNXT_PF(bp))
+               bnxt_vpd_read_info(bp);
 
        rc = bnxt_alloc_hwrm_resources(bp);
        if (rc)
@@ -12133,19 +12163,9 @@ static int bnxt_resume(struct device *device)
                goto resume_exit;
        }
 
-       if (bnxt_hwrm_queue_qportcfg(bp)) {
-               rc = -ENODEV;
+       rc = bnxt_hwrm_func_qcaps(bp);
+       if (rc)
                goto resume_exit;
-       }
-
-       if (bp->hwrm_spec_code >= 0x10803) {
-               if (bnxt_alloc_ctx_mem(bp)) {
-                       rc = -ENODEV;
-                       goto resume_exit;
-               }
-       }
-       if (BNXT_NEW_RM(bp))
-               bnxt_hwrm_func_resc_qcaps(bp, false);
 
        if (bnxt_hwrm_func_drv_rgtr(bp, NULL, 0, false)) {
                rc = -ENODEV;
@@ -12161,6 +12181,8 @@ static int bnxt_resume(struct device *device)
 
 resume_exit:
        bnxt_ulp_start(bp, rc);
+       if (!rc)
+               bnxt_reenable_sriov(bp);
        rtnl_unlock();
        return rc;
 }
@@ -12204,6 +12226,9 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
                bnxt_close(netdev);
 
        pci_disable_device(pdev);
+       bnxt_free_ctx_mem(bp);
+       kfree(bp->ctx);
+       bp->ctx = NULL;
        rtnl_unlock();
 
        /* Request a slot slot reset. */
@@ -12237,12 +12262,16 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
                pci_set_master(pdev);
 
                err = bnxt_hwrm_func_reset(bp);
-               if (!err && netif_running(netdev))
-                       err = bnxt_open(netdev);
-
-               if (!err)
-                       result = PCI_ERS_RESULT_RECOVERED;
+               if (!err) {
+                       err = bnxt_hwrm_func_qcaps(bp);
+                       if (!err && netif_running(netdev))
+                               err = bnxt_open(netdev);
+               }
                bnxt_ulp_start(bp, err);
+               if (!err) {
+                       bnxt_reenable_sriov(bp);
+                       result = PCI_ERS_RESULT_RECOVERED;
+               }
        }
 
        if (result != PCI_ERS_RESULT_RECOVERED) {
index 9e173d7..78e2fd6 100644 (file)
@@ -1746,6 +1746,11 @@ struct bnxt {
 #define PHY_VER_STR_LEN         (FW_VER_STR_LEN - BC_HWRM_STR_LEN)
        char                    fw_ver_str[FW_VER_STR_LEN];
        char                    hwrm_ver_supp[FW_VER_STR_LEN];
+       u64                     fw_ver_code;
+#define BNXT_FW_VER_CODE(maj, min, bld, rsv)                   \
+       ((u64)(maj) << 48 | (u64)(min) << 32 | (u64)(bld) << 16 | (rsv))
+#define BNXT_FW_MAJ(bp)                ((bp)->fw_ver_code >> 48)
+
        __be16                  vxlan_port;
        u8                      vxlan_port_cnt;
        __le16                  vxlan_fw_dst_port_id;
index 6b88143..b4aa56d 100644 (file)
@@ -1765,8 +1765,11 @@ static int bnxt_set_pauseparam(struct net_device *dev,
        if (epause->tx_pause)
                link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_TX;
 
-       if (netif_running(dev))
+       if (netif_running(dev)) {
+               mutex_lock(&bp->link_lock);
                rc = bnxt_hwrm_set_pause(bp);
+               mutex_unlock(&bp->link_lock);
+       }
        return rc;
 }
 
index 3a9a51f..392e32c 100644 (file)
@@ -396,6 +396,7 @@ static void bnxt_free_vf_resources(struct bnxt *bp)
                }
        }
 
+       bp->pf.active_vfs = 0;
        kfree(bp->pf.vf);
        bp->pf.vf = NULL;
 }
@@ -835,7 +836,6 @@ void bnxt_sriov_disable(struct bnxt *bp)
 
        bnxt_free_vf_resources(bp);
 
-       bp->pf.active_vfs = 0;
        /* Reclaim all resources for the PF. */
        rtnl_lock();
        bnxt_restore_pf_fw_resources(bp);
index 0eef4f5..4a11c1e 100644 (file)
@@ -1889,7 +1889,8 @@ static void bnxt_tc_setup_indr_rel(void *cb_priv)
 }
 
 static int bnxt_tc_setup_indr_block(struct net_device *netdev, struct bnxt *bp,
-                                   struct flow_block_offload *f)
+                                   struct flow_block_offload *f, void *data,
+                                   void (*cleanup)(struct flow_block_cb *block_cb))
 {
        struct bnxt_flower_indr_block_cb_priv *cb_priv;
        struct flow_block_cb *block_cb;
@@ -1907,9 +1908,10 @@ static int bnxt_tc_setup_indr_block(struct net_device *netdev, struct bnxt *bp,
                cb_priv->bp = bp;
                list_add(&cb_priv->list, &bp->tc_indr_block_list);
 
-               block_cb = flow_block_cb_alloc(bnxt_tc_setup_indr_block_cb,
-                                              cb_priv, cb_priv,
-                                              bnxt_tc_setup_indr_rel);
+               block_cb = flow_indr_block_cb_alloc(bnxt_tc_setup_indr_block_cb,
+                                                   cb_priv, cb_priv,
+                                                   bnxt_tc_setup_indr_rel, f,
+                                                   netdev, data, bp, cleanup);
                if (IS_ERR(block_cb)) {
                        list_del(&cb_priv->list);
                        kfree(cb_priv);
@@ -1930,7 +1932,7 @@ static int bnxt_tc_setup_indr_block(struct net_device *netdev, struct bnxt *bp,
                if (!block_cb)
                        return -ENOENT;
 
-               flow_block_cb_remove(block_cb, f);
+               flow_indr_block_cb_remove(block_cb, f);
                list_del(&block_cb->driver_list);
                break;
        default:
@@ -1945,14 +1947,17 @@ static bool bnxt_is_netdev_indr_offload(struct net_device *netdev)
 }
 
 static int bnxt_tc_setup_indr_cb(struct net_device *netdev, void *cb_priv,
-                                enum tc_setup_type type, void *type_data)
+                                enum tc_setup_type type, void *type_data,
+                                void *data,
+                                void (*cleanup)(struct flow_block_cb *block_cb))
 {
        if (!bnxt_is_netdev_indr_offload(netdev))
                return -EOPNOTSUPP;
 
        switch (type) {
        case TC_SETUP_BLOCK:
-               return bnxt_tc_setup_indr_block(netdev, cb_priv, type_data);
+               return bnxt_tc_setup_indr_block(netdev, cb_priv, type_data, data,
+                                               cleanup);
        default:
                break;
        }
@@ -2074,7 +2079,7 @@ void bnxt_shutdown_tc(struct bnxt *bp)
                return;
 
        flow_indr_dev_unregister(bnxt_tc_setup_indr_cb, bp,
-                                bnxt_tc_setup_indr_block_cb);
+                                bnxt_tc_setup_indr_rel);
        rhashtable_destroy(&tc_info->flow_table);
        rhashtable_destroy(&tc_info->l2_table);
        rhashtable_destroy(&tc_info->decap_l2_table);
index ff31da0..e471b14 100644 (file)
@@ -459,17 +459,6 @@ static inline void bcmgenet_rdma_ring_writel(struct bcmgenet_priv *priv,
                        genet_dma_ring_regs[r]);
 }
 
-static bool bcmgenet_hfb_is_filter_enabled(struct bcmgenet_priv *priv,
-                                          u32 f_index)
-{
-       u32 offset;
-       u32 reg;
-
-       offset = HFB_FLT_ENABLE_V3PLUS + (f_index < 32) * sizeof(u32);
-       reg = bcmgenet_hfb_reg_readl(priv, offset);
-       return !!(reg & (1 << (f_index % 32)));
-}
-
 static void bcmgenet_hfb_enable_filter(struct bcmgenet_priv *priv, u32 f_index)
 {
        u32 offset;
@@ -533,19 +522,6 @@ static void bcmgenet_hfb_set_filter_length(struct bcmgenet_priv *priv,
        bcmgenet_hfb_reg_writel(priv, reg, offset);
 }
 
-static int bcmgenet_hfb_find_unused_filter(struct bcmgenet_priv *priv)
-{
-       u32 f_index;
-
-       /* First MAX_NUM_OF_FS_RULES are reserved for Rx NFC filters */
-       for (f_index = MAX_NUM_OF_FS_RULES;
-            f_index < priv->hw_params->hfb_filter_cnt; f_index++)
-               if (!bcmgenet_hfb_is_filter_enabled(priv, f_index))
-                       return f_index;
-
-       return -ENOMEM;
-}
-
 static int bcmgenet_hfb_validate_mask(void *mask, size_t size)
 {
        while (size) {
@@ -567,14 +543,14 @@ static int bcmgenet_hfb_validate_mask(void *mask, size_t size)
 #define VALIDATE_MASK(x) \
        bcmgenet_hfb_validate_mask(&(x), sizeof(x))
 
-static int bcmgenet_hfb_insert_data(u32 *f, int offset,
-                                   void *val, void *mask, size_t size)
+static int bcmgenet_hfb_insert_data(struct bcmgenet_priv *priv, u32 f_index,
+                                   u32 offset, void *val, void *mask,
+                                   size_t size)
 {
-       int index;
-       u32 tmp;
+       u32 index, tmp;
 
-       index = offset / 2;
-       tmp = f[index];
+       index = f_index * priv->hw_params->hfb_filter_size + offset / 2;
+       tmp = bcmgenet_hfb_readl(priv, index * sizeof(u32));
 
        while (size--) {
                if (offset++ & 1) {
@@ -591,9 +567,10 @@ static int bcmgenet_hfb_insert_data(u32 *f, int offset,
                                tmp |= 0x10000;
                                break;
                        }
-                       f[index++] = tmp;
+                       bcmgenet_hfb_writel(priv, tmp, index++ * sizeof(u32));
                        if (size)
-                               tmp = f[index];
+                               tmp = bcmgenet_hfb_readl(priv,
+                                                        index * sizeof(u32));
                } else {
                        tmp &= ~0xCFF00;
                        tmp |= (*(unsigned char *)val++) << 8;
@@ -609,43 +586,26 @@ static int bcmgenet_hfb_insert_data(u32 *f, int offset,
                                break;
                        }
                        if (!size)
-                               f[index] = tmp;
+                               bcmgenet_hfb_writel(priv, tmp, index * sizeof(u32));
                }
        }
 
        return 0;
 }
 
-static void bcmgenet_hfb_set_filter(struct bcmgenet_priv *priv, u32 *f_data,
-                                   u32 f_length, u32 rx_queue, int f_index)
-{
-       u32 base = f_index * priv->hw_params->hfb_filter_size;
-       int i;
-
-       for (i = 0; i < f_length; i++)
-               bcmgenet_hfb_writel(priv, f_data[i], (base + i) * sizeof(u32));
-
-       bcmgenet_hfb_set_filter_length(priv, f_index, 2 * f_length);
-       bcmgenet_hfb_set_filter_rx_queue_mapping(priv, f_index, rx_queue);
-}
-
-static int bcmgenet_hfb_create_rxnfc_filter(struct bcmgenet_priv *priv,
-                                           struct bcmgenet_rxnfc_rule *rule)
+static void bcmgenet_hfb_create_rxnfc_filter(struct bcmgenet_priv *priv,
+                                            struct bcmgenet_rxnfc_rule *rule)
 {
        struct ethtool_rx_flow_spec *fs = &rule->fs;
-       int err = 0, offset = 0, f_length = 0;
-       u16 val_16, mask_16;
+       u32 offset = 0, f_length = 0, f;
        u8 val_8, mask_8;
+       __be16 val_16;
+       u16 mask_16;
        size_t size;
-       u32 *f_data;
-
-       f_data = kcalloc(priv->hw_params->hfb_filter_size, sizeof(u32),
-                        GFP_KERNEL);
-       if (!f_data)
-               return -ENOMEM;
 
+       f = fs->location;
        if (fs->flow_type & FLOW_MAC_EXT) {
-               bcmgenet_hfb_insert_data(f_data, 0,
+               bcmgenet_hfb_insert_data(priv, f, 0,
                                         &fs->h_ext.h_dest, &fs->m_ext.h_dest,
                                         sizeof(fs->h_ext.h_dest));
        }
@@ -653,11 +613,11 @@ static int bcmgenet_hfb_create_rxnfc_filter(struct bcmgenet_priv *priv,
        if (fs->flow_type & FLOW_EXT) {
                if (fs->m_ext.vlan_etype ||
                    fs->m_ext.vlan_tci) {
-                       bcmgenet_hfb_insert_data(f_data, 12,
+                       bcmgenet_hfb_insert_data(priv, f, 12,
                                                 &fs->h_ext.vlan_etype,
                                                 &fs->m_ext.vlan_etype,
                                                 sizeof(fs->h_ext.vlan_etype));
-                       bcmgenet_hfb_insert_data(f_data, 14,
+                       bcmgenet_hfb_insert_data(priv, f, 14,
                                                 &fs->h_ext.vlan_tci,
                                                 &fs->m_ext.vlan_tci,
                                                 sizeof(fs->h_ext.vlan_tci));
@@ -669,15 +629,15 @@ static int bcmgenet_hfb_create_rxnfc_filter(struct bcmgenet_priv *priv,
        switch (fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {
        case ETHER_FLOW:
                f_length += DIV_ROUND_UP(ETH_HLEN, 2);
-               bcmgenet_hfb_insert_data(f_data, 0,
+               bcmgenet_hfb_insert_data(priv, f, 0,
                                         &fs->h_u.ether_spec.h_dest,
                                         &fs->m_u.ether_spec.h_dest,
                                         sizeof(fs->h_u.ether_spec.h_dest));
-               bcmgenet_hfb_insert_data(f_data, ETH_ALEN,
+               bcmgenet_hfb_insert_data(priv, f, ETH_ALEN,
                                         &fs->h_u.ether_spec.h_source,
                                         &fs->m_u.ether_spec.h_source,
                                         sizeof(fs->h_u.ether_spec.h_source));
-               bcmgenet_hfb_insert_data(f_data, (2 * ETH_ALEN) + offset,
+               bcmgenet_hfb_insert_data(priv, f, (2 * ETH_ALEN) + offset,
                                         &fs->h_u.ether_spec.h_proto,
                                         &fs->m_u.ether_spec.h_proto,
                                         sizeof(fs->h_u.ether_spec.h_proto));
@@ -687,21 +647,21 @@ static int bcmgenet_hfb_create_rxnfc_filter(struct bcmgenet_priv *priv,
                /* Specify IP Ether Type */
                val_16 = htons(ETH_P_IP);
                mask_16 = 0xFFFF;
-               bcmgenet_hfb_insert_data(f_data, (2 * ETH_ALEN) + offset,
+               bcmgenet_hfb_insert_data(priv, f, (2 * ETH_ALEN) + offset,
                                         &val_16, &mask_16, sizeof(val_16));
-               bcmgenet_hfb_insert_data(f_data, 15 + offset,
+               bcmgenet_hfb_insert_data(priv, f, 15 + offset,
                                         &fs->h_u.usr_ip4_spec.tos,
                                         &fs->m_u.usr_ip4_spec.tos,
                                         sizeof(fs->h_u.usr_ip4_spec.tos));
-               bcmgenet_hfb_insert_data(f_data, 23 + offset,
+               bcmgenet_hfb_insert_data(priv, f, 23 + offset,
                                         &fs->h_u.usr_ip4_spec.proto,
                                         &fs->m_u.usr_ip4_spec.proto,
                                         sizeof(fs->h_u.usr_ip4_spec.proto));
-               bcmgenet_hfb_insert_data(f_data, 26 + offset,
+               bcmgenet_hfb_insert_data(priv, f, 26 + offset,
                                         &fs->h_u.usr_ip4_spec.ip4src,
                                         &fs->m_u.usr_ip4_spec.ip4src,
                                         sizeof(fs->h_u.usr_ip4_spec.ip4src));
-               bcmgenet_hfb_insert_data(f_data, 30 + offset,
+               bcmgenet_hfb_insert_data(priv, f, 30 + offset,
                                         &fs->h_u.usr_ip4_spec.ip4dst,
                                         &fs->m_u.usr_ip4_spec.ip4dst,
                                         sizeof(fs->h_u.usr_ip4_spec.ip4dst));
@@ -711,11 +671,11 @@ static int bcmgenet_hfb_create_rxnfc_filter(struct bcmgenet_priv *priv,
                /* Only supports 20 byte IPv4 header */
                val_8 = 0x45;
                mask_8 = 0xFF;
-               bcmgenet_hfb_insert_data(f_data, ETH_HLEN + offset,
+               bcmgenet_hfb_insert_data(priv, f, ETH_HLEN + offset,
                                         &val_8, &mask_8,
                                         sizeof(val_8));
                size = sizeof(fs->h_u.usr_ip4_spec.l4_4_bytes);
-               bcmgenet_hfb_insert_data(f_data,
+               bcmgenet_hfb_insert_data(priv, f,
                                         ETH_HLEN + 20 + offset,
                                         &fs->h_u.usr_ip4_spec.l4_4_bytes,
                                         &fs->m_u.usr_ip4_spec.l4_4_bytes,
@@ -724,87 +684,42 @@ static int bcmgenet_hfb_create_rxnfc_filter(struct bcmgenet_priv *priv,
                break;
        }
 
+       bcmgenet_hfb_set_filter_length(priv, f, 2 * f_length);
        if (!fs->ring_cookie || fs->ring_cookie == RX_CLS_FLOW_WAKE) {
                /* Ring 0 flows can be handled by the default Descriptor Ring
                 * We'll map them to ring 0, but don't enable the filter
                 */
-               bcmgenet_hfb_set_filter(priv, f_data, f_length, 0,
-                                       fs->location);
+               bcmgenet_hfb_set_filter_rx_queue_mapping(priv, f, 0);
                rule->state = BCMGENET_RXNFC_STATE_DISABLED;
        } else {
                /* Other Rx rings are direct mapped here */
-               bcmgenet_hfb_set_filter(priv, f_data, f_length,
-                                       fs->ring_cookie, fs->location);
-               bcmgenet_hfb_enable_filter(priv, fs->location);
+               bcmgenet_hfb_set_filter_rx_queue_mapping(priv, f,
+                                                        fs->ring_cookie);
+               bcmgenet_hfb_enable_filter(priv, f);
                rule->state = BCMGENET_RXNFC_STATE_ENABLED;
        }
-
-       kfree(f_data);
-
-       return err;
 }
 
-/* bcmgenet_hfb_add_filter
- *
- * Add new filter to Hardware Filter Block to match and direct Rx traffic to
- * desired Rx queue.
- *
- * f_data is an array of unsigned 32-bit integers where each 32-bit integer
- * provides filter data for 2 bytes (4 nibbles) of Rx frame:
- *
- * bits 31:20 - unused
- * bit  19    - nibble 0 match enable
- * bit  18    - nibble 1 match enable
- * bit  17    - nibble 2 match enable
- * bit  16    - nibble 3 match enable
- * bits 15:12 - nibble 0 data
- * bits 11:8  - nibble 1 data
- * bits 7:4   - nibble 2 data
- * bits 3:0   - nibble 3 data
- *
- * Example:
- * In order to match:
- * - Ethernet frame type = 0x0800 (IP)
- * - IP version field = 4
- * - IP protocol field = 0x11 (UDP)
- *
- * The following filter is needed:
- * u32 hfb_filter_ipv4_udp[] = {
- *   Rx frame offset 0x00: 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- *   Rx frame offset 0x08: 0x00000000, 0x00000000, 0x000F0800, 0x00084000,
- *   Rx frame offset 0x10: 0x00000000, 0x00000000, 0x00000000, 0x00030011,
- * };
+/* bcmgenet_hfb_clear
  *
- * To add the filter to HFB and direct the traffic to Rx queue 0, call:
- * bcmgenet_hfb_add_filter(priv, hfb_filter_ipv4_udp,
- *                         ARRAY_SIZE(hfb_filter_ipv4_udp), 0);
+ * Clear Hardware Filter Block and disable all filtering.
  */
-int bcmgenet_hfb_add_filter(struct bcmgenet_priv *priv, u32 *f_data,
-                           u32 f_length, u32 rx_queue)
+static void bcmgenet_hfb_clear_filter(struct bcmgenet_priv *priv, u32 f_index)
 {
-       int f_index;
-
-       f_index = bcmgenet_hfb_find_unused_filter(priv);
-       if (f_index < 0)
-               return -ENOMEM;
+       u32 base, i;
 
-       if (f_length > priv->hw_params->hfb_filter_size)
-               return -EINVAL;
-
-       bcmgenet_hfb_set_filter(priv, f_data, f_length, rx_queue, f_index);
-       bcmgenet_hfb_enable_filter(priv, f_index);
-
-       return 0;
+       base = f_index * priv->hw_params->hfb_filter_size;
+       for (i = 0; i < priv->hw_params->hfb_filter_size; i++)
+               bcmgenet_hfb_writel(priv, 0x0, (base + i) * sizeof(u32));
 }
 
-/* bcmgenet_hfb_clear
- *
- * Clear Hardware Filter Block and disable all filtering.
- */
 static void bcmgenet_hfb_clear(struct bcmgenet_priv *priv)
 {
        u32 i;
 
+       if (GENET_IS_V1(priv) || GENET_IS_V2(priv))
+               return;
+
        bcmgenet_hfb_reg_writel(priv, 0x0, HFB_CTRL);
        bcmgenet_hfb_reg_writel(priv, 0x0, HFB_FLT_ENABLE_V3PLUS);
        bcmgenet_hfb_reg_writel(priv, 0x0, HFB_FLT_ENABLE_V3PLUS + 4);
@@ -816,19 +731,18 @@ static void bcmgenet_hfb_clear(struct bcmgenet_priv *priv)
                bcmgenet_hfb_reg_writel(priv, 0x0,
                                        HFB_FLT_LEN_V3PLUS + i * sizeof(u32));
 
-       for (i = 0; i < priv->hw_params->hfb_filter_cnt *
-                       priv->hw_params->hfb_filter_size; i++)
-               bcmgenet_hfb_writel(priv, 0x0, i * sizeof(u32));
+       for (i = 0; i < priv->hw_params->hfb_filter_cnt; i++)
+               bcmgenet_hfb_clear_filter(priv, i);
 }
 
 static void bcmgenet_hfb_init(struct bcmgenet_priv *priv)
 {
        int i;
 
+       INIT_LIST_HEAD(&priv->rxnfc_list);
        if (GENET_IS_V1(priv) || GENET_IS_V2(priv))
                return;
 
-       INIT_LIST_HEAD(&priv->rxnfc_list);
        for (i = 0; i < MAX_NUM_OF_FS_RULES; i++) {
                INIT_LIST_HEAD(&priv->rxnfc_rules[i].list);
                priv->rxnfc_rules[i].state = BCMGENET_RXNFC_STATE_UNUSED;
@@ -1513,18 +1427,15 @@ static int bcmgenet_insert_flow(struct net_device *dev,
        loc_rule = &priv->rxnfc_rules[cmd->fs.location];
        if (loc_rule->state == BCMGENET_RXNFC_STATE_ENABLED)
                bcmgenet_hfb_disable_filter(priv, cmd->fs.location);
-       if (loc_rule->state != BCMGENET_RXNFC_STATE_UNUSED)
+       if (loc_rule->state != BCMGENET_RXNFC_STATE_UNUSED) {
                list_del(&loc_rule->list);
+               bcmgenet_hfb_clear_filter(priv, cmd->fs.location);
+       }
        loc_rule->state = BCMGENET_RXNFC_STATE_UNUSED;
        memcpy(&loc_rule->fs, &cmd->fs,
               sizeof(struct ethtool_rx_flow_spec));
 
-       err = bcmgenet_hfb_create_rxnfc_filter(priv, loc_rule);
-       if (err) {
-               netdev_err(dev, "rxnfc: Could not install rule (%d)\n",
-                          err);
-               return err;
-       }
+       bcmgenet_hfb_create_rxnfc_filter(priv, loc_rule);
 
        list_add_tail(&loc_rule->list, &priv->rxnfc_list);
 
@@ -1549,8 +1460,10 @@ static int bcmgenet_delete_flow(struct net_device *dev,
 
        if (rule->state == BCMGENET_RXNFC_STATE_ENABLED)
                bcmgenet_hfb_disable_filter(priv, cmd->fs.location);
-       if (rule->state != BCMGENET_RXNFC_STATE_UNUSED)
+       if (rule->state != BCMGENET_RXNFC_STATE_UNUSED) {
                list_del(&rule->list);
+               bcmgenet_hfb_clear_filter(priv, cmd->fs.location);
+       }
        rule->state = BCMGENET_RXNFC_STATE_UNUSED;
        memset(&rule->fs, 0, sizeof(struct ethtool_rx_flow_spec));
 
@@ -2118,11 +2031,6 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
                goto out;
        }
 
-       if (skb_padto(skb, ETH_ZLEN)) {
-               ret = NETDEV_TX_OK;
-               goto out;
-       }
-
        /* Retain how many bytes will be sent on the wire, without TSB inserted
         * by transmit checksum offload
         */
@@ -2169,6 +2077,9 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
                len_stat = (size << DMA_BUFLENGTH_SHIFT) |
                           (priv->hw_params->qtag_mask << DMA_TX_QTAG_SHIFT);
 
+               /* Note: if we ever change from DMA_TX_APPEND_CRC below we
+                * will need to restore software padding of "runt" packets
+                */
                if (!i) {
                        len_stat |= DMA_TX_APPEND_CRC | DMA_SOP;
                        if (skb->ip_summed == CHECKSUM_PARTIAL)
@@ -4077,7 +3988,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
        if (err)
                err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
        if (err)
-               goto err;
+               goto err_clk_disable;
 
        /* Mii wait queue */
        init_waitqueue_head(&priv->wq);
@@ -4089,14 +4000,14 @@ static int bcmgenet_probe(struct platform_device *pdev)
        if (IS_ERR(priv->clk_wol)) {
                dev_dbg(&priv->pdev->dev, "failed to get enet-wol clock\n");
                err = PTR_ERR(priv->clk_wol);
-               goto err;
+               goto err_clk_disable;
        }
 
        priv->clk_eee = devm_clk_get_optional(&priv->pdev->dev, "enet-eee");
        if (IS_ERR(priv->clk_eee)) {
                dev_dbg(&priv->pdev->dev, "failed to get enet-eee clock\n");
                err = PTR_ERR(priv->clk_eee);
-               goto err;
+               goto err_clk_disable;
        }
 
        /* If this is an internal GPHY, power it on now, before UniMAC is
@@ -4207,8 +4118,9 @@ static int bcmgenet_resume(struct device *d)
 {
        struct net_device *dev = dev_get_drvdata(d);
        struct bcmgenet_priv *priv = netdev_priv(dev);
+       struct bcmgenet_rxnfc_rule *rule;
        unsigned long dma_ctrl;
-       u32 offset, reg;
+       u32 reg;
        int ret;
 
        if (!netif_running(dev))
@@ -4239,10 +4151,11 @@ static int bcmgenet_resume(struct device *d)
 
        bcmgenet_set_hw_addr(priv, dev->dev_addr);
 
-       offset = HFB_FLT_ENABLE_V3PLUS;
-       bcmgenet_hfb_reg_writel(priv, priv->hfb_en[1], offset);
-       bcmgenet_hfb_reg_writel(priv, priv->hfb_en[2], offset + sizeof(u32));
-       bcmgenet_hfb_reg_writel(priv, priv->hfb_en[0], HFB_CTRL);
+       /* Restore hardware filters */
+       bcmgenet_hfb_clear(priv);
+       list_for_each_entry(rule, &priv->rxnfc_list, list)
+               if (rule->state != BCMGENET_RXNFC_STATE_UNUSED)
+                       bcmgenet_hfb_create_rxnfc_filter(priv, rule);
 
        if (priv->internal_phy) {
                reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
@@ -4286,7 +4199,6 @@ static int bcmgenet_suspend(struct device *d)
 {
        struct net_device *dev = dev_get_drvdata(d);
        struct bcmgenet_priv *priv = netdev_priv(dev);
-       u32 offset;
 
        if (!netif_running(dev))
                return 0;
@@ -4298,11 +4210,7 @@ static int bcmgenet_suspend(struct device *d)
        if (!device_may_wakeup(d))
                phy_suspend(dev->phydev);
 
-       /* Preserve filter state and disable filtering */
-       priv->hfb_en[0] = bcmgenet_hfb_reg_readl(priv, HFB_CTRL);
-       offset = HFB_FLT_ENABLE_V3PLUS;
-       priv->hfb_en[1] = bcmgenet_hfb_reg_readl(priv, offset);
-       priv->hfb_en[2] = bcmgenet_hfb_reg_readl(priv, offset + sizeof(u32));
+       /* Disable filtering */
        bcmgenet_hfb_reg_writel(priv, 0, HFB_CTRL);
 
        return 0;
index a12cb59..f6ca01d 100644 (file)
@@ -696,7 +696,6 @@ struct bcmgenet_priv {
        u32 wolopts;
        u8 sopass[SOPASS_MAX];
        bool wol_active;
-       u32 hfb_en[3];
 
        struct bcmgenet_mib_counters mib;
 
index 4ea6a26..1c86edd 100644 (file)
@@ -217,20 +217,28 @@ void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
 
        priv->wol_active = 0;
        clk_disable_unprepare(priv->clk_wol);
+       priv->crc_fwd_en = 0;
 
        /* Disable Magic Packet Detection */
-       reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
-       reg &= ~(MPD_EN | MPD_PW_EN);
-       bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
+       if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {
+               reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
+               if (!(reg & MPD_EN))
+                       return; /* already reset so skip the rest */
+               reg &= ~(MPD_EN | MPD_PW_EN);
+               bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
+       }
 
        /* Disable WAKE_FILTER Detection */
-       reg = bcmgenet_hfb_reg_readl(priv, HFB_CTRL);
-       reg &= ~(RBUF_HFB_EN | RBUF_ACPI_EN);
-       bcmgenet_hfb_reg_writel(priv, reg, HFB_CTRL);
+       if (priv->wolopts & WAKE_FILTER) {
+               reg = bcmgenet_hfb_reg_readl(priv, HFB_CTRL);
+               if (!(reg & RBUF_ACPI_EN))
+                       return; /* already reset so skip the rest */
+               reg &= ~(RBUF_HFB_EN | RBUF_ACPI_EN);
+               bcmgenet_hfb_reg_writel(priv, reg, HFB_CTRL);
+       }
 
        /* Disable CRC Forward */
        reg = bcmgenet_umac_readl(priv, UMAC_CMD);
        reg &= ~CMD_CRC_FWD;
        bcmgenet_umac_writel(priv, reg, UMAC_CMD);
-       priv->crc_fwd_en = 0;
 }
index 7a3b22b..ebff1fc 100644 (file)
@@ -18168,8 +18168,8 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev,
 
        rtnl_lock();
 
-       /* We probably don't have netdev yet */
-       if (!netdev || !netif_running(netdev))
+       /* Could be second call or maybe we don't have netdev yet */
+       if (!netdev || tp->pcierr_recovery || !netif_running(netdev))
                goto done;
 
        /* We needn't recover from permanent error */
index 5b9d7c6..2213e6a 100644 (file)
@@ -2558,22 +2558,23 @@ static int macb_open(struct net_device *dev)
 
        err = macb_phylink_connect(bp);
        if (err)
-               goto napi_exit;
+               goto reset_hw;
 
        netif_tx_start_all_queues(dev);
 
        if (bp->ptp_info)
                bp->ptp_info->ptp_init(dev);
 
-napi_exit:
+       return 0;
+
+reset_hw:
+       macb_reset_hw(bp);
        for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
                napi_disable(&queue->napi);
+       macb_free_consistent(bp);
 pm_exit:
-       if (err) {
-               pm_runtime_put_sync(&bp->pdev->dev);
-               return err;
-       }
-       return 0;
+       pm_runtime_put_sync(&bp->pdev->dev);
+       return err;
 }
 
 static int macb_close(struct net_device *dev)
@@ -2820,11 +2821,13 @@ static void macb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 {
        struct macb *bp = netdev_priv(netdev);
 
-       wol->supported = 0;
-       wol->wolopts = 0;
-
-       if (bp->wol & MACB_WOL_HAS_MAGIC_PACKET)
+       if (bp->wol & MACB_WOL_HAS_MAGIC_PACKET) {
                phylink_ethtool_get_wol(bp->phylink, wol);
+               wol->supported |= WAKE_MAGIC;
+
+               if (bp->wol & MACB_WOL_ENABLED)
+                       wol->wolopts |= WAKE_MAGIC;
+       }
 }
 
 static int macb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
@@ -2832,9 +2835,13 @@ static int macb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
        struct macb *bp = netdev_priv(netdev);
        int ret;
 
+       /* Pass the order to phylink layer */
        ret = phylink_ethtool_set_wol(bp->phylink, wol);
-       if (!ret)
-               return 0;
+       /* Don't manage WoL on MAC if handled by the PHY
+        * or if there's a failure in talking to the PHY
+        */
+       if (!ret || ret != -EOPNOTSUPP)
+               return ret;
 
        if (!(bp->wol & MACB_WOL_HAS_MAGIC_PACKET) ||
            (wol->wolopts & ~WAKE_MAGIC))
@@ -3729,7 +3736,7 @@ static int macb_init(struct platform_device *pdev)
 
        if (!(bp->caps & MACB_CAPS_USRIO_DISABLED)) {
                val = 0;
-               if (bp->phy_interface == PHY_INTERFACE_MODE_RGMII)
+               if (phy_interface_mode_is_rgmii(bp->phy_interface))
                        val = GEM_BIT(RGMII);
                else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII &&
                         (bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII))
@@ -3761,15 +3768,9 @@ static int macb_init(struct platform_device *pdev)
 
 static struct sifive_fu540_macb_mgmt *mgmt;
 
-/* Initialize and start the Receiver and Transmit subsystems */
-static int at91ether_start(struct net_device *dev)
+static int at91ether_alloc_coherent(struct macb *lp)
 {
-       struct macb *lp = netdev_priv(dev);
        struct macb_queue *q = &lp->queues[0];
-       struct macb_dma_desc *desc;
-       dma_addr_t addr;
-       u32 ctl;
-       int i;
 
        q->rx_ring = dma_alloc_coherent(&lp->pdev->dev,
                                         (AT91ETHER_MAX_RX_DESCR *
@@ -3791,6 +3792,43 @@ static int at91ether_start(struct net_device *dev)
                return -ENOMEM;
        }
 
+       return 0;
+}
+
+static void at91ether_free_coherent(struct macb *lp)
+{
+       struct macb_queue *q = &lp->queues[0];
+
+       if (q->rx_ring) {
+               dma_free_coherent(&lp->pdev->dev,
+                                 AT91ETHER_MAX_RX_DESCR *
+                                 macb_dma_desc_get_size(lp),
+                                 q->rx_ring, q->rx_ring_dma);
+               q->rx_ring = NULL;
+       }
+
+       if (q->rx_buffers) {
+               dma_free_coherent(&lp->pdev->dev,
+                                 AT91ETHER_MAX_RX_DESCR *
+                                 AT91ETHER_MAX_RBUFF_SZ,
+                                 q->rx_buffers, q->rx_buffers_dma);
+               q->rx_buffers = NULL;
+       }
+}
+
+/* Initialize and start the Receiver and Transmit subsystems */
+static int at91ether_start(struct macb *lp)
+{
+       struct macb_queue *q = &lp->queues[0];
+       struct macb_dma_desc *desc;
+       dma_addr_t addr;
+       u32 ctl;
+       int i, ret;
+
+       ret = at91ether_alloc_coherent(lp);
+       if (ret)
+               return ret;
+
        addr = q->rx_buffers_dma;
        for (i = 0; i < AT91ETHER_MAX_RX_DESCR; i++) {
                desc = macb_rx_desc(q, i);
@@ -3812,9 +3850,39 @@ static int at91ether_start(struct net_device *dev)
        ctl = macb_readl(lp, NCR);
        macb_writel(lp, NCR, ctl | MACB_BIT(RE) | MACB_BIT(TE));
 
+       /* Enable MAC interrupts */
+       macb_writel(lp, IER, MACB_BIT(RCOMP)    |
+                            MACB_BIT(RXUBR)    |
+                            MACB_BIT(ISR_TUND) |
+                            MACB_BIT(ISR_RLE)  |
+                            MACB_BIT(TCOMP)    |
+                            MACB_BIT(ISR_ROVR) |
+                            MACB_BIT(HRESP));
+
        return 0;
 }
 
+static void at91ether_stop(struct macb *lp)
+{
+       u32 ctl;
+
+       /* Disable MAC interrupts */
+       macb_writel(lp, IDR, MACB_BIT(RCOMP)    |
+                            MACB_BIT(RXUBR)    |
+                            MACB_BIT(ISR_TUND) |
+                            MACB_BIT(ISR_RLE)  |
+                            MACB_BIT(TCOMP)    |
+                            MACB_BIT(ISR_ROVR) |
+                            MACB_BIT(HRESP));
+
+       /* Disable Receiver and Transmitter */
+       ctl = macb_readl(lp, NCR);
+       macb_writel(lp, NCR, ctl & ~(MACB_BIT(TE) | MACB_BIT(RE)));
+
+       /* Free resources. */
+       at91ether_free_coherent(lp);
+}
+
 /* Open the ethernet interface */
 static int at91ether_open(struct net_device *dev)
 {
@@ -3834,63 +3902,36 @@ static int at91ether_open(struct net_device *dev)
 
        macb_set_hwaddr(lp);
 
-       ret = at91ether_start(dev);
+       ret = at91ether_start(lp);
        if (ret)
-               return ret;
-
-       /* Enable MAC interrupts */
-       macb_writel(lp, IER, MACB_BIT(RCOMP)    |
-                            MACB_BIT(RXUBR)    |
-                            MACB_BIT(ISR_TUND) |
-                            MACB_BIT(ISR_RLE)  |
-                            MACB_BIT(TCOMP)    |
-                            MACB_BIT(ISR_ROVR) |
-                            MACB_BIT(HRESP));
+               goto pm_exit;
 
        ret = macb_phylink_connect(lp);
        if (ret)
-               return ret;
+               goto stop;
 
        netif_start_queue(dev);
 
        return 0;
+
+stop:
+       at91ether_stop(lp);
+pm_exit:
+       pm_runtime_put_sync(&lp->pdev->dev);
+       return ret;
 }
 
 /* Close the interface */
 static int at91ether_close(struct net_device *dev)
 {
        struct macb *lp = netdev_priv(dev);
-       struct macb_queue *q = &lp->queues[0];
-       u32 ctl;
-
-       /* Disable Receiver and Transmitter */
-       ctl = macb_readl(lp, NCR);
-       macb_writel(lp, NCR, ctl & ~(MACB_BIT(TE) | MACB_BIT(RE)));
-
-       /* Disable MAC interrupts */
-       macb_writel(lp, IDR, MACB_BIT(RCOMP)    |
-                            MACB_BIT(RXUBR)    |
-                            MACB_BIT(ISR_TUND) |
-                            MACB_BIT(ISR_RLE)  |
-                            MACB_BIT(TCOMP)    |
-                            MACB_BIT(ISR_ROVR) |
-                            MACB_BIT(HRESP));
 
        netif_stop_queue(dev);
 
        phylink_stop(lp->phylink);
        phylink_disconnect_phy(lp->phylink);
 
-       dma_free_coherent(&lp->pdev->dev,
-                         AT91ETHER_MAX_RX_DESCR *
-                         macb_dma_desc_get_size(lp),
-                         q->rx_ring, q->rx_ring_dma);
-       q->rx_ring = NULL;
-
-       dma_free_coherent(&lp->pdev->dev,
-                         AT91ETHER_MAX_RX_DESCR * AT91ETHER_MAX_RBUFF_SZ,
-                         q->rx_buffers, q->rx_buffers_dma);
-       q->rx_buffers = NULL;
+       at91ether_stop(lp);
 
        return pm_runtime_put(&lp->pdev->dev);
 }
@@ -4387,7 +4428,7 @@ static int macb_probe(struct platform_device *pdev)
        bp->wol = 0;
        if (of_get_property(np, "magic-packet", NULL))
                bp->wol |= MACB_WOL_HAS_MAGIC_PACKET;
-       device_init_wakeup(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET);
+       device_set_wakeup_capable(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET);
 
        spin_lock_init(&bp->lock);
 
@@ -4563,10 +4604,10 @@ static int __maybe_unused macb_suspend(struct device *dev)
                        bp->pm_data.scrt2 = gem_readl_n(bp, ETHT, SCRT2_ETHT);
        }
 
-       netif_carrier_off(netdev);
        if (bp->ptp_info)
                bp->ptp_info->ptp_remove(netdev);
-       pm_runtime_force_suspend(dev);
+       if (!device_may_wakeup(dev))
+               pm_runtime_force_suspend(dev);
 
        return 0;
 }
@@ -4581,7 +4622,8 @@ static int __maybe_unused macb_resume(struct device *dev)
        if (!netif_running(netdev))
                return 0;
 
-       pm_runtime_force_resume(dev);
+       if (!device_may_wakeup(dev))
+               pm_runtime_force_resume(dev);
 
        if (bp->wol & MACB_WOL_ENABLED) {
                macb_writel(bp, IDR, MACB_BIT(WOL));
@@ -4619,7 +4661,7 @@ static int __maybe_unused macb_runtime_suspend(struct device *dev)
        struct net_device *netdev = dev_get_drvdata(dev);
        struct macb *bp = netdev_priv(netdev);
 
-       if (!(device_may_wakeup(&bp->dev->dev))) {
+       if (!(device_may_wakeup(dev))) {
                clk_disable_unprepare(bp->tx_clk);
                clk_disable_unprepare(bp->hclk);
                clk_disable_unprepare(bp->pclk);
@@ -4635,7 +4677,7 @@ static int __maybe_unused macb_runtime_resume(struct device *dev)
        struct net_device *netdev = dev_get_drvdata(dev);
        struct macb *bp = netdev_priv(netdev);
 
-       if (!(device_may_wakeup(&bp->dev->dev))) {
+       if (!(device_may_wakeup(dev))) {
                clk_prepare_enable(bp->pclk);
                clk_prepare_enable(bp->hclk);
                clk_prepare_enable(bp->tx_clk);
index 7b9cd69..d8ab8e3 100644 (file)
@@ -1975,7 +1975,6 @@ int cudbg_collect_dump_context(struct cudbg_init *pdbg_init,
        u8 mem_type[CTXT_INGRESS + 1] = { 0 };
        struct cudbg_buffer temp_buff = { 0 };
        struct cudbg_ch_cntxt *buff;
-       u64 *dst_off, *src_off;
        u8 *ctx_buf;
        u8 i, k;
        int rc;
@@ -2044,8 +2043,11 @@ int cudbg_collect_dump_context(struct cudbg_init *pdbg_init,
                }
 
                for (j = 0; j < max_ctx_qid; j++) {
+                       __be64 *dst_off;
+                       u64 *src_off;
+
                        src_off = (u64 *)(ctx_buf + j * SGE_CTXT_SIZE);
-                       dst_off = (u64 *)buff->data;
+                       dst_off = (__be64 *)buff->data;
 
                        /* The data is stored in 64-bit cpu order.  Convert it
                         * to big endian before parsing.
index d3c654b..80c6627 100644 (file)
@@ -136,6 +136,9 @@ static inline __u8 bitswap_1(unsigned char val)
               ((val & 0x02) << 5) |
               ((val & 0x01) << 7);
 }
+
+extern const char * const dcb_ver_array[];
+
 #define CXGB4_DCB_ENABLED true
 
 #else /* !CONFIG_CHELSIO_T4_DCB */
index 8284992..b477b88 100644 (file)
@@ -2379,7 +2379,6 @@ static const struct file_operations rss_vf_config_debugfs_fops = {
 };
 
 #ifdef CONFIG_CHELSIO_T4_DCB
-extern char *dcb_ver_array[];
 
 /* Data Center Briging information for each port.
  */
index 9fd4967..f27be11 100644 (file)
@@ -588,7 +588,7 @@ static void fw_caps_to_lmm(enum fw_port_type port_type,
 /**
  *     lmm_to_fw_caps - translate ethtool Link Mode Mask to Firmware
  *     capabilities
- *     @et_lmm: ethtool Link Mode Mask
+ *     @link_mode_mask: ethtool Link Mode Mask
  *
  *     Translate ethtool Link Mode Mask into a Firmware Port capabilities
  *     value.
index 7965552..d02d346 100644 (file)
@@ -165,6 +165,9 @@ static void set_nat_params(struct adapter *adap, struct filter_entry *f,
                           unsigned int tid, bool dip, bool sip, bool dp,
                           bool sp)
 {
+       u8 *nat_lp = (u8 *)&f->fs.nat_lport;
+       u8 *nat_fp = (u8 *)&f->fs.nat_fport;
+
        if (dip) {
                if (f->fs.type) {
                        set_tcb_field(adap, f, tid, TCB_SND_UNA_RAW_W,
@@ -236,8 +239,9 @@ static void set_nat_params(struct adapter *adap, struct filter_entry *f,
        }
 
        set_tcb_field(adap, f, tid, TCB_PDU_HDR_LEN_W, WORD_MASK,
-                     (dp ? f->fs.nat_lport : 0) |
-                     (sp ? f->fs.nat_fport << 16 : 0), 1);
+                     (dp ? (nat_lp[1] | nat_lp[0] << 8) : 0) |
+                     (sp ? (nat_fp[1] << 16 | nat_fp[0] << 24) : 0),
+                     1);
 }
 
 /* Validate filter spec against configuration done on the card. */
@@ -909,6 +913,9 @@ int set_filter_wr(struct adapter *adapter, int fidx)
        fwr->fpm = htons(f->fs.mask.fport);
 
        if (adapter->params.filter2_wr_support) {
+               u8 *nat_lp = (u8 *)&f->fs.nat_lport;
+               u8 *nat_fp = (u8 *)&f->fs.nat_fport;
+
                fwr->natmode_to_ulp_type =
                        FW_FILTER2_WR_ULP_TYPE_V(f->fs.nat_mode ?
                                                 ULP_MODE_TCPDDP :
@@ -916,8 +923,8 @@ int set_filter_wr(struct adapter *adapter, int fidx)
                        FW_FILTER2_WR_NATMODE_V(f->fs.nat_mode);
                memcpy(fwr->newlip, f->fs.nat_lip, sizeof(fwr->newlip));
                memcpy(fwr->newfip, f->fs.nat_fip, sizeof(fwr->newfip));
-               fwr->newlport = htons(f->fs.nat_lport);
-               fwr->newfport = htons(f->fs.nat_fport);
+               fwr->newlport = htons(nat_lp[1] | nat_lp[0] << 8);
+               fwr->newfport = htons(nat_fp[1] | nat_fp[0] << 8);
        }
 
        /* Mark the filter as "pending" and ship off the Filter Work Request.
@@ -1105,16 +1112,16 @@ static bool is_addr_all_mask(u8 *ipmask, int family)
                struct in_addr *addr;
 
                addr = (struct in_addr *)ipmask;
-               if (addr->s_addr == 0xffffffff)
+               if (addr->s_addr == htonl(0xffffffff))
                        return true;
        } else if (family == AF_INET6) {
                struct in6_addr *addr6;
 
                addr6 = (struct in6_addr *)ipmask;
-               if (addr6->s6_addr32[0] == 0xffffffff &&
-                   addr6->s6_addr32[1] == 0xffffffff &&
-                   addr6->s6_addr32[2] == 0xffffffff &&
-                   addr6->s6_addr32[3] == 0xffffffff)
+               if (addr6->s6_addr32[0] == htonl(0xffffffff) &&
+                   addr6->s6_addr32[1] == htonl(0xffffffff) &&
+                   addr6->s6_addr32[2] == htonl(0xffffffff) &&
+                   addr6->s6_addr32[3] == htonl(0xffffffff))
                        return true;
        }
        return false;
index 854b171..0329a6b 100644 (file)
@@ -449,7 +449,7 @@ static int set_rxmode(struct net_device *dev, int mtu, bool sleep_ok)
  *                or -1
  *     @addr: the new MAC address value
  *     @persist: whether a new MAC allocation should be persistent
- *     @add_smt: if true also add the address to the HW SMT
+ *     @smt_idx: the destination to store the new SMT index.
  *
  *     Modifies an MPS filter and sets it to the new MAC address if
  *     @tcam_idx >= 0, or adds the MAC address to a new filter if
@@ -1615,6 +1615,7 @@ static int tid_init(struct tid_info *t)
  *     @stid: the server TID
  *     @sip: local IP address to bind server to
  *     @sport: the server's TCP port
+ *     @vlan: the VLAN header information
  *     @queue: queue to direct messages from this server to
  *
  *     Create an IP server for the given port and address.
@@ -2609,7 +2610,7 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
 
        /* Clear out filter specifications */
        memset(&f->fs, 0, sizeof(struct ch_filter_specification));
-       f->fs.val.lport = cpu_to_be16(sport);
+       f->fs.val.lport = be16_to_cpu(sport);
        f->fs.mask.lport  = ~0;
        val = (u8 *)&sip;
        if ((val[0] | val[1] | val[2] | val[3]) != 0) {
@@ -5377,10 +5378,10 @@ static inline bool is_x_10g_port(const struct link_config *lc)
 static int cfg_queues(struct adapter *adap)
 {
        u32 avail_qsets, avail_eth_qsets, avail_uld_qsets;
-       u32 i, n10g = 0, qidx = 0, n1g = 0;
        u32 ncpus = num_online_cpus();
        u32 niqflint, neq, num_ulds;
        struct sge *s = &adap->sge;
+       u32 i, n10g = 0, qidx = 0;
        u32 q10g = 0, q1g;
 
        /* Reduce memory usage in kdump environment, disable all offload. */
@@ -5426,7 +5427,6 @@ static int cfg_queues(struct adapter *adap)
        if (n10g)
                q10g = (avail_eth_qsets - (adap->params.nports - n10g)) / n10g;
 
-       n1g = adap->params.nports - n10g;
 #ifdef CONFIG_CHELSIO_T4_DCB
        /* For Data Center Bridging support we need to be able to support up
         * to 8 Traffic Priorities; each of which will be assigned to its
@@ -5444,7 +5444,8 @@ static int cfg_queues(struct adapter *adap)
        else
                q10g = max(8U, q10g);
 
-       while ((q10g * n10g) > (avail_eth_qsets - n1g * q1g))
+       while ((q10g * n10g) >
+              (avail_eth_qsets - (adap->params.nports - n10g) * q1g))
                q10g--;
 
 #else /* !CONFIG_CHELSIO_T4_DCB */
index f5bc996..70dbee8 100644 (file)
@@ -194,6 +194,7 @@ int cxgb4_ptp_redirect_rx_packet(struct adapter *adapter, struct port_info *pi)
 }
 
 /**
+ * cxgb4_ptp_adjfreq - Adjust frequency of PHC cycle counter
  * @ptp: ptp clock structure
  * @ppb: Desired frequency change in parts per billion
  *
@@ -229,7 +230,7 @@ static int cxgb4_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
 
 /**
  * cxgb4_ptp_fineadjtime - Shift the time of the hardware clock
- * @ptp: ptp clock structure
+ * @adapter: board private structure
  * @delta: Desired change in nanoseconds
  *
  * Adjust the timer by resetting the timecounter structure.
index 4a5fa9e..59b65d4 100644 (file)
@@ -58,10 +58,6 @@ static struct ch_tc_pedit_fields pedits[] = {
        PEDIT_FIELDS(IP6_, DST_63_32, 4, nat_lip, 4),
        PEDIT_FIELDS(IP6_, DST_95_64, 4, nat_lip, 8),
        PEDIT_FIELDS(IP6_, DST_127_96, 4, nat_lip, 12),
-       PEDIT_FIELDS(TCP_, SPORT, 2, nat_fport, 0),
-       PEDIT_FIELDS(TCP_, DPORT, 2, nat_lport, 0),
-       PEDIT_FIELDS(UDP_, SPORT, 2, nat_fport, 0),
-       PEDIT_FIELDS(UDP_, DPORT, 2, nat_lport, 0),
 };
 
 static struct ch_tc_flower_entry *allocate_flower_entry(void)
@@ -156,14 +152,14 @@ static void cxgb4_process_flow_match(struct net_device *dev,
                struct flow_match_ports match;
 
                flow_rule_match_ports(rule, &match);
-               fs->val.lport = cpu_to_be16(match.key->dst);
-               fs->mask.lport = cpu_to_be16(match.mask->dst);
-               fs->val.fport = cpu_to_be16(match.key->src);
-               fs->mask.fport = cpu_to_be16(match.mask->src);
+               fs->val.lport = be16_to_cpu(match.key->dst);
+               fs->mask.lport = be16_to_cpu(match.mask->dst);
+               fs->val.fport = be16_to_cpu(match.key->src);
+               fs->mask.fport = be16_to_cpu(match.mask->src);
 
                /* also initialize nat_lport/fport to same values */
-               fs->nat_lport = cpu_to_be16(match.key->dst);
-               fs->nat_fport = cpu_to_be16(match.key->src);
+               fs->nat_lport = fs->val.lport;
+               fs->nat_fport = fs->val.fport;
        }
 
        if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
@@ -354,12 +350,9 @@ static void process_pedit_field(struct ch_filter_specification *fs, u32 val,
                switch (offset) {
                case PEDIT_TCP_SPORT_DPORT:
                        if (~mask & PEDIT_TCP_UDP_SPORT_MASK)
-                               offload_pedit(fs, cpu_to_be32(val) >> 16,
-                                             cpu_to_be32(mask) >> 16,
-                                             TCP_SPORT);
+                               fs->nat_fport = val;
                        else
-                               offload_pedit(fs, cpu_to_be32(val),
-                                             cpu_to_be32(mask), TCP_DPORT);
+                               fs->nat_lport = val >> 16;
                }
                fs->nat_mode = NAT_MODE_ALL;
                break;
@@ -367,12 +360,9 @@ static void process_pedit_field(struct ch_filter_specification *fs, u32 val,
                switch (offset) {
                case PEDIT_UDP_SPORT_DPORT:
                        if (~mask & PEDIT_TCP_UDP_SPORT_MASK)
-                               offload_pedit(fs, cpu_to_be32(val) >> 16,
-                                             cpu_to_be32(mask) >> 16,
-                                             UDP_SPORT);
+                               fs->nat_fport = val;
                        else
-                               offload_pedit(fs, cpu_to_be32(val),
-                                             cpu_to_be32(mask), UDP_DPORT);
+                               fs->nat_lport = val >> 16;
                }
                fs->nat_mode = NAT_MODE_ALL;
        }
index 3f3c11e..dede025 100644 (file)
@@ -48,7 +48,7 @@ static int fill_match_fields(struct adapter *adap,
                             bool next_header)
 {
        unsigned int i, j;
-       u32 val, mask;
+       __be32 val, mask;
        int off, err;
        bool found;
 
@@ -228,7 +228,7 @@ int cxgb4_config_knode(struct net_device *dev, struct tc_cls_u32_offload *cls)
                const struct cxgb4_next_header *next;
                bool found = false;
                unsigned int i, j;
-               u32 val, mask;
+               __be32 val, mask;
                int off;
 
                if (t->table[link_uhtid - 1].link_handle) {
@@ -242,10 +242,10 @@ int cxgb4_config_knode(struct net_device *dev, struct tc_cls_u32_offload *cls)
 
                /* Try to find matches that allow jumps to next header. */
                for (i = 0; next[i].jump; i++) {
-                       if (next[i].offoff != cls->knode.sel->offoff ||
-                           next[i].shift != cls->knode.sel->offshift ||
-                           next[i].mask != cls->knode.sel->offmask ||
-                           next[i].offset != cls->knode.sel->off)
+                       if (next[i].sel.offoff != cls->knode.sel->offoff ||
+                           next[i].sel.offshift != cls->knode.sel->offshift ||
+                           next[i].sel.offmask != cls->knode.sel->offmask ||
+                           next[i].sel.off != cls->knode.sel->off)
                                continue;
 
                        /* Found a possible candidate.  Find a key that
@@ -257,9 +257,9 @@ int cxgb4_config_knode(struct net_device *dev, struct tc_cls_u32_offload *cls)
                                val = cls->knode.sel->keys[j].val;
                                mask = cls->knode.sel->keys[j].mask;
 
-                               if (next[i].match_off == off &&
-                                   next[i].match_val == val &&
-                                   next[i].match_mask == mask) {
+                               if (next[i].key.off == off &&
+                                   next[i].key.val == val &&
+                                   next[i].key.mask == mask) {
                                        found = true;
                                        break;
                                }
index 125868c..f59dd4b 100644 (file)
 struct cxgb4_match_field {
        int off; /* Offset from the beginning of the header to match */
        /* Fill the value/mask pair in the spec if matched */
-       int (*val)(struct ch_filter_specification *f, u32 val, u32 mask);
+       int (*val)(struct ch_filter_specification *f, __be32 val, __be32 mask);
 };
 
 /* IPv4 match fields */
 static inline int cxgb4_fill_ipv4_tos(struct ch_filter_specification *f,
-                                     u32 val, u32 mask)
+                                     __be32 val, __be32 mask)
 {
        f->val.tos  = (ntohl(val)  >> 16) & 0x000000FF;
        f->mask.tos = (ntohl(mask) >> 16) & 0x000000FF;
@@ -52,7 +52,7 @@ static inline int cxgb4_fill_ipv4_tos(struct ch_filter_specification *f,
 }
 
 static inline int cxgb4_fill_ipv4_frag(struct ch_filter_specification *f,
-                                      u32 val, u32 mask)
+                                      __be32 val, __be32 mask)
 {
        u32 mask_val;
        u8 frag_val;
@@ -74,7 +74,7 @@ static inline int cxgb4_fill_ipv4_frag(struct ch_filter_specification *f,
 }
 
 static inline int cxgb4_fill_ipv4_proto(struct ch_filter_specification *f,
-                                       u32 val, u32 mask)
+                                       __be32 val, __be32 mask)
 {
        f->val.proto  = (ntohl(val)  >> 16) & 0x000000FF;
        f->mask.proto = (ntohl(mask) >> 16) & 0x000000FF;
@@ -83,7 +83,7 @@ static inline int cxgb4_fill_ipv4_proto(struct ch_filter_specification *f,
 }
 
 static inline int cxgb4_fill_ipv4_src_ip(struct ch_filter_specification *f,
-                                        u32 val, u32 mask)
+                                        __be32 val, __be32 mask)
 {
        memcpy(&f->val.fip[0],  &val,  sizeof(u32));
        memcpy(&f->mask.fip[0], &mask, sizeof(u32));
@@ -92,7 +92,7 @@ static inline int cxgb4_fill_ipv4_src_ip(struct ch_filter_specification *f,
 }
 
 static inline int cxgb4_fill_ipv4_dst_ip(struct ch_filter_specification *f,
-                                        u32 val, u32 mask)
+                                        __be32 val, __be32 mask)
 {
        memcpy(&f->val.lip[0],  &val,  sizeof(u32));
        memcpy(&f->mask.lip[0], &mask, sizeof(u32));
@@ -111,7 +111,7 @@ static const struct cxgb4_match_field cxgb4_ipv4_fields[] = {
 
 /* IPv6 match fields */
 static inline int cxgb4_fill_ipv6_tos(struct ch_filter_specification *f,
-                                     u32 val, u32 mask)
+                                     __be32 val, __be32 mask)
 {
        f->val.tos  = (ntohl(val)  >> 20) & 0x000000FF;
        f->mask.tos = (ntohl(mask) >> 20) & 0x000000FF;
@@ -120,7 +120,7 @@ static inline int cxgb4_fill_ipv6_tos(struct ch_filter_specification *f,
 }
 
 static inline int cxgb4_fill_ipv6_proto(struct ch_filter_specification *f,
-                                       u32 val, u32 mask)
+                                       __be32 val, __be32 mask)
 {
        f->val.proto  = (ntohl(val)  >> 8) & 0x000000FF;
        f->mask.proto = (ntohl(mask) >> 8) & 0x000000FF;
@@ -129,7 +129,7 @@ static inline int cxgb4_fill_ipv6_proto(struct ch_filter_specification *f,
 }
 
 static inline int cxgb4_fill_ipv6_src_ip0(struct ch_filter_specification *f,
-                                         u32 val, u32 mask)
+                                         __be32 val, __be32 mask)
 {
        memcpy(&f->val.fip[0],  &val,  sizeof(u32));
        memcpy(&f->mask.fip[0], &mask, sizeof(u32));
@@ -138,7 +138,7 @@ static inline int cxgb4_fill_ipv6_src_ip0(struct ch_filter_specification *f,
 }
 
 static inline int cxgb4_fill_ipv6_src_ip1(struct ch_filter_specification *f,
-                                         u32 val, u32 mask)
+                                         __be32 val, __be32 mask)
 {
        memcpy(&f->val.fip[4],  &val,  sizeof(u32));
        memcpy(&f->mask.fip[4], &mask, sizeof(u32));
@@ -147,7 +147,7 @@ static inline int cxgb4_fill_ipv6_src_ip1(struct ch_filter_specification *f,
 }
 
 static inline int cxgb4_fill_ipv6_src_ip2(struct ch_filter_specification *f,
-                                         u32 val, u32 mask)
+                                         __be32 val, __be32 mask)
 {
        memcpy(&f->val.fip[8],  &val,  sizeof(u32));
        memcpy(&f->mask.fip[8], &mask, sizeof(u32));
@@ -156,7 +156,7 @@ static inline int cxgb4_fill_ipv6_src_ip2(struct ch_filter_specification *f,
 }
 
 static inline int cxgb4_fill_ipv6_src_ip3(struct ch_filter_specification *f,
-                                         u32 val, u32 mask)
+                                         __be32 val, __be32 mask)
 {
        memcpy(&f->val.fip[12],  &val,  sizeof(u32));
        memcpy(&f->mask.fip[12], &mask, sizeof(u32));
@@ -165,7 +165,7 @@ static inline int cxgb4_fill_ipv6_src_ip3(struct ch_filter_specification *f,
 }
 
 static inline int cxgb4_fill_ipv6_dst_ip0(struct ch_filter_specification *f,
-                                         u32 val, u32 mask)
+                                         __be32 val, __be32 mask)
 {
        memcpy(&f->val.lip[0],  &val,  sizeof(u32));
        memcpy(&f->mask.lip[0], &mask, sizeof(u32));
@@ -174,7 +174,7 @@ static inline int cxgb4_fill_ipv6_dst_ip0(struct ch_filter_specification *f,
 }
 
 static inline int cxgb4_fill_ipv6_dst_ip1(struct ch_filter_specification *f,
-                                         u32 val, u32 mask)
+                                         __be32 val, __be32 mask)
 {
        memcpy(&f->val.lip[4],  &val,  sizeof(u32));
        memcpy(&f->mask.lip[4], &mask, sizeof(u32));
@@ -183,7 +183,7 @@ static inline int cxgb4_fill_ipv6_dst_ip1(struct ch_filter_specification *f,
 }
 
 static inline int cxgb4_fill_ipv6_dst_ip2(struct ch_filter_specification *f,
-                                         u32 val, u32 mask)
+                                         __be32 val, __be32 mask)
 {
        memcpy(&f->val.lip[8],  &val,  sizeof(u32));
        memcpy(&f->mask.lip[8], &mask, sizeof(u32));
@@ -192,7 +192,7 @@ static inline int cxgb4_fill_ipv6_dst_ip2(struct ch_filter_specification *f,
 }
 
 static inline int cxgb4_fill_ipv6_dst_ip3(struct ch_filter_specification *f,
-                                         u32 val, u32 mask)
+                                         __be32 val, __be32 mask)
 {
        memcpy(&f->val.lip[12],  &val,  sizeof(u32));
        memcpy(&f->mask.lip[12], &mask, sizeof(u32));
@@ -216,7 +216,7 @@ static const struct cxgb4_match_field cxgb4_ipv6_fields[] = {
 
 /* TCP/UDP match */
 static inline int cxgb4_fill_l4_ports(struct ch_filter_specification *f,
-                                     u32 val, u32 mask)
+                                     __be32 val, __be32 mask)
 {
        f->val.fport  = ntohl(val)  >> 16;
        f->mask.fport = ntohl(mask) >> 16;
@@ -237,19 +237,13 @@ static const struct cxgb4_match_field cxgb4_udp_fields[] = {
 };
 
 struct cxgb4_next_header {
-       unsigned int offset; /* Offset to next header */
-       /* offset, shift, and mask added to offset above
+       /* Offset, shift, and mask added to beginning of the header
         * to get to next header.  Useful when using a header
         * field's value to jump to next header such as IHL field
         * in IPv4 header.
         */
-       unsigned int offoff;
-       u32 shift;
-       u32 mask;
-       /* match criteria to make this jump */
-       unsigned int match_off;
-       u32 match_val;
-       u32 match_mask;
+       struct tc_u32_sel sel;
+       struct tc_u32_key key;
        /* location of jump to make */
        const struct cxgb4_match_field *jump;
 };
@@ -258,26 +252,74 @@ struct cxgb4_next_header {
  * IPv4 header.
  */
 static const struct cxgb4_next_header cxgb4_ipv4_jumps[] = {
-       { .offset = 0, .offoff = 0, .shift = 6, .mask = 0xF,
-         .match_off = 8, .match_val = 0x600, .match_mask = 0xFF00,
-         .jump = cxgb4_tcp_fields },
-       { .offset = 0, .offoff = 0, .shift = 6, .mask = 0xF,
-         .match_off = 8, .match_val = 0x1100, .match_mask = 0xFF00,
-         .jump = cxgb4_udp_fields },
-       { .jump = NULL }
+       {
+               /* TCP Jump */
+               .sel = {
+                       .off = 0,
+                       .offoff = 0,
+                       .offshift = 6,
+                       .offmask = cpu_to_be16(0x0f00),
+               },
+               .key = {
+                       .off = 8,
+                       .val = cpu_to_be32(0x00060000),
+                       .mask = cpu_to_be32(0x00ff0000),
+               },
+               .jump = cxgb4_tcp_fields,
+       },
+       {
+               /* UDP Jump */
+               .sel = {
+                       .off = 0,
+                       .offoff = 0,
+                       .offshift = 6,
+                       .offmask = cpu_to_be16(0x0f00),
+               },
+               .key = {
+                       .off = 8,
+                       .val = cpu_to_be32(0x00110000),
+                       .mask = cpu_to_be32(0x00ff0000),
+               },
+               .jump = cxgb4_udp_fields,
+       },
+       { .jump = NULL },
 };
 
 /* Accept a rule with a jump directly past the 40 Bytes of IPv6 fixed header
  * to get to transport layer header.
  */
 static const struct cxgb4_next_header cxgb4_ipv6_jumps[] = {
-       { .offset = 0x28, .offoff = 0, .shift = 0, .mask = 0,
-         .match_off = 4, .match_val = 0x60000, .match_mask = 0xFF0000,
-         .jump = cxgb4_tcp_fields },
-       { .offset = 0x28, .offoff = 0, .shift = 0, .mask = 0,
-         .match_off = 4, .match_val = 0x110000, .match_mask = 0xFF0000,
-         .jump = cxgb4_udp_fields },
-       { .jump = NULL }
+       {
+               /* TCP Jump */
+               .sel = {
+                       .off = 40,
+                       .offoff = 0,
+                       .offshift = 0,
+                       .offmask = 0,
+               },
+               .key = {
+                       .off = 4,
+                       .val = cpu_to_be32(0x00000600),
+                       .mask = cpu_to_be32(0x0000ff00),
+               },
+               .jump = cxgb4_tcp_fields,
+       },
+       {
+               /* UDP Jump */
+               .sel = {
+                       .off = 40,
+                       .offoff = 0,
+                       .offshift = 0,
+                       .offmask = 0,
+               },
+               .key = {
+                       .off = 4,
+                       .val = cpu_to_be32(0x00001100),
+                       .mask = cpu_to_be32(0x0000ff00),
+               },
+               .jump = cxgb4_udp_fields,
+       },
+       { .jump = NULL },
 };
 
 struct cxgb4_link {
index 72b37a6..c486412 100644 (file)
@@ -502,41 +502,20 @@ u64 cxgb4_select_ntuple(struct net_device *dev,
 }
 EXPORT_SYMBOL(cxgb4_select_ntuple);
 
-/*
- * Called when address resolution fails for an L2T entry to handle packets
- * on the arpq head.  If a packet specifies a failure handler it is invoked,
- * otherwise the packet is sent to the device.
- */
-static void handle_failed_resolution(struct adapter *adap, struct l2t_entry *e)
-{
-       struct sk_buff *skb;
-
-       while ((skb = __skb_dequeue(&e->arpq)) != NULL) {
-               const struct l2t_skb_cb *cb = L2T_SKB_CB(skb);
-
-               spin_unlock(&e->lock);
-               if (cb->arp_err_handler)
-                       cb->arp_err_handler(cb->handle, skb);
-               else
-                       t4_ofld_send(adap, skb);
-               spin_lock(&e->lock);
-       }
-}
-
 /*
  * Called when the host's neighbor layer makes a change to some entry that is
  * loaded into the HW L2 table.
  */
 void t4_l2t_update(struct adapter *adap, struct neighbour *neigh)
 {
-       struct l2t_entry *e;
-       struct sk_buff_head *arpq = NULL;
-       struct l2t_data *d = adap->l2t;
        unsigned int addr_len = neigh->tbl->key_len;
        u32 *addr = (u32 *) neigh->primary_key;
-       int ifidx = neigh->dev->ifindex;
-       int hash = addr_hash(d, addr, addr_len, ifidx);
+       int hash, ifidx = neigh->dev->ifindex;
+       struct sk_buff_head *arpq = NULL;
+       struct l2t_data *d = adap->l2t;
+       struct l2t_entry *e;
 
+       hash = addr_hash(d, addr, addr_len, ifidx);
        read_lock_bh(&d->lock);
        for (e = d->l2tab[hash].first; e; e = e->next)
                if (!addreq(e, addr) && e->ifindex == ifidx) {
@@ -569,8 +548,25 @@ void t4_l2t_update(struct adapter *adap, struct neighbour *neigh)
                        write_l2e(adap, e, 0);
        }
 
-       if (arpq)
-               handle_failed_resolution(adap, e);
+       if (arpq) {
+               struct sk_buff *skb;
+
+               /* Called when address resolution fails for an L2T
+                * entry to handle packets on the arpq head. If a
+                * packet specifies a failure handler it is invoked,
+                * otherwise the packet is sent to the device.
+                */
+               while ((skb = __skb_dequeue(&e->arpq)) != NULL) {
+                       const struct l2t_skb_cb *cb = L2T_SKB_CB(skb);
+
+                       spin_unlock(&e->lock);
+                       if (cb->arp_err_handler)
+                               cb->arp_err_handler(cb->handle, skb);
+                       else
+                               t4_ofld_send(adap, skb);
+                       spin_lock(&e->lock);
+               }
+       }
        spin_unlock_bh(&e->lock);
 }
 
@@ -613,6 +609,7 @@ struct l2t_entry *t4_l2t_alloc_switching(struct adapter *adap, u16 vlan,
 }
 
 /**
+ * cxgb4_l2t_alloc_switching - Allocates an L2T entry for switch filters
  * @dev: net_device pointer
  * @vlan: VLAN Id
  * @port: Associated port
index fde93c5..a1b1446 100644 (file)
@@ -598,7 +598,7 @@ struct sched_class *cxgb4_sched_class_alloc(struct net_device *dev,
 /**
  * cxgb4_sched_class_free - free a scheduling class
  * @dev: net_device pointer
- * @e: scheduling class
+ * @classid: scheduling class id to free
  *
  * Frees a scheduling class if there are no users.
  */
index 1359158..92eee66 100644 (file)
@@ -302,7 +302,7 @@ static void deferred_unmap_destructor(struct sk_buff *skb)
 
 /**
  *     free_tx_desc - reclaims Tx descriptors and their buffers
- *     @adapter: the adapter
+ *     @adap: the adapter
  *     @q: the Tx queue to reclaim descriptors from
  *     @n: the number of descriptors to reclaim
  *     @unmap: whether the buffers should be unmapped for DMA
@@ -722,6 +722,7 @@ static inline unsigned int flits_to_desc(unsigned int n)
 /**
  *     is_eth_imm - can an Ethernet packet be sent as immediate data?
  *     @skb: the packet
+ *     @chip_ver: chip version
  *
  *     Returns whether an Ethernet packet is small enough to fit as
  *     immediate data. Return value corresponds to headroom required.
@@ -749,6 +750,7 @@ static inline int is_eth_imm(const struct sk_buff *skb, unsigned int chip_ver)
 /**
  *     calc_tx_flits - calculate the number of flits for a packet Tx WR
  *     @skb: the packet
+ *     @chip_ver: chip version
  *
  *     Returns the number of flits needed for a Tx WR for the given Ethernet
  *     packet, including the needed WR and CPL headers.
@@ -804,6 +806,7 @@ static inline unsigned int calc_tx_flits(const struct sk_buff *skb,
 /**
  *     calc_tx_descs - calculate the number of Tx descriptors for a packet
  *     @skb: the packet
+ *     @chip_ver: chip version
  *
  *     Returns the number of Tx descriptors needed for the given Ethernet
  *     packet, including the needed WR and CPL headers.
@@ -1425,12 +1428,10 @@ static netdev_tx_t cxgb4_eth_xmit(struct sk_buff *skb, struct net_device *dev)
 
        qidx = skb_get_queue_mapping(skb);
        if (ptp_enabled) {
-               spin_lock(&adap->ptp_lock);
                if (!(adap->ptp_tx_skb)) {
                        skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
                        adap->ptp_tx_skb = skb_get(skb);
                } else {
-                       spin_unlock(&adap->ptp_lock);
                        goto out_free;
                }
                q = &adap->sge.ptptxq;
@@ -1444,11 +1445,8 @@ static netdev_tx_t cxgb4_eth_xmit(struct sk_buff *skb, struct net_device *dev)
 
 #ifdef CONFIG_CHELSIO_T4_FCOE
        ret = cxgb_fcoe_offload(skb, adap, pi, &cntrl);
-       if (unlikely(ret == -ENOTSUPP)) {
-               if (ptp_enabled)
-                       spin_unlock(&adap->ptp_lock);
+       if (unlikely(ret == -EOPNOTSUPP))
                goto out_free;
-       }
 #endif /* CONFIG_CHELSIO_T4_FCOE */
 
        chip_ver = CHELSIO_CHIP_VERSION(adap->params.chip);
@@ -1461,8 +1459,6 @@ static netdev_tx_t cxgb4_eth_xmit(struct sk_buff *skb, struct net_device *dev)
                dev_err(adap->pdev_dev,
                        "%s: Tx ring %u full while queue awake!\n",
                        dev->name, qidx);
-               if (ptp_enabled)
-                       spin_unlock(&adap->ptp_lock);
                return NETDEV_TX_BUSY;
        }
 
@@ -1481,8 +1477,6 @@ static netdev_tx_t cxgb4_eth_xmit(struct sk_buff *skb, struct net_device *dev)
            unlikely(cxgb4_map_skb(adap->pdev_dev, skb, sgl_sdesc->addr) < 0)) {
                memset(sgl_sdesc->addr, 0, sizeof(sgl_sdesc->addr));
                q->mapping_err++;
-               if (ptp_enabled)
-                       spin_unlock(&adap->ptp_lock);
                goto out_free;
        }
 
@@ -1533,8 +1527,7 @@ static netdev_tx_t cxgb4_eth_xmit(struct sk_buff *skb, struct net_device *dev)
                        if (iph->version == 4) {
                                iph->check = 0;
                                iph->tot_len = 0;
-                               iph->check = (u16)(~ip_fast_csum((u8 *)iph,
-                                                                iph->ihl));
+                               iph->check = ~ip_fast_csum((u8 *)iph, iph->ihl);
                        }
                        if (skb->ip_summed == CHECKSUM_PARTIAL)
                                cntrl = hwcsum(adap->params.chip, skb);
@@ -1630,8 +1623,6 @@ static netdev_tx_t cxgb4_eth_xmit(struct sk_buff *skb, struct net_device *dev)
        txq_advance(&q->q, ndesc);
 
        cxgb4_ring_tx_db(adap, &q->q, ndesc);
-       if (ptp_enabled)
-               spin_unlock(&adap->ptp_lock);
        return NETDEV_TX_OK;
 
 out_free:
@@ -2377,6 +2368,16 @@ netdev_tx_t t4_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if (unlikely(qid >= pi->nqsets))
                return cxgb4_ethofld_xmit(skb, dev);
 
+       if (is_ptp_enabled(skb, dev)) {
+               struct adapter *adap = netdev2adap(dev);
+               netdev_tx_t ret;
+
+               spin_lock(&adap->ptp_lock);
+               ret = cxgb4_eth_xmit(skb, dev);
+               spin_unlock(&adap->ptp_lock);
+               return ret;
+       }
+
        return cxgb4_eth_xmit(skb, dev);
 }
 
@@ -2410,9 +2411,9 @@ static void eosw_txq_flush_pending_skbs(struct sge_eosw_txq *eosw_txq)
 
 /**
  * cxgb4_ethofld_send_flowc - Send ETHOFLD flowc request to bind eotid to tc.
- * @dev - netdevice
- * @eotid - ETHOFLD tid to bind/unbind
- * @tc - traffic class. If set to FW_SCHED_CLS_NONE, then unbinds the @eotid
+ * @dev: netdevice
+ * @eotid: ETHOFLD tid to bind/unbind
+ * @tc: traffic class. If set to FW_SCHED_CLS_NONE, then unbinds the @eotid
  *
  * Send a FLOWC work request to bind an ETHOFLD TID to a traffic class.
  * If @tc is set to FW_SCHED_CLS_NONE, then the @eotid is unbound from
@@ -2691,7 +2692,6 @@ static inline unsigned int calc_tx_flits_ofld(const struct sk_buff *skb)
 
 /**
  *     txq_stop_maperr - stop a Tx queue due to I/O MMU exhaustion
- *     @adap: the adapter
  *     @q: the queue to stop
  *
  *     Mark a Tx queue stopped due to I/O MMU exhaustion and resulting
@@ -2938,6 +2938,7 @@ static inline int uld_send(struct adapter *adap, struct sk_buff *skb,
        txq_info = adap->sge.uld_txq_info[tx_uld_type];
        if (unlikely(!txq_info)) {
                WARN_ON(true);
+               kfree_skb(skb);
                return NET_XMIT_DROP;
        }
 
@@ -3286,7 +3287,7 @@ enum {
 
 /**
  *     t4_systim_to_hwstamp - read hardware time stamp
- *     @adap: the adapter
+ *     @adapter: the adapter
  *     @skb: the packet
  *
  *     Read Time Stamp from MPS packet and insert in skb which
@@ -3313,15 +3314,16 @@ static noinline int t4_systim_to_hwstamp(struct adapter *adapter,
 
        hwtstamps = skb_hwtstamps(skb);
        memset(hwtstamps, 0, sizeof(*hwtstamps));
-       hwtstamps->hwtstamp = ns_to_ktime(be64_to_cpu(*((u64 *)data)));
+       hwtstamps->hwtstamp = ns_to_ktime(get_unaligned_be64(data));
 
        return RX_PTP_PKT_SUC;
 }
 
 /**
  *     t4_rx_hststamp - Recv PTP Event Message
- *     @adap: the adapter
+ *     @adapter: the adapter
  *     @rsp: the response queue descriptor holding the RX_PKT message
+ *     @rxq: the response queue holding the RX_PKT message
  *     @skb: the packet
  *
  *     PTP enabled and MPS packet, read HW timestamp
@@ -3345,7 +3347,7 @@ static int t4_rx_hststamp(struct adapter *adapter, const __be64 *rsp,
 
 /**
  *      t4_tx_hststamp - Loopback PTP Transmit Event Message
- *      @adap: the adapter
+ *      @adapter: the adapter
  *      @skb: the packet
  *      @dev: the ingress net device
  *
index 01c65d1..cbe72ed 100644 (file)
@@ -103,6 +103,7 @@ static void t4_smte_free(struct smt_entry *e)
 }
 
 /**
+ * cxgb4_smt_release - Release SMT entry
  * @e: smt entry to release
  *
  * Releases ref count and frees up an smt entry from SMT table
@@ -231,6 +232,7 @@ static struct smt_entry *t4_smt_alloc_switching(struct adapter *adap, u16 pfvf,
 }
 
 /**
+ * cxgb4_smt_alloc_switching - Allocates an SMT entry for switch filters.
  * @dev: net_device pointer
  * @smac: MAC address to add to SMT
  * Returns pointer to the SMT entry created
index 1c8068c..ad522f8 100644 (file)
@@ -3163,7 +3163,7 @@ int t4_get_tp_version(struct adapter *adapter, u32 *vers)
 
 /**
  *     t4_get_exprom_version - return the Expansion ROM version (if any)
- *     @adapter: the adapter
+ *     @adap: the adapter
  *     @vers: where to place the version
  *
  *     Reads the Expansion ROM header from FLASH and returns the version
@@ -3493,7 +3493,7 @@ int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
        drv_fw = &fw_info->fw_hdr;
 
        /* Read the header of the firmware on the card */
-       ret = -t4_read_flash(adap, FLASH_FW_START,
+       ret = t4_read_flash(adap, FLASH_FW_START,
                            sizeof(*card_fw) / sizeof(uint32_t),
                            (uint32_t *)card_fw, 1);
        if (ret == 0) {
@@ -3522,8 +3522,8 @@ int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
                   should_install_fs_fw(adap, card_fw_usable,
                                        be32_to_cpu(fs_fw->fw_ver),
                                        be32_to_cpu(card_fw->fw_ver))) {
-               ret = -t4_fw_upgrade(adap, adap->mbox, fw_data,
-                                    fw_size, 0);
+               ret = t4_fw_upgrade(adap, adap->mbox, fw_data,
+                                   fw_size, 0);
                if (ret != 0) {
                        dev_err(adap->pdev_dev,
                                "failed to install firmware: %d\n", ret);
@@ -3554,7 +3554,7 @@ int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
                        FW_HDR_FW_VER_MICRO_G(c), FW_HDR_FW_VER_BUILD_G(c),
                        FW_HDR_FW_VER_MAJOR_G(k), FW_HDR_FW_VER_MINOR_G(k),
                        FW_HDR_FW_VER_MICRO_G(k), FW_HDR_FW_VER_BUILD_G(k));
-               ret = EINVAL;
+               ret = -EINVAL;
                goto bye;
        }
 
@@ -5310,7 +5310,7 @@ static unsigned int t4_use_ldst(struct adapter *adap)
  * @cmd: TP fw ldst address space type
  * @vals: where the indirect register values are stored/written
  * @nregs: how many indirect registers to read/write
- * @start_idx: index of first indirect register to read/write
+ * @start_index: index of first indirect register to read/write
  * @rw: Read (1) or Write (0)
  * @sleep_ok: if true we may sleep while awaiting command completion
  *
@@ -6115,7 +6115,7 @@ void t4_pmrx_get_stats(struct adapter *adap, u32 cnt[], u64 cycles[])
 
 /**
  *     compute_mps_bg_map - compute the MPS Buffer Group Map for a Port
- *     @adap: the adapter
+ *     @adapter: the adapter
  *     @pidx: the port index
  *
  *     Computes and returns a bitmap indicating which MPS buffer groups are
@@ -6252,7 +6252,7 @@ static unsigned int t4_get_tp_e2c_map(struct adapter *adapter, int pidx)
 
 /**
  *     t4_get_tp_ch_map - return TP ingress channels associated with a port
- *     @adapter: the adapter
+ *     @adap: the adapter
  *     @pidx: the port index
  *
  *     Returns a bitmap indicating which TP Ingress Channels are associated
@@ -6589,7 +6589,7 @@ int t4_mdio_rd(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
  *     @phy_addr: the PHY address
  *     @mmd: the PHY MMD to access (0 for clause 22 PHYs)
  *     @reg: the register to write
- *     @valp: value to write
+ *     @val: value to write
  *
  *     Issues a FW command through the given mailbox to write a PHY register.
  */
@@ -6615,7 +6615,7 @@ int t4_mdio_wr(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
 
 /**
  *     t4_sge_decode_idma_state - decode the idma state
- *     @adap: the adapter
+ *     @adapter: the adapter
  *     @state: the state idma is stuck in
  */
 void t4_sge_decode_idma_state(struct adapter *adapter, int state)
@@ -6782,7 +6782,7 @@ void t4_sge_decode_idma_state(struct adapter *adapter, int state)
  *      t4_sge_ctxt_flush - flush the SGE context cache
  *      @adap: the adapter
  *      @mbox: mailbox to use for the FW command
- *      @ctx_type: Egress or Ingress
+ *      @ctxt_type: Egress or Ingress
  *
  *      Issues a FW command through the given mailbox to flush the
  *      SGE context cache.
@@ -6809,7 +6809,7 @@ int t4_sge_ctxt_flush(struct adapter *adap, unsigned int mbox, int ctxt_type)
 
 /**
  *     t4_read_sge_dbqtimers - read SGE Doorbell Queue Timer values
- *     @adap - the adapter
+ *     @adap: the adapter
  *     @ndbqtimers: size of the provided SGE Doorbell Queue Timer table
  *     @dbqtimers: SGE Doorbell Queue Timer table
  *
@@ -7092,6 +7092,7 @@ static int t4_fw_halt(struct adapter *adap, unsigned int mbox, int force)
 /**
  *     t4_fw_restart - restart the firmware by taking the uP out of RESET
  *     @adap: the adapter
+ *     @mbox: mailbox to use for the FW command
  *     @reset: if we want to do a RESET to restart things
  *
  *     Restart firmware previously halted by t4_fw_halt().  On successful
@@ -7630,6 +7631,8 @@ int t4_cfg_pfvf(struct adapter *adap, unsigned int mbox, unsigned int pf,
  *     @nmac: number of MAC addresses needed (1 to 5)
  *     @mac: the MAC addresses of the VI
  *     @rss_size: size of RSS table slice associated with this VI
+ *     @vivld: the destination to store the VI Valid value.
+ *     @vin: the destination to store the VIN value.
  *
  *     Allocates a virtual interface for the given physical port.  If @mac is
  *     not %NULL it contains the MAC addresses of the VI as assigned by FW.
@@ -7848,7 +7851,7 @@ int t4_free_raw_mac_filt(struct adapter *adap, unsigned int viid,
  *      t4_alloc_encap_mac_filt - Adds a mac entry in mps tcam with VNI support
  *      @adap: the adapter
  *      @viid: the VI id
- *      @mac: the MAC address
+ *      @addr: the MAC address
  *      @mask: the mask
  *      @vni: the VNI id for the tunnel protocol
  *      @vni_mask: mask for the VNI id
@@ -7897,11 +7900,11 @@ int t4_alloc_encap_mac_filt(struct adapter *adap, unsigned int viid,
  *     t4_alloc_raw_mac_filt - Adds a mac entry in mps tcam
  *     @adap: the adapter
  *     @viid: the VI id
- *     @mac: the MAC address
+ *     @addr: the MAC address
  *     @mask: the mask
  *     @idx: index at which to add this entry
- *     @port_id: the port index
  *     @lookup_type: MAC address for inner (1) or outer (0) header
+ *     @port_id: the port index
  *     @sleep_ok: call is allowed to sleep
  *
  *     Adds the mac entry at the specified index using raw mac interface.
@@ -8126,7 +8129,7 @@ int t4_free_mac_filt(struct adapter *adap, unsigned int mbox,
  *     @idx: index of existing filter for old value of MAC address, or -1
  *     @addr: the new MAC address value
  *     @persist: whether a new MAC allocation should be persistent
- *     @add_smt: if true also add the address to the HW SMT
+ *     @smt_idx: the destination to store the new SMT index.
  *
  *     Modifies an exact-match filter and sets it to the new MAC address.
  *     Note that in general it is not possible to modify the value of a given
@@ -8448,7 +8451,6 @@ int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
 
 /**
  *     t4_link_down_rc_str - return a string for a Link Down Reason Code
- *     @adap: the adapter
  *     @link_down_rc: Link Down Reason Code
  *
  *     Returns a string representation of the Link Down Reason Code.
@@ -8472,9 +8474,7 @@ static const char *t4_link_down_rc_str(unsigned char link_down_rc)
        return reason[link_down_rc];
 }
 
-/**
- * Return the highest speed set in the port capabilities, in Mb/s.
- */
+/* Return the highest speed set in the port capabilities, in Mb/s. */
 static unsigned int fwcap_to_speed(fw_port_cap32_t caps)
 {
        #define TEST_SPEED_RETURN(__caps_speed, __speed) \
@@ -9110,7 +9110,6 @@ found:
 /**
  *     t4_prep_adapter - prepare SW and HW for operation
  *     @adapter: the adapter
- *     @reset: if true perform a HW reset
  *
  *     Initialize adapter SW state for the various HW modules, set initial
  *     values for some adapter tunables, take PHYs out of reset, and
@@ -10395,6 +10394,7 @@ int t4_sched_params(struct adapter *adapter, u8 type, u8 level, u8 mode,
 /**
  *     t4_i2c_rd - read I2C data from adapter
  *     @adap: the adapter
+ *     @mbox: mailbox to use for the FW command
  *     @port: Port number if per-port device; <0 if not
  *     @devid: per-port device ID or absolute device ID
  *     @offset: byte offset into device I2C space
@@ -10450,7 +10450,7 @@ int t4_i2c_rd(struct adapter *adap, unsigned int mbox, int port,
 
 /**
  *      t4_set_vlan_acl - Set a VLAN id for the specified VF
- *      @adapter: the adapter
+ *      @adap: the adapter
  *      @mbox: mailbox to use for the FW command
  *      @vf: one of the VFs instantiated by the specified PF
  *      @vlan: The vlanid to be set
index cec865a..a7641be 100644 (file)
@@ -260,8 +260,7 @@ static int cxgb4vf_set_addr_hash(struct port_info *pi)
  *     @tcam_idx: TCAM index of existing filter for old value of MAC address,
  *                or -1
  *     @addr: the new MAC address value
- *     @persist: whether a new MAC allocation should be persistent
- *     @add_smt: if true also add the address to the HW SMT
+ *     @persistent: whether a new MAC allocation should be persistent
  *
  *     Modifies an MPS filter and sets it to the new MAC address if
  *     @tcam_idx >= 0, or adds the MAC address to a new filter if
index f71c973..8c3d6e1 100644 (file)
@@ -1692,7 +1692,7 @@ static inline bool is_new_response(const struct rsp_ctrl *rc,
  *     restore_rx_bufs - put back a packet's RX buffers
  *     @gl: the packet gather list
  *     @fl: the SGE Free List
- *     @nfrags: how many fragments in @si
+ *     @frags: how many fragments in @si
  *
  *     Called when we find out that the current packet, @si, can't be
  *     processed right away for some reason.  This is a very rare event and
@@ -2054,7 +2054,7 @@ irq_handler_t t4vf_intr_handler(struct adapter *adapter)
 
 /**
  *     sge_rx_timer_cb - perform periodic maintenance of SGE RX queues
- *     @data: the adapter
+ *     @t: Rx timer
  *
  *     Runs periodically from a timer to perform maintenance of SGE RX queues.
  *
@@ -2113,7 +2113,7 @@ static void sge_rx_timer_cb(struct timer_list *t)
 
 /**
  *     sge_tx_timer_cb - perform periodic maintenance of SGE Tx queues
- *     @data: the adapter
+ *     @t: Tx timer
  *
  *     Runs periodically from a timer to perform maintenance of SGE TX queues.
  *
@@ -2405,6 +2405,7 @@ err:
  *     t4vf_sge_alloc_eth_txq - allocate an SGE Ethernet TX Queue
  *     @adapter: the adapter
  *     @txq: pointer to the new txq to be filled in
+ *     @dev: the network device
  *     @devq: the network TX queue associated with the new txq
  *     @iqid: the relative ingress queue ID to which events relating to
  *             the new txq should be directed
index 9d49ff2..a31b873 100644 (file)
@@ -389,9 +389,7 @@ static inline enum cc_fec fwcap_to_cc_fec(fw_port_cap32_t fw_fec)
        return cc_fec;
 }
 
-/**
- * Return the highest speed set in the port capabilities, in Mb/s.
- */
+/* Return the highest speed set in the port capabilities, in Mb/s. */
 static unsigned int fwcap_to_speed(fw_port_cap32_t caps)
 {
        #define TEST_SPEED_RETURN(__caps_speed, __speed) \
@@ -1467,6 +1465,7 @@ int t4vf_identify_port(struct adapter *adapter, unsigned int viid,
  *     @bcast: 1 to enable broadcast Rx, 0 to disable it, -1 no change
  *     @vlanex: 1 to enable hardware VLAN Tag extraction, 0 to disable it,
  *             -1 no change
+ *     @sleep_ok: call is allowed to sleep
  *
  *     Sets Rx properties of a virtual interface.
  */
@@ -1906,7 +1905,7 @@ static const char *t4vf_link_down_rc_str(unsigned char link_down_rc)
 /**
  *     t4vf_handle_get_port_info - process a FW reply message
  *     @pi: the port info
- *     @rpl: start of the FW message
+ *     @cmd: start of the FW message
  *
  *     Processes a GET_PORT_INFO FW reply message.
  */
@@ -2137,8 +2136,6 @@ int t4vf_handle_fw_rpl(struct adapter *adapter, const __be64 *rpl)
        return 0;
 }
 
-/**
- */
 int t4vf_prep_adapter(struct adapter *adapter)
 {
        int err;
index 2972244..43570f4 100644 (file)
@@ -2938,7 +2938,7 @@ static int dpaa_eth_probe(struct platform_device *pdev)
                                                   DMA_BIT_MASK(40));
        if (err) {
                netdev_err(net_dev, "dma_coerce_mask_and_coherent() failed\n");
-               return err;
+               goto free_netdev;
        }
 
        /* If fsl_fm_max_frm is set to a higher value than the all-common 1500,
index f150cd4..0998ceb 100644 (file)
@@ -3632,7 +3632,7 @@ static int dpaa2_eth_connect_mac(struct dpaa2_eth_priv *priv)
 
        dpni_dev = to_fsl_mc_device(priv->net_dev->dev.parent);
        dpmac_dev = fsl_mc_get_endpoint(dpni_dev);
-       if (IS_ERR(dpmac_dev) || dpmac_dev->dev.type != &fsl_mc_bus_dpmac_type)
+       if (IS_ERR_OR_NULL(dpmac_dev) || dpmac_dev->dev.type != &fsl_mc_bus_dpmac_type)
                return 0;
 
        if (dpaa2_mac_is_type_fixed(dpmac_dev, priv->mc_io))
index 298c557..22105d0 100644 (file)
@@ -266,7 +266,7 @@ static irqreturn_t enetc_msix(int irq, void *data)
        /* disable interrupts */
        enetc_wr_reg(v->rbier, 0);
 
-       for_each_set_bit(i, &v->tx_rings_map, v->count_tx_rings)
+       for_each_set_bit(i, &v->tx_rings_map, ENETC_MAX_NUM_TXQS)
                enetc_wr_reg(v->tbier_base + ENETC_BDR_OFF(i), 0);
 
        napi_schedule_irqoff(&v->napi);
@@ -302,7 +302,7 @@ static int enetc_poll(struct napi_struct *napi, int budget)
        /* enable interrupts */
        enetc_wr_reg(v->rbier, ENETC_RBIER_RXTIE);
 
-       for_each_set_bit(i, &v->tx_rings_map, v->count_tx_rings)
+       for_each_set_bit(i, &v->tx_rings_map, ENETC_MAX_NUM_TXQS)
                enetc_wr_reg(v->tbier_base + ENETC_BDR_OFF(i),
                             ENETC_TBIER_TXTIE);
 
@@ -1595,6 +1595,24 @@ static int enetc_set_psfp(struct net_device *ndev, int en)
        return 0;
 }
 
+static void enetc_enable_rxvlan(struct net_device *ndev, bool en)
+{
+       struct enetc_ndev_priv *priv = netdev_priv(ndev);
+       int i;
+
+       for (i = 0; i < priv->num_rx_rings; i++)
+               enetc_bdr_enable_rxvlan(&priv->si->hw, i, en);
+}
+
+static void enetc_enable_txvlan(struct net_device *ndev, bool en)
+{
+       struct enetc_ndev_priv *priv = netdev_priv(ndev);
+       int i;
+
+       for (i = 0; i < priv->num_tx_rings; i++)
+               enetc_bdr_enable_txvlan(&priv->si->hw, i, en);
+}
+
 int enetc_set_features(struct net_device *ndev,
                       netdev_features_t features)
 {
@@ -1604,6 +1622,14 @@ int enetc_set_features(struct net_device *ndev,
        if (changed & NETIF_F_RXHASH)
                enetc_set_rss(ndev, !!(features & NETIF_F_RXHASH));
 
+       if (changed & NETIF_F_HW_VLAN_CTAG_RX)
+               enetc_enable_rxvlan(ndev,
+                                   !!(features & NETIF_F_HW_VLAN_CTAG_RX));
+
+       if (changed & NETIF_F_HW_VLAN_CTAG_TX)
+               enetc_enable_txvlan(ndev,
+                                   !!(features & NETIF_F_HW_VLAN_CTAG_TX));
+
        if (changed & NETIF_F_HW_TC)
                err = enetc_set_psfp(ndev, !!(features & NETIF_F_HW_TC));
 
index 6314051..ce0d321 100644 (file)
@@ -531,22 +531,22 @@ struct enetc_msg_cmd_header {
 
 /* Common H/W utility functions */
 
-static inline void enetc_enable_rxvlan(struct enetc_hw *hw, int si_idx,
-                                      bool en)
+static inline void enetc_bdr_enable_rxvlan(struct enetc_hw *hw, int idx,
+                                          bool en)
 {
-       u32 val = enetc_rxbdr_rd(hw, si_idx, ENETC_RBMR);
+       u32 val = enetc_rxbdr_rd(hw, idx, ENETC_RBMR);
 
        val = (val & ~ENETC_RBMR_VTE) | (en ? ENETC_RBMR_VTE : 0);
-       enetc_rxbdr_wr(hw, si_idx, ENETC_RBMR, val);
+       enetc_rxbdr_wr(hw, idx, ENETC_RBMR, val);
 }
 
-static inline void enetc_enable_txvlan(struct enetc_hw *hw, int si_idx,
-                                      bool en)
+static inline void enetc_bdr_enable_txvlan(struct enetc_hw *hw, int idx,
+                                          bool en)
 {
-       u32 val = enetc_txbdr_rd(hw, si_idx, ENETC_TBMR);
+       u32 val = enetc_txbdr_rd(hw, idx, ENETC_TBMR);
 
        val = (val & ~ENETC_TBMR_VIH) | (en ? ENETC_TBMR_VIH : 0);
-       enetc_txbdr_wr(hw, si_idx, ENETC_TBMR, val);
+       enetc_txbdr_wr(hw, idx, ENETC_TBMR, val);
 }
 
 static inline void enetc_set_bdr_prio(struct enetc_hw *hw, int bdr_idx,
index 824d211..7a9675b 100644 (file)
@@ -649,14 +649,6 @@ static int enetc_pf_set_features(struct net_device *ndev,
        netdev_features_t changed = ndev->features ^ features;
        struct enetc_ndev_priv *priv = netdev_priv(ndev);
 
-       if (changed & NETIF_F_HW_VLAN_CTAG_RX)
-               enetc_enable_rxvlan(&priv->si->hw, 0,
-                                   !!(features & NETIF_F_HW_VLAN_CTAG_RX));
-
-       if (changed & NETIF_F_HW_VLAN_CTAG_TX)
-               enetc_enable_txvlan(&priv->si->hw, 0,
-                                   !!(features & NETIF_F_HW_VLAN_CTAG_TX));
-
        if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
                struct enetc_pf *pf = enetc_si_priv(priv->si);
 
@@ -914,6 +906,7 @@ static int enetc_pf_probe(struct pci_dev *pdev,
        return 0;
 
 err_reg_netdev:
+       enetc_mdio_remove(pf);
        enetc_of_put_phy(priv);
        enetc_free_msix(priv);
 err_alloc_msix:
index a6cdd5b..832a217 100644 (file)
@@ -525,11 +525,6 @@ struct fec_enet_private {
        unsigned int total_tx_ring_size;
        unsigned int total_rx_ring_size;
 
-       unsigned long work_tx;
-       unsigned long work_rx;
-       unsigned long work_ts;
-       unsigned long work_mdio;
-
        struct  platform_device *pdev;
 
        int     dev_id;
@@ -595,6 +590,7 @@ struct fec_enet_private {
 void fec_ptp_init(struct platform_device *pdev, int irq_idx);
 void fec_ptp_stop(struct platform_device *pdev);
 void fec_ptp_start_cyclecounter(struct net_device *ndev);
+void fec_ptp_disable_hwts(struct net_device *ndev);
 int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr);
 int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr);
 
index 2d0d313..cc7fbfc 100644 (file)
@@ -75,8 +75,6 @@ static void fec_enet_itr_coal_init(struct net_device *ndev);
 
 #define DRIVER_NAME    "fec"
 
-#define FEC_ENET_GET_QUQUE(_x) ((_x == 0) ? 1 : ((_x == 1) ? 2 : 0))
-
 /* Pause frame feild and FIFO threshold */
 #define FEC_ENET_FCE   (1 << 5)
 #define FEC_ENET_RSEM_V        0x84
@@ -1248,8 +1246,6 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
 
        fep = netdev_priv(ndev);
 
-       queue_id = FEC_ENET_GET_QUQUE(queue_id);
-
        txq = fep->tx_queue[queue_id];
        /* get next bdp of dirty_tx */
        nq = netdev_get_tx_queue(ndev, queue_id);
@@ -1298,8 +1294,13 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
                        ndev->stats.tx_bytes += skb->len;
                }
 
-               if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) &&
-                       fep->bufdesc_ex) {
+               /* NOTE: SKBTX_IN_PROGRESS being set does not imply it's we who
+                * are to time stamp the packet, so we still need to check time
+                * stamping enabled flag.
+                */
+               if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS &&
+                            fep->hwts_tx_en) &&
+                   fep->bufdesc_ex) {
                        struct skb_shared_hwtstamps shhwtstamps;
                        struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
 
@@ -1340,17 +1341,14 @@ skb_done:
                writel(0, txq->bd.reg_desc_active);
 }
 
-static void
-fec_enet_tx(struct net_device *ndev)
+static void fec_enet_tx(struct net_device *ndev)
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
-       u16 queue_id;
-       /* First process class A queue, then Class B and Best Effort queue */
-       for_each_set_bit(queue_id, &fep->work_tx, FEC_ENET_MAX_TX_QS) {
-               clear_bit(queue_id, &fep->work_tx);
-               fec_enet_tx_queue(ndev, queue_id);
-       }
-       return;
+       int i;
+
+       /* Make sure that AVB queues are processed first. */
+       for (i = fep->num_tx_queues - 1; i >= 0; i--)
+               fec_enet_tx_queue(ndev, i);
 }
 
 static int
@@ -1426,7 +1424,6 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
 #ifdef CONFIG_M532x
        flush_cache_all();
 #endif
-       queue_id = FEC_ENET_GET_QUQUE(queue_id);
        rxq = fep->rx_queue[queue_id];
 
        /* First, grab all of the stats for the incoming packet.
@@ -1550,6 +1547,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
                                               htons(ETH_P_8021Q),
                                               vlan_tag);
 
+               skb_record_rx_queue(skb, queue_id);
                napi_gro_receive(&fep->napi, skb);
 
                if (is_copybreak) {
@@ -1595,48 +1593,30 @@ rx_processing_done:
        return pkt_received;
 }
 
-static int
-fec_enet_rx(struct net_device *ndev, int budget)
+static int fec_enet_rx(struct net_device *ndev, int budget)
 {
-       int     pkt_received = 0;
-       u16     queue_id;
        struct fec_enet_private *fep = netdev_priv(ndev);
+       int i, done = 0;
 
-       for_each_set_bit(queue_id, &fep->work_rx, FEC_ENET_MAX_RX_QS) {
-               int ret;
+       /* Make sure that AVB queues are processed first. */
+       for (i = fep->num_rx_queues - 1; i >= 0; i--)
+               done += fec_enet_rx_queue(ndev, budget - done, i);
 
-               ret = fec_enet_rx_queue(ndev,
-                                       budget - pkt_received, queue_id);
-
-               if (ret < budget - pkt_received)
-                       clear_bit(queue_id, &fep->work_rx);
-
-               pkt_received += ret;
-       }
-       return pkt_received;
+       return done;
 }
 
-static bool
-fec_enet_collect_events(struct fec_enet_private *fep, uint int_events)
+static bool fec_enet_collect_events(struct fec_enet_private *fep)
 {
-       if (int_events == 0)
-               return false;
+       uint int_events;
+
+       int_events = readl(fep->hwp + FEC_IEVENT);
 
-       if (int_events & FEC_ENET_RXF_0)
-               fep->work_rx |= (1 << 2);
-       if (int_events & FEC_ENET_RXF_1)
-               fep->work_rx |= (1 << 0);
-       if (int_events & FEC_ENET_RXF_2)
-               fep->work_rx |= (1 << 1);
+       /* Don't clear MDIO events, we poll for those */
+       int_events &= ~FEC_ENET_MII;
 
-       if (int_events & FEC_ENET_TXF_0)
-               fep->work_tx |= (1 << 2);
-       if (int_events & FEC_ENET_TXF_1)
-               fep->work_tx |= (1 << 0);
-       if (int_events & FEC_ENET_TXF_2)
-               fep->work_tx |= (1 << 1);
+       writel(int_events, fep->hwp + FEC_IEVENT);
 
-       return true;
+       return int_events != 0;
 }
 
 static irqreturn_t
@@ -1644,18 +1624,9 @@ fec_enet_interrupt(int irq, void *dev_id)
 {
        struct net_device *ndev = dev_id;
        struct fec_enet_private *fep = netdev_priv(ndev);
-       uint int_events;
        irqreturn_t ret = IRQ_NONE;
 
-       int_events = readl(fep->hwp + FEC_IEVENT);
-
-       /* Don't clear MDIO events, we poll for those */
-       int_events &= ~FEC_ENET_MII;
-
-       writel(int_events, fep->hwp + FEC_IEVENT);
-       fec_enet_collect_events(fep, int_events);
-
-       if ((fep->work_tx || fep->work_rx) && fep->link) {
+       if (fec_enet_collect_events(fep) && fep->link) {
                ret = IRQ_HANDLED;
 
                if (napi_schedule_prep(&fep->napi)) {
@@ -1672,17 +1643,19 @@ static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
 {
        struct net_device *ndev = napi->dev;
        struct fec_enet_private *fep = netdev_priv(ndev);
-       int pkts;
+       int done = 0;
 
-       pkts = fec_enet_rx(ndev, budget);
-
-       fec_enet_tx(ndev);
+       do {
+               done += fec_enet_rx(ndev, budget - done);
+               fec_enet_tx(ndev);
+       } while ((done < budget) && fec_enet_collect_events(fep));
 
-       if (pkts < budget) {
-               napi_complete_done(napi, pkts);
+       if (done < budget) {
+               napi_complete_done(napi, done);
                writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
        }
-       return pkts;
+
+       return done;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -2755,10 +2728,16 @@ static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
                return -ENODEV;
 
        if (fep->bufdesc_ex) {
-               if (cmd == SIOCSHWTSTAMP)
-                       return fec_ptp_set(ndev, rq);
-               if (cmd == SIOCGHWTSTAMP)
-                       return fec_ptp_get(ndev, rq);
+               bool use_fec_hwts = !phy_has_hwtstamp(phydev);
+
+               if (cmd == SIOCSHWTSTAMP) {
+                       if (use_fec_hwts)
+                               return fec_ptp_set(ndev, rq);
+                       fec_ptp_disable_hwts(ndev);
+               } else if (cmd == SIOCGHWTSTAMP) {
+                       if (use_fec_hwts)
+                               return fec_ptp_get(ndev, rq);
+               }
        }
 
        return phy_mii_ioctl(phydev, rq, cmd);
index 945643c..f8a592c 100644 (file)
@@ -452,6 +452,18 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp,
        return -EOPNOTSUPP;
 }
 
+/**
+ * fec_ptp_disable_hwts - disable hardware time stamping
+ * @ndev: pointer to net_device
+ */
+void fec_ptp_disable_hwts(struct net_device *ndev)
+{
+       struct fec_enet_private *fep = netdev_priv(ndev);
+
+       fep->hwts_tx_en = 0;
+       fep->hwts_rx_en = 0;
+}
+
 int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr)
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
index b3c69e9..b513b8c 100644 (file)
@@ -779,8 +779,12 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
 
        mac_addr = of_get_mac_address(np);
 
-       if (!IS_ERR(mac_addr))
+       if (!IS_ERR(mac_addr)) {
                ether_addr_copy(dev->dev_addr, mac_addr);
+       } else {
+               eth_hw_addr_random(dev);
+               dev_info(&ofdev->dev, "Using random MAC address: %pM\n", dev->dev_addr);
+       }
 
        if (model && !strcasecmp(model, "TSEC"))
                priv->device_flags |= FSL_GIANFAR_DEV_HAS_GIGABIT |
index c117074..23f278e 100644 (file)
@@ -699,7 +699,7 @@ static void hns_nic_rx_up_pro(struct hns_nic_ring_data *ring_data,
        struct net_device *ndev = ring_data->napi.dev;
 
        skb->protocol = eth_type_trans(skb, ndev);
-       (void)napi_gro_receive(&ring_data->napi, skb);
+       napi_gro_receive(&ring_data->napi, skb);
 }
 
 static int hns_desc_unused(struct hnae_ring *ring)
index d041cac..088550d 100644 (file)
@@ -77,6 +77,7 @@
        ((ring)->p = ((ring)->p - 1 + (ring)->desc_num) % (ring)->desc_num)
 
 enum hns_desc_type {
+       DESC_TYPE_UNKNOWN,
        DESC_TYPE_SKB,
        DESC_TYPE_FRAGLIST_SKB,
        DESC_TYPE_PAGE,
index b14f2ab..33c481d 100644 (file)
@@ -1118,12 +1118,12 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv,
                return -ENOMEM;
        }
 
+       desc_cb->priv = priv;
        desc_cb->length = size;
+       desc_cb->dma = dma;
+       desc_cb->type = type;
 
        if (likely(size <= HNS3_MAX_BD_SIZE)) {
-               desc_cb->priv = priv;
-               desc_cb->dma = dma;
-               desc_cb->type = type;
                desc->addr = cpu_to_le64(dma);
                desc->tx.send_size = cpu_to_le16(size);
                desc->tx.bdtp_fe_sc_vld_ra_ri =
@@ -1135,18 +1135,11 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv,
        }
 
        frag_buf_num = hns3_tx_bd_count(size);
-       sizeoflast = size & HNS3_TX_LAST_SIZE_M;
+       sizeoflast = size % HNS3_MAX_BD_SIZE;
        sizeoflast = sizeoflast ? sizeoflast : HNS3_MAX_BD_SIZE;
 
        /* When frag size is bigger than hardware limit, split this frag */
        for (k = 0; k < frag_buf_num; k++) {
-               /* The txbd's baseinfo of DESC_TYPE_PAGE & DESC_TYPE_SKB */
-               desc_cb->priv = priv;
-               desc_cb->dma = dma + HNS3_MAX_BD_SIZE * k;
-               desc_cb->type = ((type == DESC_TYPE_FRAGLIST_SKB ||
-                                 type == DESC_TYPE_SKB) && !k) ?
-                               type : DESC_TYPE_PAGE;
-
                /* now, fill the descriptor */
                desc->addr = cpu_to_le64(dma + HNS3_MAX_BD_SIZE * k);
                desc->tx.send_size = cpu_to_le16((k == frag_buf_num - 1) ?
@@ -1158,7 +1151,6 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv,
                /* move ring pointer to next */
                ring_ptr_move_fw(ring, next_to_use);
 
-               desc_cb = &ring->desc_cb[ring->next_to_use];
                desc = &ring->desc[ring->next_to_use];
        }
 
@@ -1346,6 +1338,10 @@ static void hns3_clear_desc(struct hns3_enet_ring *ring, int next_to_use_orig)
        unsigned int i;
 
        for (i = 0; i < ring->desc_num; i++) {
+               struct hns3_desc *desc = &ring->desc[ring->next_to_use];
+
+               memset(desc, 0, sizeof(*desc));
+
                /* check if this is where we started */
                if (ring->next_to_use == next_to_use_orig)
                        break;
@@ -1353,6 +1349,9 @@ static void hns3_clear_desc(struct hns3_enet_ring *ring, int next_to_use_orig)
                /* rollback one */
                ring_ptr_move_bw(ring, next_to_use);
 
+               if (!ring->desc_cb[ring->next_to_use].dma)
+                       continue;
+
                /* unmap the descriptor dma address */
                if (ring->desc_cb[ring->next_to_use].type == DESC_TYPE_SKB ||
                    ring->desc_cb[ring->next_to_use].type ==
@@ -1369,6 +1368,7 @@ static void hns3_clear_desc(struct hns3_enet_ring *ring, int next_to_use_orig)
 
                ring->desc_cb[ring->next_to_use].length = 0;
                ring->desc_cb[ring->next_to_use].dma = 0;
+               ring->desc_cb[ring->next_to_use].type = DESC_TYPE_UNKNOWN;
        }
 }
 
@@ -4127,9 +4127,8 @@ static void hns3_client_uninit(struct hnae3_handle *handle, bool reset)
 
        hns3_put_ring_config(priv);
 
-       hns3_dbg_uninit(handle);
-
 out_netdev_free:
+       hns3_dbg_uninit(handle);
        free_netdev(netdev);
 }
 
index 66cd439..a877662 100644 (file)
@@ -165,8 +165,6 @@ enum hns3_nic_state {
 #define HNS3_TXD_MSS_S                         0
 #define HNS3_TXD_MSS_M                         (0x3fff << HNS3_TXD_MSS_S)
 
-#define HNS3_TX_LAST_SIZE_M                    0xffff
-
 #define HNS3_VECTOR_TX_IRQ                     BIT_ULL(0)
 #define HNS3_VECTOR_RX_IRQ                     BIT_ULL(1)
 
index 6b1545f..2622e04 100644 (file)
@@ -180,18 +180,21 @@ static void hns3_lb_check_skb_data(struct hns3_enet_ring *ring,
 {
        struct hns3_enet_tqp_vector *tqp_vector = ring->tqp_vector;
        unsigned char *packet = skb->data;
+       u32 len = skb_headlen(skb);
        u32 i;
 
-       for (i = 0; i < skb->len; i++)
+       len = min_t(u32, len, HNS3_NIC_LB_TEST_PACKET_SIZE);
+
+       for (i = 0; i < len; i++)
                if (packet[i] != (unsigned char)(i & 0xff))
                        break;
 
        /* The packet is correctly received */
-       if (i == skb->len)
+       if (i == HNS3_NIC_LB_TEST_PACKET_SIZE)
                tqp_vector->rx_group.total_packets++;
        else
                print_hex_dump(KERN_ERR, "selftest:", DUMP_PREFIX_OFFSET, 16, 1,
-                              skb->data, skb->len, true);
+                              skb->data, len, true);
 
        dev_kfree_skb_any(skb);
 }
index 96bfad5..bb4a632 100644 (file)
@@ -2673,11 +2673,10 @@ void hclge_task_schedule(struct hclge_dev *hdev, unsigned long delay_time)
                                    delay_time);
 }
 
-static int hclge_get_mac_link_status(struct hclge_dev *hdev)
+static int hclge_get_mac_link_status(struct hclge_dev *hdev, int *link_status)
 {
        struct hclge_link_status_cmd *req;
        struct hclge_desc desc;
-       int link_status;
        int ret;
 
        hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_LINK_STATUS, true);
@@ -2689,33 +2688,25 @@ static int hclge_get_mac_link_status(struct hclge_dev *hdev)
        }
 
        req = (struct hclge_link_status_cmd *)desc.data;
-       link_status = req->status & HCLGE_LINK_STATUS_UP_M;
+       *link_status = (req->status & HCLGE_LINK_STATUS_UP_M) > 0 ?
+               HCLGE_LINK_STATUS_UP : HCLGE_LINK_STATUS_DOWN;
 
-       return !!link_status;
+       return 0;
 }
 
-static int hclge_get_mac_phy_link(struct hclge_dev *hdev)
+static int hclge_get_mac_phy_link(struct hclge_dev *hdev, int *link_status)
 {
-       unsigned int mac_state;
-       int link_stat;
+       struct phy_device *phydev = hdev->hw.mac.phydev;
+
+       *link_status = HCLGE_LINK_STATUS_DOWN;
 
        if (test_bit(HCLGE_STATE_DOWN, &hdev->state))
                return 0;
 
-       mac_state = hclge_get_mac_link_status(hdev);
-
-       if (hdev->hw.mac.phydev) {
-               if (hdev->hw.mac.phydev->state == PHY_RUNNING)
-                       link_stat = mac_state &
-                               hdev->hw.mac.phydev->link;
-               else
-                       link_stat = 0;
-
-       } else {
-               link_stat = mac_state;
-       }
+       if (phydev && (phydev->state != PHY_RUNNING || !phydev->link))
+               return 0;
 
-       return !!link_stat;
+       return hclge_get_mac_link_status(hdev, link_status);
 }
 
 static void hclge_update_link_status(struct hclge_dev *hdev)
@@ -2725,6 +2716,7 @@ static void hclge_update_link_status(struct hclge_dev *hdev)
        struct hnae3_handle *rhandle;
        struct hnae3_handle *handle;
        int state;
+       int ret;
        int i;
 
        if (!client)
@@ -2733,7 +2725,12 @@ static void hclge_update_link_status(struct hclge_dev *hdev)
        if (test_and_set_bit(HCLGE_STATE_LINK_UPDATING, &hdev->state))
                return;
 
-       state = hclge_get_mac_phy_link(hdev);
+       ret = hclge_get_mac_phy_link(hdev, &state);
+       if (ret) {
+               clear_bit(HCLGE_STATE_LINK_UPDATING, &hdev->state);
+               return;
+       }
+
        if (state != hdev->hw.mac.link) {
                for (i = 0; i < hdev->num_vmdq_vport + 1; i++) {
                        handle = &hdev->vport[i].nic;
@@ -6524,14 +6521,15 @@ static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret)
 {
 #define HCLGE_MAC_LINK_STATUS_NUM  100
 
+       int link_status;
        int i = 0;
        int ret;
 
        do {
-               ret = hclge_get_mac_link_status(hdev);
-               if (ret < 0)
+               ret = hclge_get_mac_link_status(hdev, &link_status);
+               if (ret)
                        return ret;
-               else if (ret == link_ret)
+               if (link_status == link_ret)
                        return 0;
 
                msleep(HCLGE_LINK_STATUS_MS);
@@ -6542,9 +6540,6 @@ static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret)
 static int hclge_mac_phy_link_status_wait(struct hclge_dev *hdev, bool en,
                                          bool is_phy)
 {
-#define HCLGE_LINK_STATUS_DOWN 0
-#define HCLGE_LINK_STATUS_UP   1
-
        int link_ret;
 
        link_ret = en ? HCLGE_LINK_STATUS_UP : HCLGE_LINK_STATUS_DOWN;
@@ -9859,7 +9854,7 @@ retry:
        set_bit(HCLGE_STATE_RST_HANDLING, &hdev->state);
        hdev->reset_type = HNAE3_FLR_RESET;
        ret = hclge_reset_prepare(hdev);
-       if (ret) {
+       if (ret || hdev->reset_pending) {
                dev_err(&hdev->pdev->dev, "fail to prepare FLR, ret=%d\n",
                        ret);
                if (hdev->reset_pending ||
index 46e6e0f..9bbdd45 100644 (file)
@@ -317,6 +317,9 @@ enum hclge_link_fail_code {
        HCLGE_LF_XSFP_ABSENT,
 };
 
+#define HCLGE_LINK_STATUS_DOWN 0
+#define HCLGE_LINK_STATUS_UP   1
+
 #define HCLGE_PG_NUM           4
 #define HCLGE_SCH_MODE_SP      0
 #define HCLGE_SCH_MODE_DWRR    1
index 1b9578d..a10b022 100644 (file)
@@ -1793,6 +1793,11 @@ static int hclgevf_reset_prepare_wait(struct hclgevf_dev *hdev)
        if (hdev->reset_type == HNAE3_VF_FUNC_RESET) {
                hclgevf_build_send_msg(&send_msg, HCLGE_MBX_RESET, 0);
                ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0);
+               if (ret) {
+                       dev_err(&hdev->pdev->dev,
+                               "failed to assert VF reset, ret = %d\n", ret);
+                       return ret;
+               }
                hdev->rst_stats.vf_func_rst_cnt++;
        }
 
index 0245da0..b735bc5 100644 (file)
@@ -814,6 +814,8 @@ err_aeqs_init:
 err_init_msix:
 err_pfhwdev_alloc:
        hinic_free_hwif(hwif);
+       if (err > 0)
+               err = -EIO;
        return ERR_PTR(err);
 }
 
index c33eb11..e0f5a81 100644 (file)
@@ -370,48 +370,89 @@ int hinic_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt,
                                MSG_NOT_RESP, timeout);
 }
 
-/**
- * mgmt_recv_msg_handler - handler for message from mgmt cpu
- * @pf_to_mgmt: PF to MGMT channel
- * @recv_msg: received message details
- **/
-static void mgmt_recv_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
-                                 struct hinic_recv_msg *recv_msg)
+static void recv_mgmt_msg_work_handler(struct work_struct *work)
 {
-       struct hinic_hwif *hwif = pf_to_mgmt->hwif;
-       struct pci_dev *pdev = hwif->pdev;
-       u8 *buf_out = recv_msg->buf_out;
+       struct hinic_mgmt_msg_handle_work *mgmt_work =
+               container_of(work, struct hinic_mgmt_msg_handle_work, work);
+       struct hinic_pf_to_mgmt *pf_to_mgmt = mgmt_work->pf_to_mgmt;
+       struct pci_dev *pdev = pf_to_mgmt->hwif->pdev;
+       u8 *buf_out = pf_to_mgmt->mgmt_ack_buf;
        struct hinic_mgmt_cb *mgmt_cb;
        unsigned long cb_state;
        u16 out_size = 0;
 
-       if (recv_msg->mod >= HINIC_MOD_MAX) {
+       memset(buf_out, 0, MAX_PF_MGMT_BUF_SIZE);
+
+       if (mgmt_work->mod >= HINIC_MOD_MAX) {
                dev_err(&pdev->dev, "Unknown MGMT MSG module = %d\n",
-                       recv_msg->mod);
+                       mgmt_work->mod);
+               kfree(mgmt_work->msg);
+               kfree(mgmt_work);
                return;
        }
 
-       mgmt_cb = &pf_to_mgmt->mgmt_cb[recv_msg->mod];
+       mgmt_cb = &pf_to_mgmt->mgmt_cb[mgmt_work->mod];
 
        cb_state = cmpxchg(&mgmt_cb->state,
                           HINIC_MGMT_CB_ENABLED,
                           HINIC_MGMT_CB_ENABLED | HINIC_MGMT_CB_RUNNING);
 
        if ((cb_state == HINIC_MGMT_CB_ENABLED) && (mgmt_cb->cb))
-               mgmt_cb->cb(mgmt_cb->handle, recv_msg->cmd,
-                           recv_msg->msg, recv_msg->msg_len,
+               mgmt_cb->cb(mgmt_cb->handle, mgmt_work->cmd,
+                           mgmt_work->msg, mgmt_work->msg_len,
                            buf_out, &out_size);
        else
                dev_err(&pdev->dev, "No MGMT msg handler, mod: %d, cmd: %d\n",
-                       recv_msg->mod, recv_msg->cmd);
+                       mgmt_work->mod, mgmt_work->cmd);
 
        mgmt_cb->state &= ~HINIC_MGMT_CB_RUNNING;
 
-       if (!recv_msg->async_mgmt_to_pf)
+       if (!mgmt_work->async_mgmt_to_pf)
                /* MGMT sent sync msg, send the response */
-               msg_to_mgmt_async(pf_to_mgmt, recv_msg->mod, recv_msg->cmd,
+               msg_to_mgmt_async(pf_to_mgmt, mgmt_work->mod, mgmt_work->cmd,
                                  buf_out, out_size, MGMT_RESP,
-                                 recv_msg->msg_id);
+                                 mgmt_work->msg_id);
+
+       kfree(mgmt_work->msg);
+       kfree(mgmt_work);
+}
+
+/**
+ * mgmt_recv_msg_handler - handler for message from mgmt cpu
+ * @pf_to_mgmt: PF to MGMT channel
+ * @recv_msg: received message details
+ **/
+static void mgmt_recv_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
+                                 struct hinic_recv_msg *recv_msg)
+{
+       struct hinic_mgmt_msg_handle_work *mgmt_work = NULL;
+       struct pci_dev *pdev = pf_to_mgmt->hwif->pdev;
+
+       mgmt_work = kzalloc(sizeof(*mgmt_work), GFP_KERNEL);
+       if (!mgmt_work) {
+               dev_err(&pdev->dev, "Allocate mgmt work memory failed\n");
+               return;
+       }
+
+       if (recv_msg->msg_len) {
+               mgmt_work->msg = kzalloc(recv_msg->msg_len, GFP_KERNEL);
+               if (!mgmt_work->msg) {
+                       dev_err(&pdev->dev, "Allocate mgmt msg memory failed\n");
+                       kfree(mgmt_work);
+                       return;
+               }
+       }
+
+       mgmt_work->pf_to_mgmt = pf_to_mgmt;
+       mgmt_work->msg_len = recv_msg->msg_len;
+       memcpy(mgmt_work->msg, recv_msg->msg, recv_msg->msg_len);
+       mgmt_work->msg_id = recv_msg->msg_id;
+       mgmt_work->mod = recv_msg->mod;
+       mgmt_work->cmd = recv_msg->cmd;
+       mgmt_work->async_mgmt_to_pf = recv_msg->async_mgmt_to_pf;
+
+       INIT_WORK(&mgmt_work->work, recv_mgmt_msg_work_handler);
+       queue_work(pf_to_mgmt->workq, &mgmt_work->work);
 }
 
 /**
@@ -546,6 +587,12 @@ static int alloc_msg_buf(struct hinic_pf_to_mgmt *pf_to_mgmt)
        if (!pf_to_mgmt->sync_msg_buf)
                return -ENOMEM;
 
+       pf_to_mgmt->mgmt_ack_buf = devm_kzalloc(&pdev->dev,
+                                               MAX_PF_MGMT_BUF_SIZE,
+                                               GFP_KERNEL);
+       if (!pf_to_mgmt->mgmt_ack_buf)
+               return -ENOMEM;
+
        return 0;
 }
 
@@ -571,6 +618,11 @@ int hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt *pf_to_mgmt,
                return 0;
 
        sema_init(&pf_to_mgmt->sync_msg_lock, 1);
+       pf_to_mgmt->workq = create_singlethread_workqueue("hinic_mgmt");
+       if (!pf_to_mgmt->workq) {
+               dev_err(&pdev->dev, "Failed to initialize MGMT workqueue\n");
+               return -ENOMEM;
+       }
        pf_to_mgmt->sync_msg_id = 0;
 
        err = alloc_msg_buf(pf_to_mgmt);
@@ -605,4 +657,5 @@ void hinic_pf_to_mgmt_free(struct hinic_pf_to_mgmt *pf_to_mgmt)
 
        hinic_aeq_unregister_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU);
        hinic_api_cmd_free(pf_to_mgmt->cmd_chain);
+       destroy_workqueue(pf_to_mgmt->workq);
 }
index c2b142c..a824fbd 100644 (file)
@@ -119,6 +119,7 @@ struct hinic_pf_to_mgmt {
        struct semaphore                sync_msg_lock;
        u16                             sync_msg_id;
        u8                              *sync_msg_buf;
+       void                            *mgmt_ack_buf;
 
        struct hinic_recv_msg           recv_resp_msg_from_mgmt;
        struct hinic_recv_msg           recv_msg_from_mgmt;
@@ -126,6 +127,21 @@ struct hinic_pf_to_mgmt {
        struct hinic_api_cmd_chain      *cmd_chain[HINIC_API_CMD_MAX];
 
        struct hinic_mgmt_cb            mgmt_cb[HINIC_MOD_MAX];
+
+       struct workqueue_struct         *workq;
+};
+
+struct hinic_mgmt_msg_handle_work {
+       struct work_struct work;
+       struct hinic_pf_to_mgmt *pf_to_mgmt;
+
+       void                    *msg;
+       u16                     msg_len;
+
+       enum hinic_mod_type     mod;
+       u8                      cmd;
+       u16                     msg_id;
+       int                     async_mgmt_to_pf;
 };
 
 void hinic_register_mgmt_msg_cb(struct hinic_pf_to_mgmt *pf_to_mgmt,
index 96d36ae..c5c7326 100644 (file)
@@ -1715,7 +1715,7 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
        }
 
        netdev->min_mtu = IBMVETH_MIN_MTU;
-       netdev->max_mtu = ETH_MAX_MTU;
+       netdev->max_mtu = ETH_MAX_MTU - IBMVETH_BUFF_OH;
 
        memcpy(netdev->dev_addr, mac_addr_p, ETH_ALEN);
 
index 1b4d04e..0fd7eae 100644 (file)
@@ -842,12 +842,13 @@ static int ibmvnic_login(struct net_device *netdev)
        struct ibmvnic_adapter *adapter = netdev_priv(netdev);
        unsigned long timeout = msecs_to_jiffies(30000);
        int retry_count = 0;
+       int retries = 10;
        bool retry;
        int rc;
 
        do {
                retry = false;
-               if (retry_count > IBMVNIC_MAX_QUEUES) {
+               if (retry_count > retries) {
                        netdev_warn(netdev, "Login attempts exceeded\n");
                        return -1;
                }
@@ -862,11 +863,23 @@ static int ibmvnic_login(struct net_device *netdev)
 
                if (!wait_for_completion_timeout(&adapter->init_done,
                                                 timeout)) {
-                       netdev_warn(netdev, "Login timed out\n");
-                       return -1;
+                       netdev_warn(netdev, "Login timed out, retrying...\n");
+                       retry = true;
+                       adapter->init_done_rc = 0;
+                       retry_count++;
+                       continue;
                }
 
-               if (adapter->init_done_rc == PARTIALSUCCESS) {
+               if (adapter->init_done_rc == ABORTED) {
+                       netdev_warn(netdev, "Login aborted, retrying...\n");
+                       retry = true;
+                       adapter->init_done_rc = 0;
+                       retry_count++;
+                       /* FW or device may be busy, so
+                        * wait a bit before retrying login
+                        */
+                       msleep(500);
+               } else if (adapter->init_done_rc == PARTIALSUCCESS) {
                        retry_count++;
                        release_sub_crqs(adapter, 1);
 
@@ -1958,13 +1971,18 @@ static int do_reset(struct ibmvnic_adapter *adapter,
                        release_sub_crqs(adapter, 1);
                } else {
                        rc = ibmvnic_reset_crq(adapter);
-                       if (!rc)
+                       if (rc == H_CLOSED || rc == H_SUCCESS) {
                                rc = vio_enable_interrupts(adapter->vdev);
+                               if (rc)
+                                       netdev_err(adapter->netdev,
+                                                  "Reset failed to enable interrupts. rc=%d\n",
+                                                  rc);
+                       }
                }
 
                if (rc) {
                        netdev_err(adapter->netdev,
-                                  "Couldn't initialize crq. rc=%d\n", rc);
+                                  "Reset couldn't initialize crq. rc=%d\n", rc);
                        goto out;
                }
 
index d9fa460..4b2de08 100644 (file)
@@ -151,10 +151,8 @@ static int e1000_vlan_rx_kill_vid(struct net_device *netdev,
                                  __be16 proto, u16 vid);
 static void e1000_restore_vlan(struct e1000_adapter *adapter);
 
-#ifdef CONFIG_PM
-static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);
-static int e1000_resume(struct pci_dev *pdev);
-#endif
+static int __maybe_unused e1000_suspend(struct device *dev);
+static int __maybe_unused e1000_resume(struct device *dev);
 static void e1000_shutdown(struct pci_dev *pdev);
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -179,16 +177,16 @@ static const struct pci_error_handlers e1000_err_handler = {
        .resume = e1000_io_resume,
 };
 
+static SIMPLE_DEV_PM_OPS(e1000_pm_ops, e1000_suspend, e1000_resume);
+
 static struct pci_driver e1000_driver = {
        .name     = e1000_driver_name,
        .id_table = e1000_pci_tbl,
        .probe    = e1000_probe,
        .remove   = e1000_remove,
-#ifdef CONFIG_PM
-       /* Power Management Hooks */
-       .suspend  = e1000_suspend,
-       .resume   = e1000_resume,
-#endif
+       .driver = {
+               .pm = &e1000_pm_ops,
+       },
        .shutdown = e1000_shutdown,
        .err_handler = &e1000_err_handler
 };
@@ -5060,9 +5058,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
        struct e1000_hw *hw = &adapter->hw;
        u32 ctrl, ctrl_ext, rctl, status;
        u32 wufc = adapter->wol;
-#ifdef CONFIG_PM
-       int retval = 0;
-#endif
 
        netif_device_detach(netdev);
 
@@ -5076,12 +5071,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
                e1000_down(adapter);
        }
 
-#ifdef CONFIG_PM
-       retval = pci_save_state(pdev);
-       if (retval)
-               return retval;
-#endif
-
        status = er32(STATUS);
        if (status & E1000_STATUS_LU)
                wufc &= ~E1000_WUFC_LNKC;
@@ -5142,37 +5131,26 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
+static int __maybe_unused e1000_suspend(struct device *dev)
 {
        int retval;
+       struct pci_dev *pdev = to_pci_dev(dev);
        bool wake;
 
        retval = __e1000_shutdown(pdev, &wake);
-       if (retval)
-               return retval;
-
-       if (wake) {
-               pci_prepare_to_sleep(pdev);
-       } else {
-               pci_wake_from_d3(pdev, false);
-               pci_set_power_state(pdev, PCI_D3hot);
-       }
+       device_set_wakeup_enable(dev, wake);
 
-       return 0;
+       return retval;
 }
 
-static int e1000_resume(struct pci_dev *pdev)
+static int __maybe_unused e1000_resume(struct device *dev)
 {
+       struct pci_dev *pdev = to_pci_dev(dev);
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
        u32 err;
 
-       pci_set_power_state(pdev, PCI_D0);
-       pci_restore_state(pdev);
-       pci_save_state(pdev);
-
        if (adapter->need_ioport)
                err = pci_enable_device(pdev);
        else
@@ -5209,7 +5187,6 @@ static int e1000_resume(struct pci_dev *pdev)
 
        return 0;
 }
-#endif
 
 static void e1000_shutdown(struct pci_dev *pdev)
 {
index a279f4f..6f6479c 100644 (file)
@@ -6349,7 +6349,6 @@ fl_out:
        pm_runtime_put_sync(netdev->dev.parent);
 }
 
-#ifdef CONFIG_PM_SLEEP
 /* S0ix implementation */
 static void e1000e_s0ix_entry_flow(struct e1000_adapter *adapter)
 {
@@ -6571,7 +6570,6 @@ static void e1000e_s0ix_exit_flow(struct e1000_adapter *adapter)
        mac_data &= ~E1000_CTRL_EXT_FORCE_SMBUS;
        ew32(CTRL_EXT, mac_data);
 }
-#endif /* CONFIG_PM_SLEEP */
 
 static int e1000e_pm_freeze(struct device *dev)
 {
@@ -6611,11 +6609,17 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
-       u32 ctrl, ctrl_ext, rctl, status;
-       /* Runtime suspend should only enable wakeup for link changes */
-       u32 wufc = runtime ? E1000_WUFC_LNKC : adapter->wol;
+       u32 ctrl, ctrl_ext, rctl, status, wufc;
        int retval = 0;
 
+       /* Runtime suspend should only enable wakeup for link changes */
+       if (runtime)
+               wufc = E1000_WUFC_LNKC;
+       else if (device_may_wakeup(&pdev->dev))
+               wufc = adapter->wol;
+       else
+               wufc = 0;
+
        status = er32(STATUS);
        if (status & E1000_STATUS_LU)
                wufc &= ~E1000_WUFC_LNKC;
@@ -6672,7 +6676,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
        if (adapter->hw.phy.type == e1000_phy_igp_3) {
                e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw);
        } else if (hw->mac.type >= e1000_pch_lpt) {
-               if (!(wufc & (E1000_WUFC_EX | E1000_WUFC_MC | E1000_WUFC_BC)))
+               if (wufc && !(wufc & (E1000_WUFC_EX | E1000_WUFC_MC | E1000_WUFC_BC)))
                        /* ULP does not support wake from unicast, multicast
                         * or broadcast.
                         */
@@ -6869,7 +6873,6 @@ err_irq:
        return rc;
 }
 
-#ifdef CONFIG_PM
 static int __e1000_resume(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
@@ -6935,8 +6938,7 @@ static int __e1000_resume(struct pci_dev *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int e1000e_pm_suspend(struct device *dev)
+static __maybe_unused int e1000e_pm_suspend(struct device *dev)
 {
        struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));
        struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -6960,7 +6962,7 @@ static int e1000e_pm_suspend(struct device *dev)
        return rc;
 }
 
-static int e1000e_pm_resume(struct device *dev)
+static __maybe_unused int e1000e_pm_resume(struct device *dev)
 {
        struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));
        struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -6979,9 +6981,8 @@ static int e1000e_pm_resume(struct device *dev)
 
        return e1000e_pm_thaw(dev);
 }
-#endif /* CONFIG_PM_SLEEP */
 
-static int e1000e_pm_runtime_idle(struct device *dev)
+static __maybe_unused int e1000e_pm_runtime_idle(struct device *dev)
 {
        struct net_device *netdev = dev_get_drvdata(dev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -6997,7 +6998,7 @@ static int e1000e_pm_runtime_idle(struct device *dev)
        return -EBUSY;
 }
 
-static int e1000e_pm_runtime_resume(struct device *dev)
+static __maybe_unused int e1000e_pm_runtime_resume(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        struct net_device *netdev = pci_get_drvdata(pdev);
@@ -7014,7 +7015,7 @@ static int e1000e_pm_runtime_resume(struct device *dev)
        return rc;
 }
 
-static int e1000e_pm_runtime_suspend(struct device *dev)
+static __maybe_unused int e1000e_pm_runtime_suspend(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        struct net_device *netdev = pci_get_drvdata(pdev);
@@ -7039,7 +7040,6 @@ static int e1000e_pm_runtime_suspend(struct device *dev)
 
        return 0;
 }
-#endif /* CONFIG_PM */
 
 static void e1000_shutdown(struct pci_dev *pdev)
 {
index aa8026b..67806b7 100644 (file)
@@ -2070,6 +2070,9 @@ static int i40e_set_ringparam(struct net_device *netdev,
                         */
                        rx_rings[i].tail = hw->hw_addr + I40E_PRTGEN_STATUS;
                        err = i40e_setup_rx_descriptors(&rx_rings[i]);
+                       if (err)
+                               goto rx_unwind;
+                       err = i40e_alloc_rx_bi(&rx_rings[i]);
                        if (err)
                                goto rx_unwind;
 
index 5d807c8..56ecd6c 100644 (file)
@@ -439,11 +439,15 @@ static void i40e_get_netdev_stats_struct(struct net_device *netdev,
                i40e_get_netdev_stats_struct_tx(ring, stats);
 
                if (i40e_enabled_xdp_vsi(vsi)) {
-                       ring++;
+                       ring = READ_ONCE(vsi->xdp_rings[i]);
+                       if (!ring)
+                               continue;
                        i40e_get_netdev_stats_struct_tx(ring, stats);
                }
 
-               ring++;
+               ring = READ_ONCE(vsi->rx_rings[i]);
+               if (!ring)
+                       continue;
                do {
                        start   = u64_stats_fetch_begin_irq(&ring->syncp);
                        packets = ring->stats.packets;
@@ -787,6 +791,8 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
        for (q = 0; q < vsi->num_queue_pairs; q++) {
                /* locate Tx ring */
                p = READ_ONCE(vsi->tx_rings[q]);
+               if (!p)
+                       continue;
 
                do {
                        start = u64_stats_fetch_begin_irq(&p->syncp);
@@ -800,8 +806,11 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
                tx_linearize += p->tx_stats.tx_linearize;
                tx_force_wb += p->tx_stats.tx_force_wb;
 
-               /* Rx queue is part of the same block as Tx queue */
-               p = &p[1];
+               /* locate Rx ring */
+               p = READ_ONCE(vsi->rx_rings[q]);
+               if (!p)
+                       continue;
+
                do {
                        start = u64_stats_fetch_begin_irq(&p->syncp);
                        packets = p->stats.packets;
@@ -10824,10 +10833,10 @@ static void i40e_vsi_clear_rings(struct i40e_vsi *vsi)
        if (vsi->tx_rings && vsi->tx_rings[0]) {
                for (i = 0; i < vsi->alloc_queue_pairs; i++) {
                        kfree_rcu(vsi->tx_rings[i], rcu);
-                       vsi->tx_rings[i] = NULL;
-                       vsi->rx_rings[i] = NULL;
+                       WRITE_ONCE(vsi->tx_rings[i], NULL);
+                       WRITE_ONCE(vsi->rx_rings[i], NULL);
                        if (vsi->xdp_rings)
-                               vsi->xdp_rings[i] = NULL;
+                               WRITE_ONCE(vsi->xdp_rings[i], NULL);
                }
        }
 }
@@ -10861,7 +10870,7 @@ static int i40e_alloc_rings(struct i40e_vsi *vsi)
                if (vsi->back->hw_features & I40E_HW_WB_ON_ITR_CAPABLE)
                        ring->flags = I40E_TXR_FLAGS_WB_ON_ITR;
                ring->itr_setting = pf->tx_itr_default;
-               vsi->tx_rings[i] = ring++;
+               WRITE_ONCE(vsi->tx_rings[i], ring++);
 
                if (!i40e_enabled_xdp_vsi(vsi))
                        goto setup_rx;
@@ -10879,7 +10888,7 @@ static int i40e_alloc_rings(struct i40e_vsi *vsi)
                        ring->flags = I40E_TXR_FLAGS_WB_ON_ITR;
                set_ring_xdp(ring);
                ring->itr_setting = pf->tx_itr_default;
-               vsi->xdp_rings[i] = ring++;
+               WRITE_ONCE(vsi->xdp_rings[i], ring++);
 
 setup_rx:
                ring->queue_index = i;
@@ -10892,7 +10901,7 @@ setup_rx:
                ring->size = 0;
                ring->dcb_tc = 0;
                ring->itr_setting = pf->rx_itr_default;
-               vsi->rx_rings[i] = ring;
+               WRITE_ONCE(vsi->rx_rings[i], ring);
        }
 
        return 0;
index 28b46cc..2e3a39c 100644 (file)
@@ -1194,7 +1194,7 @@ static void ice_vsi_clear_rings(struct ice_vsi *vsi)
                for (i = 0; i < vsi->alloc_txq; i++) {
                        if (vsi->tx_rings[i]) {
                                kfree_rcu(vsi->tx_rings[i], rcu);
-                               vsi->tx_rings[i] = NULL;
+                               WRITE_ONCE(vsi->tx_rings[i], NULL);
                        }
                }
        }
@@ -1202,7 +1202,7 @@ static void ice_vsi_clear_rings(struct ice_vsi *vsi)
                for (i = 0; i < vsi->alloc_rxq; i++) {
                        if (vsi->rx_rings[i]) {
                                kfree_rcu(vsi->rx_rings[i], rcu);
-                               vsi->rx_rings[i] = NULL;
+                               WRITE_ONCE(vsi->rx_rings[i], NULL);
                        }
                }
        }
@@ -1235,7 +1235,7 @@ static int ice_vsi_alloc_rings(struct ice_vsi *vsi)
                ring->vsi = vsi;
                ring->dev = dev;
                ring->count = vsi->num_tx_desc;
-               vsi->tx_rings[i] = ring;
+               WRITE_ONCE(vsi->tx_rings[i], ring);
        }
 
        /* Allocate Rx rings */
@@ -1254,7 +1254,7 @@ static int ice_vsi_alloc_rings(struct ice_vsi *vsi)
                ring->netdev = vsi->netdev;
                ring->dev = dev;
                ring->count = vsi->num_rx_desc;
-               vsi->rx_rings[i] = ring;
+               WRITE_ONCE(vsi->rx_rings[i], ring);
        }
 
        return 0;
index 082825e..4cbd49c 100644 (file)
@@ -1702,7 +1702,7 @@ static int ice_xdp_alloc_setup_rings(struct ice_vsi *vsi)
                xdp_ring->netdev = NULL;
                xdp_ring->dev = dev;
                xdp_ring->count = vsi->num_tx_desc;
-               vsi->xdp_rings[i] = xdp_ring;
+               WRITE_ONCE(vsi->xdp_rings[i], xdp_ring);
                if (ice_setup_tx_ring(xdp_ring))
                        goto free_xdp_rings;
                ice_set_ring_xdp(xdp_ring);
index fd9f5d4..2e35c57 100644 (file)
@@ -921,7 +921,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
                ring->queue_index = txr_idx;
 
                /* assign ring to adapter */
-               adapter->tx_ring[txr_idx] = ring;
+               WRITE_ONCE(adapter->tx_ring[txr_idx], ring);
 
                /* update count and index */
                txr_count--;
@@ -948,7 +948,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
                set_ring_xdp(ring);
 
                /* assign ring to adapter */
-               adapter->xdp_ring[xdp_idx] = ring;
+               WRITE_ONCE(adapter->xdp_ring[xdp_idx], ring);
 
                /* update count and index */
                xdp_count--;
@@ -991,7 +991,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
                ring->queue_index = rxr_idx;
 
                /* assign ring to adapter */
-               adapter->rx_ring[rxr_idx] = ring;
+               WRITE_ONCE(adapter->rx_ring[rxr_idx], ring);
 
                /* update count and index */
                rxr_count--;
@@ -1020,13 +1020,13 @@ static void ixgbe_free_q_vector(struct ixgbe_adapter *adapter, int v_idx)
 
        ixgbe_for_each_ring(ring, q_vector->tx) {
                if (ring_is_xdp(ring))
-                       adapter->xdp_ring[ring->queue_index] = NULL;
+                       WRITE_ONCE(adapter->xdp_ring[ring->queue_index], NULL);
                else
-                       adapter->tx_ring[ring->queue_index] = NULL;
+                       WRITE_ONCE(adapter->tx_ring[ring->queue_index], NULL);
        }
 
        ixgbe_for_each_ring(ring, q_vector->rx)
-               adapter->rx_ring[ring->queue_index] = NULL;
+               WRITE_ONCE(adapter->rx_ring[ring->queue_index], NULL);
 
        adapter->q_vector[v_idx] = NULL;
        napi_hash_del(&q_vector->napi);
index f162b8b..97a423e 100644 (file)
@@ -7051,7 +7051,10 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
        }
 
        for (i = 0; i < adapter->num_rx_queues; i++) {
-               struct ixgbe_ring *rx_ring = adapter->rx_ring[i];
+               struct ixgbe_ring *rx_ring = READ_ONCE(adapter->rx_ring[i]);
+
+               if (!rx_ring)
+                       continue;
                non_eop_descs += rx_ring->rx_stats.non_eop_descs;
                alloc_rx_page += rx_ring->rx_stats.alloc_rx_page;
                alloc_rx_page_failed += rx_ring->rx_stats.alloc_rx_page_failed;
@@ -7072,15 +7075,20 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
        packets = 0;
        /* gather some stats to the adapter struct that are per queue */
        for (i = 0; i < adapter->num_tx_queues; i++) {
-               struct ixgbe_ring *tx_ring = adapter->tx_ring[i];
+               struct ixgbe_ring *tx_ring = READ_ONCE(adapter->tx_ring[i]);
+
+               if (!tx_ring)
+                       continue;
                restart_queue += tx_ring->tx_stats.restart_queue;
                tx_busy += tx_ring->tx_stats.tx_busy;
                bytes += tx_ring->stats.bytes;
                packets += tx_ring->stats.packets;
        }
        for (i = 0; i < adapter->num_xdp_queues; i++) {
-               struct ixgbe_ring *xdp_ring = adapter->xdp_ring[i];
+               struct ixgbe_ring *xdp_ring = READ_ONCE(adapter->xdp_ring[i]);
 
+               if (!xdp_ring)
+                       continue;
                restart_queue += xdp_ring->tx_stats.restart_queue;
                tx_busy += xdp_ring->tx_stats.tx_busy;
                bytes += xdp_ring->stats.bytes;
index 946925b..7d5d9d3 100644 (file)
 #define      MVNETA_TX_IN_PRGRS                  BIT(1)
 #define      MVNETA_TX_FIFO_EMPTY                BIT(8)
 #define MVNETA_RX_MIN_FRAME_SIZE                 0x247c
+/* Only exists on Armada XP and Armada 370 */
 #define MVNETA_SERDES_CFG                       0x24A0
 #define      MVNETA_SGMII_SERDES_PROTO          0x0cc7
 #define      MVNETA_QSGMII_SERDES_PROTO                 0x0667
+#define      MVNETA_HSGMII_SERDES_PROTO                 0x1107
 #define MVNETA_TYPE_PRIO                         0x24bc
 #define      MVNETA_FORCE_UNI                    BIT(21)
 #define MVNETA_TXQ_CMD_1                         0x24e4
@@ -3529,26 +3531,60 @@ static int mvneta_setup_txqs(struct mvneta_port *pp)
        return 0;
 }
 
-static int mvneta_comphy_init(struct mvneta_port *pp)
+static int mvneta_comphy_init(struct mvneta_port *pp, phy_interface_t interface)
 {
        int ret;
 
-       if (!pp->comphy)
-               return 0;
-
-       ret = phy_set_mode_ext(pp->comphy, PHY_MODE_ETHERNET,
-                              pp->phy_interface);
+       ret = phy_set_mode_ext(pp->comphy, PHY_MODE_ETHERNET, interface);
        if (ret)
                return ret;
 
        return phy_power_on(pp->comphy);
 }
 
+static int mvneta_config_interface(struct mvneta_port *pp,
+                                  phy_interface_t interface)
+{
+       int ret = 0;
+
+       if (pp->comphy) {
+               if (interface == PHY_INTERFACE_MODE_SGMII ||
+                   interface == PHY_INTERFACE_MODE_1000BASEX ||
+                   interface == PHY_INTERFACE_MODE_2500BASEX) {
+                       ret = mvneta_comphy_init(pp, interface);
+               }
+       } else {
+               switch (interface) {
+               case PHY_INTERFACE_MODE_QSGMII:
+                       mvreg_write(pp, MVNETA_SERDES_CFG,
+                                   MVNETA_QSGMII_SERDES_PROTO);
+                       break;
+
+               case PHY_INTERFACE_MODE_SGMII:
+               case PHY_INTERFACE_MODE_1000BASEX:
+                       mvreg_write(pp, MVNETA_SERDES_CFG,
+                                   MVNETA_SGMII_SERDES_PROTO);
+                       break;
+
+               case PHY_INTERFACE_MODE_2500BASEX:
+                       mvreg_write(pp, MVNETA_SERDES_CFG,
+                                   MVNETA_HSGMII_SERDES_PROTO);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       pp->phy_interface = interface;
+
+       return ret;
+}
+
 static void mvneta_start_dev(struct mvneta_port *pp)
 {
        int cpu;
 
-       WARN_ON(mvneta_comphy_init(pp));
+       WARN_ON(mvneta_config_interface(pp, pp->phy_interface));
 
        mvneta_max_rx_size_set(pp, pp->pkt_size);
        mvneta_txq_max_tx_size_set(pp, pp->pkt_size);
@@ -3923,17 +3959,13 @@ static void mvneta_mac_config(struct phylink_config *config, unsigned int mode,
        /* When at 2.5G, the link partner can send frames with shortened
         * preambles.
         */
-       if (state->speed == SPEED_2500)
+       if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
                new_ctrl4 |= MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE;
 
-       if (pp->comphy && pp->phy_interface != state->interface &&
-           (state->interface == PHY_INTERFACE_MODE_SGMII ||
-            state->interface == PHY_INTERFACE_MODE_1000BASEX ||
-            state->interface == PHY_INTERFACE_MODE_2500BASEX)) {
-               pp->phy_interface = state->interface;
-
-               WARN_ON(phy_power_off(pp->comphy));
-               WARN_ON(mvneta_comphy_init(pp));
+       if (pp->phy_interface != state->interface) {
+               if (pp->comphy)
+                       WARN_ON(phy_power_off(pp->comphy));
+               WARN_ON(mvneta_config_interface(pp, state->interface));
        }
 
        if (new_ctrl0 != gmac_ctrl0)
@@ -4982,12 +5014,10 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
        /* MAC Cause register should be cleared */
        mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0);
 
-       if (phy_mode == PHY_INTERFACE_MODE_QSGMII)
-               mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_QSGMII_SERDES_PROTO);
-       else if (phy_mode == PHY_INTERFACE_MODE_SGMII ||
-                phy_interface_mode_is_8023z(phy_mode))
-               mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO);
-       else if (!phy_interface_mode_is_rgmii(phy_mode))
+       if (phy_mode != PHY_INTERFACE_MODE_QSGMII &&
+           phy_mode != PHY_INTERFACE_MODE_SGMII &&
+           !phy_interface_mode_is_8023z(phy_mode) &&
+           !phy_interface_mode_is_rgmii(phy_mode))
                return -EINVAL;
 
        return 0;
@@ -5176,10 +5206,10 @@ static int mvneta_probe(struct platform_device *pdev)
        if (err < 0)
                goto err_netdev;
 
-       err = mvneta_port_power_up(pp, phy_mode);
+       err = mvneta_port_power_up(pp, pp->phy_interface);
        if (err < 0) {
                dev_err(&pdev->dev, "can't power up port\n");
-               goto err_netdev;
+               return err;
        }
 
        /* Armada3700 network controller does not support per-cpu
index 2b5dad2..24f4d8e 100644 (file)
@@ -1544,7 +1544,7 @@ static void mvpp2_read_stats(struct mvpp2_port *port)
        for (q = 0; q < port->ntxqs; q++)
                for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_txq_regs); i++)
                        *pstats++ += mvpp2_read_index(port->priv,
-                                                     MVPP22_CTRS_TX_CTR(port->id, i),
+                                                     MVPP22_CTRS_TX_CTR(port->id, q),
                                                      mvpp2_ethtool_txq_regs[i].offset);
 
        /* Rxqs are numbered from 0 from the user standpoint, but not from the
@@ -1553,7 +1553,7 @@ static void mvpp2_read_stats(struct mvpp2_port *port)
        for (q = 0; q < port->nrxqs; q++)
                for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_rxq_regs); i++)
                        *pstats++ += mvpp2_read_index(port->priv,
-                                                     port->first_rxq + i,
+                                                     port->first_rxq + q,
                                                      mvpp2_ethtool_rxq_regs[i].offset);
 }
 
@@ -5983,8 +5983,8 @@ static int mvpp2_remove(struct platform_device *pdev)
 {
        struct mvpp2 *priv = platform_get_drvdata(pdev);
        struct fwnode_handle *fwnode = pdev->dev.fwnode;
+       int i = 0, poolnum = MVPP2_BM_POOLS_NUM;
        struct fwnode_handle *port_fwnode;
-       int i = 0;
 
        mvpp2_dbgfs_cleanup(priv);
 
@@ -5998,7 +5998,10 @@ static int mvpp2_remove(struct platform_device *pdev)
 
        destroy_workqueue(priv->stats_queue);
 
-       for (i = 0; i < MVPP2_BM_POOLS_NUM; i++) {
+       if (priv->percpu_pools)
+               poolnum = mvpp2_get_nrxqs(priv) * 2;
+
+       for (i = 0; i < poolnum; i++) {
                struct mvpp2_bm_pool *bm_pool = &priv->bm_pools[i];
 
                mvpp2_bm_pool_destroy(&pdev->dev, priv, bm_pool);
index 241f007..fe54764 100644 (file)
@@ -203,7 +203,7 @@ io_error:
 
 static inline u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg)
 {
-       u16 v;
+       u16 v = 0;
        __gm_phy_read(hw, port, reg, &v);
        return v;
 }
index f1ace4f..3e765bd 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/regmap.h>
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
-#include <linux/workqueue.h>
 
 #define MTK_STAR_DRVNAME                       "mtk_star_emac"
 
@@ -262,7 +261,6 @@ struct mtk_star_priv {
        spinlock_t lock;
 
        struct rtnl_link_stats64 stats;
-       struct work_struct stats_work;
 };
 
 static struct device *mtk_star_get_dev(struct mtk_star_priv *priv)
@@ -432,42 +430,6 @@ static void mtk_star_intr_disable(struct mtk_star_priv *priv)
        regmap_write(priv->regs, MTK_STAR_REG_INT_MASK, ~0);
 }
 
-static void mtk_star_intr_enable_tx(struct mtk_star_priv *priv)
-{
-       regmap_clear_bits(priv->regs, MTK_STAR_REG_INT_MASK,
-                         MTK_STAR_BIT_INT_STS_TNTC);
-}
-
-static void mtk_star_intr_enable_rx(struct mtk_star_priv *priv)
-{
-       regmap_clear_bits(priv->regs, MTK_STAR_REG_INT_MASK,
-                         MTK_STAR_BIT_INT_STS_FNRC);
-}
-
-static void mtk_star_intr_enable_stats(struct mtk_star_priv *priv)
-{
-       regmap_clear_bits(priv->regs, MTK_STAR_REG_INT_MASK,
-                         MTK_STAR_REG_INT_STS_MIB_CNT_TH);
-}
-
-static void mtk_star_intr_disable_tx(struct mtk_star_priv *priv)
-{
-       regmap_set_bits(priv->regs, MTK_STAR_REG_INT_MASK,
-                       MTK_STAR_BIT_INT_STS_TNTC);
-}
-
-static void mtk_star_intr_disable_rx(struct mtk_star_priv *priv)
-{
-       regmap_set_bits(priv->regs, MTK_STAR_REG_INT_MASK,
-                       MTK_STAR_BIT_INT_STS_FNRC);
-}
-
-static void mtk_star_intr_disable_stats(struct mtk_star_priv *priv)
-{
-       regmap_set_bits(priv->regs, MTK_STAR_REG_INT_MASK,
-                       MTK_STAR_REG_INT_STS_MIB_CNT_TH);
-}
-
 static unsigned int mtk_star_intr_read(struct mtk_star_priv *priv)
 {
        unsigned int val;
@@ -663,20 +625,6 @@ static void mtk_star_update_stats(struct mtk_star_priv *priv)
        stats->rx_errors += stats->rx_fifo_errors;
 }
 
-/* This runs in process context and parallel TX and RX paths executing in
- * napi context may result in losing some stats data but this should happen
- * seldom enough to be acceptable.
- */
-static void mtk_star_update_stats_work(struct work_struct *work)
-{
-       struct mtk_star_priv *priv = container_of(work, struct mtk_star_priv,
-                                                stats_work);
-
-       mtk_star_update_stats(priv);
-       mtk_star_reset_counters(priv);
-       mtk_star_intr_enable_stats(priv);
-}
-
 static struct sk_buff *mtk_star_alloc_skb(struct net_device *ndev)
 {
        uintptr_t tail, offset;
@@ -767,42 +715,25 @@ static void mtk_star_free_tx_skbs(struct mtk_star_priv *priv)
        mtk_star_ring_free_skbs(priv, ring, mtk_star_dma_unmap_tx);
 }
 
-/* All processing for TX and RX happens in the napi poll callback. */
+/* All processing for TX and RX happens in the napi poll callback.
+ *
+ * FIXME: The interrupt handling should be more fine-grained with each
+ * interrupt enabled/disabled independently when needed. Unfortunatly this
+ * turned out to impact the driver's stability and until we have something
+ * working properly, we're disabling all interrupts during TX & RX processing
+ * or when resetting the counter registers.
+ */
 static irqreturn_t mtk_star_handle_irq(int irq, void *data)
 {
        struct mtk_star_priv *priv;
        struct net_device *ndev;
-       bool need_napi = false;
-       unsigned int status;
 
        ndev = data;
        priv = netdev_priv(ndev);
 
        if (netif_running(ndev)) {
-               status = mtk_star_intr_read(priv);
-
-               if (status & MTK_STAR_BIT_INT_STS_TNTC) {
-                       mtk_star_intr_disable_tx(priv);
-                       need_napi = true;
-               }
-
-               if (status & MTK_STAR_BIT_INT_STS_FNRC) {
-                       mtk_star_intr_disable_rx(priv);
-                       need_napi = true;
-               }
-
-               if (need_napi)
-                       napi_schedule(&priv->napi);
-
-               /* One of the counters reached 0x8000000 - update stats and
-                * reset all counters.
-                */
-               if (unlikely(status & MTK_STAR_REG_INT_STS_MIB_CNT_TH)) {
-                       mtk_star_intr_disable_stats(priv);
-                       schedule_work(&priv->stats_work);
-               }
-
-               mtk_star_intr_ack_all(priv);
+               mtk_star_intr_disable(priv);
+               napi_schedule(&priv->napi);
        }
 
        return IRQ_HANDLED;
@@ -1169,8 +1100,6 @@ static void mtk_star_tx_complete_all(struct mtk_star_priv *priv)
        if (wake && netif_queue_stopped(ndev))
                netif_wake_queue(ndev);
 
-       mtk_star_intr_enable_tx(priv);
-
        spin_unlock(&priv->lock);
 }
 
@@ -1332,20 +1261,32 @@ static int mtk_star_process_rx(struct mtk_star_priv *priv, int budget)
 static int mtk_star_poll(struct napi_struct *napi, int budget)
 {
        struct mtk_star_priv *priv;
+       unsigned int status;
        int received = 0;
 
        priv = container_of(napi, struct mtk_star_priv, napi);
 
-       /* Clean-up all TX descriptors. */
-       mtk_star_tx_complete_all(priv);
-       /* Receive up to $budget packets. */
-       received = mtk_star_process_rx(priv, budget);
+       status = mtk_star_intr_read(priv);
+       mtk_star_intr_ack_all(priv);
 
-       if (received < budget) {
-               napi_complete_done(napi, received);
-               mtk_star_intr_enable_rx(priv);
+       if (status & MTK_STAR_BIT_INT_STS_TNTC)
+               /* Clean-up all TX descriptors. */
+               mtk_star_tx_complete_all(priv);
+
+       if (status & MTK_STAR_BIT_INT_STS_FNRC)
+               /* Receive up to $budget packets. */
+               received = mtk_star_process_rx(priv, budget);
+
+       if (unlikely(status & MTK_STAR_REG_INT_STS_MIB_CNT_TH)) {
+               mtk_star_update_stats(priv);
+               mtk_star_reset_counters(priv);
        }
 
+       if (received < budget)
+               napi_complete_done(napi, received);
+
+       mtk_star_intr_enable(priv);
+
        return received;
 }
 
@@ -1532,7 +1473,6 @@ static int mtk_star_probe(struct platform_device *pdev)
        ndev->max_mtu = MTK_STAR_MAX_FRAME_SIZE;
 
        spin_lock_init(&priv->lock);
-       INIT_WORK(&priv->stats_work, mtk_star_update_stats_work);
 
        base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(base))
index 7be6b2d..9976de8 100644 (file)
@@ -29,6 +29,7 @@ struct mlx5e_dcbx {
        bool                       manual_buffer;
        u32                        cable_len;
        u32                        xoff;
+       u16                        port_buff_cell_sz;
 };
 
 #define MLX5E_MAX_DSCP (64)
index 2a8950b..3cf3e35 100644 (file)
@@ -78,11 +78,26 @@ static const u32 mlx5e_ext_link_speed[MLX5E_EXT_LINK_MODES_NUMBER] = {
        [MLX5E_400GAUI_8]                       = 400000,
 };
 
+bool mlx5e_ptys_ext_supported(struct mlx5_core_dev *mdev)
+{
+       struct mlx5e_port_eth_proto eproto;
+       int err;
+
+       if (MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet))
+               return true;
+
+       err = mlx5_port_query_eth_proto(mdev, 1, true, &eproto);
+       if (err)
+               return false;
+
+       return !!eproto.cap;
+}
+
 static void mlx5e_port_get_speed_arr(struct mlx5_core_dev *mdev,
                                     const u32 **arr, u32 *size,
                                     bool force_legacy)
 {
-       bool ext = force_legacy ? false : MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+       bool ext = force_legacy ? false : mlx5e_ptys_ext_supported(mdev);
 
        *size = ext ? ARRAY_SIZE(mlx5e_ext_link_speed) :
                      ARRAY_SIZE(mlx5e_link_speed);
@@ -177,7 +192,7 @@ int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
        bool ext;
        int err;
 
-       ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+       ext = mlx5e_ptys_ext_supported(mdev);
        err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
        if (err)
                goto out;
@@ -205,7 +220,7 @@ int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
        int err;
        int i;
 
-       ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+       ext = mlx5e_ptys_ext_supported(mdev);
        err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
        if (err)
                return err;
index a2ddd44..7a7defe 100644 (file)
@@ -54,7 +54,7 @@ int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
 int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
 u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed,
                               bool force_legacy);
-
+bool mlx5e_ptys_ext_supported(struct mlx5_core_dev *mdev);
 int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out);
 int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in);
 int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer);
index ae99fac..673f1c8 100644 (file)
@@ -34,6 +34,7 @@
 int mlx5e_port_query_buffer(struct mlx5e_priv *priv,
                            struct mlx5e_port_buffer *port_buffer)
 {
+       u16 port_buff_cell_sz = priv->dcbx.port_buff_cell_sz;
        struct mlx5_core_dev *mdev = priv->mdev;
        int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
        u32 total_used = 0;
@@ -57,11 +58,11 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv,
                port_buffer->buffer[i].epsb =
                        MLX5_GET(bufferx_reg, buffer, epsb);
                port_buffer->buffer[i].size =
-                       MLX5_GET(bufferx_reg, buffer, size) << MLX5E_BUFFER_CELL_SHIFT;
+                       MLX5_GET(bufferx_reg, buffer, size) * port_buff_cell_sz;
                port_buffer->buffer[i].xon =
-                       MLX5_GET(bufferx_reg, buffer, xon_threshold) << MLX5E_BUFFER_CELL_SHIFT;
+                       MLX5_GET(bufferx_reg, buffer, xon_threshold) * port_buff_cell_sz;
                port_buffer->buffer[i].xoff =
-                       MLX5_GET(bufferx_reg, buffer, xoff_threshold) << MLX5E_BUFFER_CELL_SHIFT;
+                       MLX5_GET(bufferx_reg, buffer, xoff_threshold) * port_buff_cell_sz;
                total_used += port_buffer->buffer[i].size;
 
                mlx5e_dbg(HW, priv, "buffer %d: size=%d, xon=%d, xoff=%d, epsb=%d, lossy=%d\n", i,
@@ -73,7 +74,7 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv,
        }
 
        port_buffer->port_buffer_size =
-               MLX5_GET(pbmc_reg, out, port_buffer_size) << MLX5E_BUFFER_CELL_SHIFT;
+               MLX5_GET(pbmc_reg, out, port_buffer_size) * port_buff_cell_sz;
        port_buffer->spare_buffer_size =
                port_buffer->port_buffer_size - total_used;
 
@@ -88,9 +89,9 @@ out:
 static int port_set_buffer(struct mlx5e_priv *priv,
                           struct mlx5e_port_buffer *port_buffer)
 {
+       u16 port_buff_cell_sz = priv->dcbx.port_buff_cell_sz;
        struct mlx5_core_dev *mdev = priv->mdev;
        int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
-       void *buffer;
        void *in;
        int err;
        int i;
@@ -104,16 +105,18 @@ static int port_set_buffer(struct mlx5e_priv *priv,
                goto out;
 
        for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
-               buffer = MLX5_ADDR_OF(pbmc_reg, in, buffer[i]);
-
-               MLX5_SET(bufferx_reg, buffer, size,
-                        port_buffer->buffer[i].size >> MLX5E_BUFFER_CELL_SHIFT);
-               MLX5_SET(bufferx_reg, buffer, lossy,
-                        port_buffer->buffer[i].lossy);
-               MLX5_SET(bufferx_reg, buffer, xoff_threshold,
-                        port_buffer->buffer[i].xoff >> MLX5E_BUFFER_CELL_SHIFT);
-               MLX5_SET(bufferx_reg, buffer, xon_threshold,
-                        port_buffer->buffer[i].xon >> MLX5E_BUFFER_CELL_SHIFT);
+               void *buffer = MLX5_ADDR_OF(pbmc_reg, in, buffer[i]);
+               u64 size = port_buffer->buffer[i].size;
+               u64 xoff = port_buffer->buffer[i].xoff;
+               u64 xon = port_buffer->buffer[i].xon;
+
+               do_div(size, port_buff_cell_sz);
+               do_div(xoff, port_buff_cell_sz);
+               do_div(xon, port_buff_cell_sz);
+               MLX5_SET(bufferx_reg, buffer, size, size);
+               MLX5_SET(bufferx_reg, buffer, lossy, port_buffer->buffer[i].lossy);
+               MLX5_SET(bufferx_reg, buffer, xoff_threshold, xoff);
+               MLX5_SET(bufferx_reg, buffer, xon_threshold, xon);
        }
 
        err = mlx5e_port_set_pbmc(mdev, in);
@@ -143,7 +146,7 @@ static u32 calculate_xoff(struct mlx5e_priv *priv, unsigned int mtu)
 }
 
 static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer,
-                                u32 xoff, unsigned int max_mtu)
+                                u32 xoff, unsigned int max_mtu, u16 port_buff_cell_sz)
 {
        int i;
 
@@ -155,7 +158,7 @@ static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer,
                }
 
                if (port_buffer->buffer[i].size <
-                   (xoff + max_mtu + (1 << MLX5E_BUFFER_CELL_SHIFT))) {
+                   (xoff + max_mtu + port_buff_cell_sz)) {
                        pr_err("buffer_size[%d]=%d is not enough for lossless buffer\n",
                               i, port_buffer->buffer[i].size);
                        return -ENOMEM;
@@ -175,6 +178,7 @@ static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer,
  *     @pfc_en: <input> current pfc configuration
  *     @buffer: <input> current prio to buffer mapping
  *     @xoff:   <input> xoff value
+ *     @port_buff_cell_sz: <input> port buffer cell_size
  *     @port_buffer: <output> port receive buffer configuration
  *     @change: <output>
  *
@@ -189,7 +193,7 @@ static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer,
  *     sets change to true if buffer configuration was modified.
  */
 static int update_buffer_lossy(unsigned int max_mtu,
-                              u8 pfc_en, u8 *buffer, u32 xoff,
+                              u8 pfc_en, u8 *buffer, u32 xoff, u16 port_buff_cell_sz,
                               struct mlx5e_port_buffer *port_buffer,
                               bool *change)
 {
@@ -225,7 +229,7 @@ static int update_buffer_lossy(unsigned int max_mtu,
        }
 
        if (changed) {
-               err = update_xoff_threshold(port_buffer, xoff, max_mtu);
+               err = update_xoff_threshold(port_buffer, xoff, max_mtu, port_buff_cell_sz);
                if (err)
                        return err;
 
@@ -262,6 +266,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
                                    u32 *buffer_size,
                                    u8 *prio2buffer)
 {
+       u16 port_buff_cell_sz = priv->dcbx.port_buff_cell_sz;
        struct mlx5e_port_buffer port_buffer;
        u32 xoff = calculate_xoff(priv, mtu);
        bool update_prio2buffer = false;
@@ -282,7 +287,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
 
        if (change & MLX5E_PORT_BUFFER_CABLE_LEN) {
                update_buffer = true;
-               err = update_xoff_threshold(&port_buffer, xoff, max_mtu);
+               err = update_xoff_threshold(&port_buffer, xoff, max_mtu, port_buff_cell_sz);
                if (err)
                        return err;
        }
@@ -292,7 +297,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
                if (err)
                        return err;
 
-               err = update_buffer_lossy(max_mtu, pfc->pfc_en, buffer, xoff,
+               err = update_buffer_lossy(max_mtu, pfc->pfc_en, buffer, xoff, port_buff_cell_sz,
                                          &port_buffer, &update_buffer);
                if (err)
                        return err;
@@ -304,7 +309,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
                if (err)
                        return err;
 
-               err = update_buffer_lossy(max_mtu, curr_pfc_en, prio2buffer,
+               err = update_buffer_lossy(max_mtu, curr_pfc_en, prio2buffer, port_buff_cell_sz,
                                          xoff, &port_buffer, &update_buffer);
                if (err)
                        return err;
@@ -329,7 +334,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
                        return -EINVAL;
 
                update_buffer = true;
-               err = update_xoff_threshold(&port_buffer, xoff, max_mtu);
+               err = update_xoff_threshold(&port_buffer, xoff, max_mtu, port_buff_cell_sz);
                if (err)
                        return err;
        }
@@ -337,7 +342,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
        /* Need to update buffer configuration if xoff value is changed */
        if (!update_buffer && xoff != priv->dcbx.xoff) {
                update_buffer = true;
-               err = update_xoff_threshold(&port_buffer, xoff, max_mtu);
+               err = update_xoff_threshold(&port_buffer, xoff, max_mtu, port_buff_cell_sz);
                if (err)
                        return err;
        }
index 34f55b8..80af7a5 100644 (file)
@@ -36,7 +36,6 @@
 #include "port.h"
 
 #define MLX5E_MAX_BUFFER 8
-#define MLX5E_BUFFER_CELL_SHIFT 7
 #define MLX5E_DEFAULT_CABLE_LEN 7 /* 7 meters */
 
 #define MLX5_BUFFER_SUPPORTED(mdev) (MLX5_CAP_GEN(mdev, pcam_reg) && \
index baa1624..c3d167f 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/rculist.h>
 #include <linux/rtnetlink.h>
 #include <linux/workqueue.h>
-#include <linux/rwlock.h>
 #include <linux/spinlock.h>
 #include <linux/notifier.h>
 #include <net/netevent.h>
index 8071312..eefeb1c 100644 (file)
@@ -407,7 +407,9 @@ static int
 mlx5e_rep_indr_setup_block(struct net_device *netdev,
                           struct mlx5e_rep_priv *rpriv,
                           struct flow_block_offload *f,
-                          flow_setup_cb_t *setup_cb)
+                          flow_setup_cb_t *setup_cb,
+                          void *data,
+                          void (*cleanup)(struct flow_block_cb *block_cb))
 {
        struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
        struct mlx5e_rep_indr_block_priv *indr_priv;
@@ -438,8 +440,10 @@ mlx5e_rep_indr_setup_block(struct net_device *netdev,
                list_add(&indr_priv->list,
                         &rpriv->uplink_priv.tc_indr_block_priv_list);
 
-               block_cb = flow_block_cb_alloc(setup_cb, indr_priv, indr_priv,
-                                              mlx5e_rep_indr_block_unbind);
+               block_cb = flow_indr_block_cb_alloc(setup_cb, indr_priv, indr_priv,
+                                                   mlx5e_rep_indr_block_unbind,
+                                                   f, netdev, data, rpriv,
+                                                   cleanup);
                if (IS_ERR(block_cb)) {
                        list_del(&indr_priv->list);
                        kfree(indr_priv);
@@ -458,7 +462,7 @@ mlx5e_rep_indr_setup_block(struct net_device *netdev,
                if (!block_cb)
                        return -ENOENT;
 
-               flow_block_cb_remove(block_cb, f);
+               flow_indr_block_cb_remove(block_cb, f);
                list_del(&block_cb->driver_list);
                return 0;
        default:
@@ -469,15 +473,19 @@ mlx5e_rep_indr_setup_block(struct net_device *netdev,
 
 static
 int mlx5e_rep_indr_setup_cb(struct net_device *netdev, void *cb_priv,
-                           enum tc_setup_type type, void *type_data)
+                           enum tc_setup_type type, void *type_data,
+                           void *data,
+                           void (*cleanup)(struct flow_block_cb *block_cb))
 {
        switch (type) {
        case TC_SETUP_BLOCK:
                return mlx5e_rep_indr_setup_block(netdev, cb_priv, type_data,
-                                                 mlx5e_rep_indr_setup_tc_cb);
+                                                 mlx5e_rep_indr_setup_tc_cb,
+                                                 data, cleanup);
        case TC_SETUP_FT:
                return mlx5e_rep_indr_setup_block(netdev, cb_priv, type_data,
-                                                 mlx5e_rep_indr_setup_ft_cb);
+                                                 mlx5e_rep_indr_setup_ft_cb,
+                                                 data, cleanup);
        default:
                return -EOPNOTSUPP;
        }
@@ -496,7 +504,7 @@ int mlx5e_rep_tc_netdevice_event_register(struct mlx5e_rep_priv *rpriv)
 void mlx5e_rep_tc_netdevice_event_unregister(struct mlx5e_rep_priv *rpriv)
 {
        flow_indr_dev_unregister(mlx5e_rep_indr_setup_cb, rpriv,
-                                mlx5e_rep_indr_setup_tc_cb);
+                                mlx5e_rep_indr_block_unbind);
 }
 
 #if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
index 4300255..aad1c29 100644 (file)
@@ -1097,6 +1097,7 @@ mlx5_tc_ct_flush_ft_entry(void *ptr, void *arg)
        struct mlx5_ct_entry *entry = ptr;
 
        mlx5_tc_ct_entry_del_rules(ct_priv, entry);
+       kfree(entry);
 }
 
 static void
index bc102d0..d20243d 100644 (file)
@@ -1217,6 +1217,24 @@ static int mlx5e_trust_initialize(struct mlx5e_priv *priv)
        return 0;
 }
 
+#define MLX5E_BUFFER_CELL_SHIFT 7
+
+static u16 mlx5e_query_port_buffers_cell_size(struct mlx5e_priv *priv)
+{
+       struct mlx5_core_dev *mdev = priv->mdev;
+       u32 out[MLX5_ST_SZ_DW(sbcam_reg)] = {};
+       u32 in[MLX5_ST_SZ_DW(sbcam_reg)] = {};
+
+       if (!MLX5_CAP_GEN(mdev, sbcam_reg))
+               return (1 << MLX5E_BUFFER_CELL_SHIFT);
+
+       if (mlx5_core_access_reg(mdev, in, sizeof(in), out, sizeof(out),
+                                MLX5_REG_SBCAM, 0, 0))
+               return (1 << MLX5E_BUFFER_CELL_SHIFT);
+
+       return MLX5_GET(sbcam_reg, out, cap_cell_size);
+}
+
 void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv)
 {
        struct mlx5e_dcbx *dcbx = &priv->dcbx;
@@ -1234,6 +1252,7 @@ void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv)
        if (priv->dcbx.mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
                priv->dcbx.cap |= DCB_CAP_DCBX_HOST;
 
+       priv->dcbx.port_buff_cell_sz = mlx5e_query_port_buffers_cell_size(priv);
        priv->dcbx.manual_buffer = false;
        priv->dcbx.cable_len = MLX5E_DEFAULT_CABLE_LEN;
 
index ec5658b..c2464c3 100644 (file)
@@ -200,7 +200,7 @@ static void mlx5e_ethtool_get_speed_arr(struct mlx5_core_dev *mdev,
                                        struct ptys2ethtool_config **arr,
                                        u32 *size)
 {
-       bool ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+       bool ext = mlx5e_ptys_ext_supported(mdev);
 
        *arr = ext ? ptys2ext_ethtool_table : ptys2legacy_ethtool_table;
        *size = ext ? ARRAY_SIZE(ptys2ext_ethtool_table) :
@@ -883,7 +883,7 @@ static void get_lp_advertising(struct mlx5_core_dev *mdev, u32 eth_proto_lp,
                               struct ethtool_link_ksettings *link_ksettings)
 {
        unsigned long *lp_advertising = link_ksettings->link_modes.lp_advertising;
-       bool ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+       bool ext = mlx5e_ptys_ext_supported(mdev);
 
        ptys2ethtool_adver_link(lp_advertising, eth_proto_lp, ext);
 }
@@ -913,7 +913,7 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
                           __func__, err);
                goto err_query_regs;
        }
-       ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+       ext = !!MLX5_GET_ETH_PROTO(ptys_reg, out, true, eth_proto_capability);
        eth_proto_cap    = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
                                              eth_proto_capability);
        eth_proto_admin  = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
@@ -1066,7 +1066,7 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
        autoneg = link_ksettings->base.autoneg;
        speed = link_ksettings->base.speed;
 
-       ext_supported = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+       ext_supported = mlx5e_ptys_ext_supported(mdev);
        ext = ext_requested(autoneg, adver, ext_supported);
        if (!ext_supported && ext)
                return -EOPNOTSUPP;
index a836a02..081f150 100644 (file)
@@ -3104,9 +3104,6 @@ int mlx5e_open(struct net_device *netdev)
                mlx5_set_port_admin_status(priv->mdev, MLX5_PORT_UP);
        mutex_unlock(&priv->state_lock);
 
-       if (mlx5_vxlan_allowed(priv->mdev->vxlan))
-               udp_tunnel_get_rx_info(netdev);
-
        return err;
 }
 
@@ -5121,6 +5118,10 @@ static int mlx5e_init_nic_rx(struct mlx5e_priv *priv)
        if (err)
                goto err_destroy_flow_steering;
 
+#ifdef CONFIG_MLX5_EN_ARFS
+       priv->netdev->rx_cpu_rmap =  mlx5_eq_table_get_rmap(priv->mdev);
+#endif
+
        return 0;
 
 err_destroy_flow_steering:
@@ -5202,6 +5203,8 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
        rtnl_lock();
        if (netif_running(netdev))
                mlx5e_open(netdev);
+       if (mlx5_vxlan_allowed(priv->mdev->vxlan))
+               udp_tunnel_get_rx_info(netdev);
        netif_device_attach(netdev);
        rtnl_unlock();
 }
@@ -5216,6 +5219,8 @@ static void mlx5e_nic_disable(struct mlx5e_priv *priv)
        rtnl_lock();
        if (netif_running(priv->netdev))
                mlx5e_close(priv->netdev);
+       if (mlx5_vxlan_allowed(priv->mdev->vxlan))
+               udp_tunnel_drop_rx_info(priv->netdev);
        netif_device_detach(priv->netdev);
        rtnl_unlock();
 
@@ -5288,10 +5293,6 @@ int mlx5e_netdev_init(struct net_device *netdev,
        /* netdev init */
        netif_carrier_off(netdev);
 
-#ifdef CONFIG_MLX5_EN_ARFS
-       netdev->rx_cpu_rmap =  mlx5_eq_table_get_rmap(mdev);
-#endif
-
        return 0;
 
 err_free_cpumask:
index 7fc84f5..cc84121 100644 (file)
@@ -4670,9 +4670,10 @@ static bool is_flow_rule_duplicate_allowed(struct net_device *dev,
                                           struct mlx5e_rep_priv *rpriv)
 {
        /* Offloaded flow rule is allowed to duplicate on non-uplink representor
-        * sharing tc block with other slaves of a lag device.
+        * sharing tc block with other slaves of a lag device. Rpriv can be NULL if this
+        * function is called from NIC mode.
         */
-       return netif_is_lag_port(dev) && rpriv->rep->vport != MLX5_VPORT_UPLINK;
+       return netif_is_lag_port(dev) && rpriv && rpriv->rep->vport != MLX5_VPORT_UPLINK;
 }
 
 int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv,
@@ -4686,13 +4687,12 @@ int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv,
 
        rcu_read_lock();
        flow = rhashtable_lookup(tc_ht, &f->cookie, tc_ht_params);
-       rcu_read_unlock();
        if (flow) {
                /* Same flow rule offloaded to non-uplink representor sharing tc block,
                 * just return 0.
                 */
                if (is_flow_rule_duplicate_allowed(dev, rpriv) && flow->orig_dev != dev)
-                       goto out;
+                       goto rcu_unlock;
 
                NL_SET_ERR_MSG_MOD(extack,
                                   "flow cookie already exists, ignoring");
@@ -4700,8 +4700,12 @@ int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv,
                                 "flow cookie %lx already exists, ignoring\n",
                                 f->cookie);
                err = -EEXIST;
-               goto out;
+               goto rcu_unlock;
        }
+rcu_unlock:
+       rcu_read_unlock();
+       if (flow)
+               goto out;
 
        trace_mlx5e_configure_flower(f);
        err = mlx5e_tc_add_flow(priv, f, flags, dev, &flow);
index 5dc335e..b68976b 100644 (file)
@@ -217,7 +217,6 @@ int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw,
        }
 
        /* Create ingress allow rule */
-       memset(spec, 0, sizeof(*spec));
        spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
        flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
        vport->ingress.allow_rule = mlx5_add_flow_rules(vport->ingress.acl, spec,
index 9f829e6..e4186e8 100644 (file)
@@ -293,7 +293,40 @@ static int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num)
        return 0;
 }
 
-static int mlx5_eeprom_page(int offset)
+static int mlx5_query_module_id(struct mlx5_core_dev *dev, int module_num,
+                               u8 *module_id)
+{
+       u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {};
+       u32 out[MLX5_ST_SZ_DW(mcia_reg)];
+       int err, status;
+       u8 *ptr;
+
+       MLX5_SET(mcia_reg, in, i2c_device_address, MLX5_I2C_ADDR_LOW);
+       MLX5_SET(mcia_reg, in, module, module_num);
+       MLX5_SET(mcia_reg, in, device_address, 0);
+       MLX5_SET(mcia_reg, in, page_number, 0);
+       MLX5_SET(mcia_reg, in, size, 1);
+       MLX5_SET(mcia_reg, in, l, 0);
+
+       err = mlx5_core_access_reg(dev, in, sizeof(in), out,
+                                  sizeof(out), MLX5_REG_MCIA, 0, 0);
+       if (err)
+               return err;
+
+       status = MLX5_GET(mcia_reg, out, status);
+       if (status) {
+               mlx5_core_err(dev, "query_mcia_reg failed: status: 0x%x\n",
+                             status);
+               return -EIO;
+       }
+       ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
+
+       *module_id = ptr[0];
+
+       return 0;
+}
+
+static int mlx5_qsfp_eeprom_page(u16 offset)
 {
        if (offset < MLX5_EEPROM_PAGE_LENGTH)
                /* Addresses between 0-255 - page 00 */
@@ -307,7 +340,7 @@ static int mlx5_eeprom_page(int offset)
                    MLX5_EEPROM_HIGH_PAGE_LENGTH);
 }
 
-static int mlx5_eeprom_high_page_offset(int page_num)
+static int mlx5_qsfp_eeprom_high_page_offset(int page_num)
 {
        if (!page_num) /* Page 0 always start from low page */
                return 0;
@@ -316,35 +349,62 @@ static int mlx5_eeprom_high_page_offset(int page_num)
        return page_num * MLX5_EEPROM_HIGH_PAGE_LENGTH;
 }
 
+static void mlx5_qsfp_eeprom_params_set(u16 *i2c_addr, int *page_num, u16 *offset)
+{
+       *i2c_addr = MLX5_I2C_ADDR_LOW;
+       *page_num = mlx5_qsfp_eeprom_page(*offset);
+       *offset -=  mlx5_qsfp_eeprom_high_page_offset(*page_num);
+}
+
+static void mlx5_sfp_eeprom_params_set(u16 *i2c_addr, int *page_num, u16 *offset)
+{
+       *i2c_addr = MLX5_I2C_ADDR_LOW;
+       *page_num = 0;
+
+       if (*offset < MLX5_EEPROM_PAGE_LENGTH)
+               return;
+
+       *i2c_addr = MLX5_I2C_ADDR_HIGH;
+       *offset -= MLX5_EEPROM_PAGE_LENGTH;
+}
+
 int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
                             u16 offset, u16 size, u8 *data)
 {
-       int module_num, page_num, status, err;
+       int module_num, status, err, page_num = 0;
+       u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {};
        u32 out[MLX5_ST_SZ_DW(mcia_reg)];
-       u32 in[MLX5_ST_SZ_DW(mcia_reg)];
-       u16 i2c_addr;
-       void *ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
+       u16 i2c_addr = 0;
+       u8 module_id;
+       void *ptr;
 
        err = mlx5_query_module_num(dev, &module_num);
        if (err)
                return err;
 
-       memset(in, 0, sizeof(in));
-       size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
-
-       /* Get the page number related to the given offset */
-       page_num = mlx5_eeprom_page(offset);
+       err = mlx5_query_module_id(dev, module_num, &module_id);
+       if (err)
+               return err;
 
-       /* Set the right offset according to the page number,
-        * For page_num > 0, relative offset is always >= 128 (high page).
-        */
-       offset -= mlx5_eeprom_high_page_offset(page_num);
+       switch (module_id) {
+       case MLX5_MODULE_ID_SFP:
+               mlx5_sfp_eeprom_params_set(&i2c_addr, &page_num, &offset);
+               break;
+       case MLX5_MODULE_ID_QSFP:
+       case MLX5_MODULE_ID_QSFP_PLUS:
+       case MLX5_MODULE_ID_QSFP28:
+               mlx5_qsfp_eeprom_params_set(&i2c_addr, &page_num, &offset);
+               break;
+       default:
+               mlx5_core_err(dev, "Module ID not recognized: 0x%x\n", module_id);
+               return -EINVAL;
+       }
 
        if (offset + size > MLX5_EEPROM_PAGE_LENGTH)
                /* Cross pages read, read until offset 256 in low page */
                size -= offset + size - MLX5_EEPROM_PAGE_LENGTH;
 
-       i2c_addr = MLX5_I2C_ADDR_LOW;
+       size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
 
        MLX5_SET(mcia_reg, in, l, 0);
        MLX5_SET(mcia_reg, in, module, module_num);
@@ -365,6 +425,7 @@ int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
                return -EIO;
        }
 
+       ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
        memcpy(data, ptr, size);
 
        return size;
index e9ccd33..d6d6fe6 100644 (file)
@@ -710,7 +710,7 @@ static int mlxsw_emad_init(struct mlxsw_core *mlxsw_core)
        err = mlxsw_core_trap_register(mlxsw_core, &mlxsw_emad_rx_listener,
                                       mlxsw_core);
        if (err)
-               return err;
+               goto err_trap_register;
 
        err = mlxsw_core->driver->basic_trap_groups_set(mlxsw_core);
        if (err)
@@ -722,6 +722,7 @@ static int mlxsw_emad_init(struct mlxsw_core *mlxsw_core)
 err_emad_trap_set:
        mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_emad_rx_listener,
                                   mlxsw_core);
+err_trap_register:
        destroy_workqueue(mlxsw_core->emad_wq);
        return err;
 }
index 08215fe..a7d86df 100644 (file)
@@ -45,7 +45,7 @@ static int mlxsw_env_validate_cable_ident(struct mlxsw_core *core, int id,
 static int
 mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module,
                              u16 offset, u16 size, void *data,
-                             unsigned int *p_read_size)
+                             bool qsfp, unsigned int *p_read_size)
 {
        char eeprom_tmp[MLXSW_REG_MCIA_EEPROM_SIZE];
        char mcia_pl[MLXSW_REG_MCIA_LEN];
@@ -54,6 +54,10 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module,
        int status;
        int err;
 
+       /* MCIA register accepts buffer size <= 48. Page of size 128 should be
+        * read by chunks of size 48, 48, 32. Align the size of the last chunk
+        * to avoid reading after the end of the page.
+        */
        size = min_t(u16, size, MLXSW_REG_MCIA_EEPROM_SIZE);
 
        if (offset < MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH &&
@@ -63,18 +67,25 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module,
 
        i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_LOW;
        if (offset >= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) {
-               page = MLXSW_REG_MCIA_PAGE_GET(offset);
-               offset -= MLXSW_REG_MCIA_EEPROM_UP_PAGE_LENGTH * page;
-               /* When reading upper pages 1, 2 and 3 the offset starts at
-                * 128. Please refer to "QSFP+ Memory Map" figure in SFF-8436
-                * specification for graphical depiction.
-                * MCIA register accepts buffer size <= 48. Page of size 128
-                * should be read by chunks of size 48, 48, 32. Align the size
-                * of the last chunk to avoid reading after the end of the
-                * page.
-                */
-               if (offset + size > MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH)
-                       size = MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH - offset;
+               if (qsfp) {
+                       /* When reading upper pages 1, 2 and 3 the offset
+                        * starts at 128. Please refer to "QSFP+ Memory Map"
+                        * figure in SFF-8436 specification for graphical
+                        * depiction.
+                        */
+                       page = MLXSW_REG_MCIA_PAGE_GET(offset);
+                       offset -= MLXSW_REG_MCIA_EEPROM_UP_PAGE_LENGTH * page;
+                       if (offset + size > MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH)
+                               size = MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH - offset;
+               } else {
+                       /* When reading upper pages 1, 2 and 3 the offset
+                        * starts at 0 and I2C high address is used. Please refer
+                        * refer to "Memory Organization" figure in SFF-8472
+                        * specification for graphical depiction.
+                        */
+                       i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_HIGH;
+                       offset -= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH;
+               }
        }
 
        mlxsw_reg_mcia_pack(mcia_pl, module, 0, page, offset, size, i2c_addr);
@@ -166,7 +177,7 @@ int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module,
        int err;
 
        err = mlxsw_env_query_module_eeprom(mlxsw_core, module, 0, offset,
-                                           module_info, &read_size);
+                                           module_info, false, &read_size);
        if (err)
                return err;
 
@@ -197,7 +208,7 @@ int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module,
                /* Verify if transceiver provides diagnostic monitoring page */
                err = mlxsw_env_query_module_eeprom(mlxsw_core, module,
                                                    SFP_DIAGMON, 1, &diag_mon,
-                                                   &read_size);
+                                                   false, &read_size);
                if (err)
                        return err;
 
@@ -225,17 +236,22 @@ int mlxsw_env_get_module_eeprom(struct net_device *netdev,
        int offset = ee->offset;
        unsigned int read_size;
        int i = 0;
+       bool qsfp;
        int err;
 
        if (!ee->len)
                return -EINVAL;
 
        memset(data, 0, ee->len);
+       /* Validate module identifier value. */
+       err = mlxsw_env_validate_cable_ident(mlxsw_core, module, &qsfp);
+       if (err)
+               return err;
 
        while (i < ee->len) {
                err = mlxsw_env_query_module_eeprom(mlxsw_core, module, offset,
                                                    ee->len - i, data + i,
-                                                   &read_size);
+                                                   qsfp, &read_size);
                if (err) {
                        netdev_err(netdev, "Eeprom query failed\n");
                        return err;
index fd0e97d..c04ec1a 100644 (file)
@@ -1414,23 +1414,12 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
        u16 num_pages;
        int err;
 
-       mutex_init(&mlxsw_pci->cmd.lock);
-       init_waitqueue_head(&mlxsw_pci->cmd.wait);
-
        mlxsw_pci->core = mlxsw_core;
 
        mbox = mlxsw_cmd_mbox_alloc();
        if (!mbox)
                return -ENOMEM;
 
-       err = mlxsw_pci_mbox_alloc(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
-       if (err)
-               goto mbox_put;
-
-       err = mlxsw_pci_mbox_alloc(mlxsw_pci, &mlxsw_pci->cmd.out_mbox);
-       if (err)
-               goto err_out_mbox_alloc;
-
        err = mlxsw_pci_sw_reset(mlxsw_pci, mlxsw_pci->id);
        if (err)
                goto err_sw_reset;
@@ -1537,9 +1526,6 @@ err_query_fw:
        mlxsw_pci_free_irq_vectors(mlxsw_pci);
 err_alloc_irq:
 err_sw_reset:
-       mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.out_mbox);
-err_out_mbox_alloc:
-       mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
 mbox_put:
        mlxsw_cmd_mbox_free(mbox);
        return err;
@@ -1553,8 +1539,6 @@ static void mlxsw_pci_fini(void *bus_priv)
        mlxsw_pci_aqs_fini(mlxsw_pci);
        mlxsw_pci_fw_area_fini(mlxsw_pci);
        mlxsw_pci_free_irq_vectors(mlxsw_pci);
-       mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.out_mbox);
-       mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
 }
 
 static struct mlxsw_pci_queue *
@@ -1776,6 +1760,37 @@ static const struct mlxsw_bus mlxsw_pci_bus = {
        .features               = MLXSW_BUS_F_TXRX | MLXSW_BUS_F_RESET,
 };
 
+static int mlxsw_pci_cmd_init(struct mlxsw_pci *mlxsw_pci)
+{
+       int err;
+
+       mutex_init(&mlxsw_pci->cmd.lock);
+       init_waitqueue_head(&mlxsw_pci->cmd.wait);
+
+       err = mlxsw_pci_mbox_alloc(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
+       if (err)
+               goto err_in_mbox_alloc;
+
+       err = mlxsw_pci_mbox_alloc(mlxsw_pci, &mlxsw_pci->cmd.out_mbox);
+       if (err)
+               goto err_out_mbox_alloc;
+
+       return 0;
+
+err_out_mbox_alloc:
+       mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
+err_in_mbox_alloc:
+       mutex_destroy(&mlxsw_pci->cmd.lock);
+       return err;
+}
+
+static void mlxsw_pci_cmd_fini(struct mlxsw_pci *mlxsw_pci)
+{
+       mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.out_mbox);
+       mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
+       mutex_destroy(&mlxsw_pci->cmd.lock);
+}
+
 static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        const char *driver_name = pdev->driver->name;
@@ -1831,6 +1846,10 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        mlxsw_pci->pdev = pdev;
        pci_set_drvdata(pdev, mlxsw_pci);
 
+       err = mlxsw_pci_cmd_init(mlxsw_pci);
+       if (err)
+               goto err_pci_cmd_init;
+
        mlxsw_pci->bus_info.device_kind = driver_name;
        mlxsw_pci->bus_info.device_name = pci_name(mlxsw_pci->pdev);
        mlxsw_pci->bus_info.dev = &pdev->dev;
@@ -1848,6 +1867,8 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        return 0;
 
 err_bus_device_register:
+       mlxsw_pci_cmd_fini(mlxsw_pci);
+err_pci_cmd_init:
        iounmap(mlxsw_pci->hw_addr);
 err_ioremap:
 err_pci_resource_len_check:
@@ -1865,6 +1886,7 @@ static void mlxsw_pci_remove(struct pci_dev *pdev)
        struct mlxsw_pci *mlxsw_pci = pci_get_drvdata(pdev);
 
        mlxsw_core_bus_device_unregister(mlxsw_pci->core, false);
+       mlxsw_pci_cmd_fini(mlxsw_pci);
        iounmap(mlxsw_pci->hw_addr);
        pci_release_regions(mlxsw_pci->pdev);
        pci_disable_device(mlxsw_pci->pdev);
index 5ffa32b..029ea34 100644 (file)
@@ -978,8 +978,10 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu,
 
                lossy = !(pfc || pause_en);
                thres_cells = mlxsw_sp_pg_buf_threshold_get(mlxsw_sp, mtu);
+               thres_cells = mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, thres_cells);
                delay_cells = mlxsw_sp_pg_buf_delay_get(mlxsw_sp, mtu, delay,
                                                        pfc, pause_en);
+               delay_cells = mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, delay_cells);
                total_cells = thres_cells + delay_cells;
 
                taken_headroom_cells += total_cells;
index 6f96ca5..3abe3e7 100644 (file)
@@ -374,6 +374,17 @@ mlxsw_sp_port_vlan_find_by_vid(const struct mlxsw_sp_port *mlxsw_sp_port,
        return NULL;
 }
 
+static inline u32
+mlxsw_sp_port_headroom_8x_adjust(const struct mlxsw_sp_port *mlxsw_sp_port,
+                                u32 size_cells)
+{
+       /* Ports with eight lanes use two headroom buffers between which the
+        * configured headroom size is split. Therefore, multiply the calculated
+        * headroom size by two.
+        */
+       return mlxsw_sp_port->mapping.width == 8 ? 2 * size_cells : size_cells;
+}
+
 enum mlxsw_sp_flood_type {
        MLXSW_SP_FLOOD_TYPE_UC,
        MLXSW_SP_FLOOD_TYPE_BC,
index 21bfb2f..6f84557 100644 (file)
@@ -312,6 +312,7 @@ static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port)
 
                if (i == MLXSW_SP_PB_UNUSED)
                        continue;
+               size = mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, size);
                mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, i, size);
        }
        mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl,
index 770de02..019ed50 100644 (file)
@@ -6262,7 +6262,7 @@ static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
        }
 
        fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC);
-       if (WARN_ON(!fib_work))
+       if (!fib_work)
                return NOTIFY_BAD;
 
        fib_work->mlxsw_sp = router->mlxsw_sp;
index 304eb8c..92351a7 100644 (file)
@@ -782,6 +782,7 @@ mlxsw_sp_span_port_buffer_update(struct mlxsw_sp_port *mlxsw_sp_port, u16 mtu)
                speed = 0;
 
        buffsize = mlxsw_sp_span_buffsize_get(mlxsw_sp, speed, mtu);
+       buffsize = mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, buffsize);
        mlxsw_reg_sbib_pack(sbib_pl, mlxsw_sp_port->local_port, buffsize);
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
 }
index c5c5c68..f1711ac 100644 (file)
@@ -3091,6 +3091,8 @@ static const struct pci_device_id lan743x_pcidev_tbl[] = {
        { 0, }
 };
 
+MODULE_DEVICE_TABLE(pci, lan743x_pcidev_tbl);
+
 static struct pci_driver lan743x_pcidev_driver = {
        .name     = DRIVER_NAME,
        .id_table = lan743x_pcidev_tbl,
index 628fa9b..3731651 100644 (file)
@@ -297,7 +297,7 @@ struct vxge_hw_fifo_config {
  * @greedy_return: If Set it forces the device to return absolutely all RxD
  *             that are consumed and still on board when a timer interrupt
  *             triggers. If Clear, then if the device has already returned
- *             RxD before current timer interrupt trigerred and after the
+ *             RxD before current timer interrupt triggered and after the
  *             previous timer interrupt triggered, then the device is not
  *             forced to returned the rest of the consumed RxD that it has
  *             on board which account for a byte count less than the one
index 9b63574..b5f1849 100644 (file)
@@ -98,7 +98,7 @@ static inline void VXGE_COMPLETE_VPATH_TX(struct vxge_fifo *fifo)
 {
        struct sk_buff **skb_ptr = NULL;
        struct sk_buff **temp;
-#define NR_SKB_COMPLETED 128
+#define NR_SKB_COMPLETED 16
        struct sk_buff *completed[NR_SKB_COMPLETED];
        int more;
 
index c393276..bb448c8 100644 (file)
@@ -861,7 +861,7 @@ static void nfp_flower_clean(struct nfp_app *app)
        flush_work(&app_priv->cmsg_work);
 
        flow_indr_dev_unregister(nfp_flower_indr_setup_tc_cb, app,
-                                nfp_flower_setup_indr_block_cb);
+                                nfp_flower_setup_indr_tc_release);
 
        if (app_priv->flower_ext_feats & NFP_FL_FEATS_VF_RLIM)
                nfp_flower_qos_cleanup(app);
index 6c3dc3b..7f54a62 100644 (file)
@@ -459,9 +459,10 @@ int nfp_flower_setup_qos_offload(struct nfp_app *app, struct net_device *netdev,
                                 struct tc_cls_matchall_offload *flow);
 void nfp_flower_stats_rlim_reply(struct nfp_app *app, struct sk_buff *skb);
 int nfp_flower_indr_setup_tc_cb(struct net_device *netdev, void *cb_priv,
-                               enum tc_setup_type type, void *type_data);
-int nfp_flower_setup_indr_block_cb(enum tc_setup_type type, void *type_data,
-                                  void *cb_priv);
+                               enum tc_setup_type type, void *type_data,
+                               void *data,
+                               void (*cleanup)(struct flow_block_cb *block_cb));
+void nfp_flower_setup_indr_tc_release(void *cb_priv);
 
 void
 __nfp_flower_non_repr_priv_get(struct nfp_flower_non_repr_priv *non_repr_priv);
index 695d24b..d7340dc 100644 (file)
@@ -1619,8 +1619,8 @@ nfp_flower_indr_block_cb_priv_lookup(struct nfp_app *app,
        return NULL;
 }
 
-int nfp_flower_setup_indr_block_cb(enum tc_setup_type type,
-                                  void *type_data, void *cb_priv)
+static int nfp_flower_setup_indr_block_cb(enum tc_setup_type type,
+                                         void *type_data, void *cb_priv)
 {
        struct nfp_flower_indr_block_cb_priv *priv = cb_priv;
        struct flow_cls_offload *flower = type_data;
@@ -1637,7 +1637,7 @@ int nfp_flower_setup_indr_block_cb(enum tc_setup_type type,
        }
 }
 
-static void nfp_flower_setup_indr_tc_release(void *cb_priv)
+void nfp_flower_setup_indr_tc_release(void *cb_priv)
 {
        struct nfp_flower_indr_block_cb_priv *priv = cb_priv;
 
@@ -1647,7 +1647,8 @@ static void nfp_flower_setup_indr_tc_release(void *cb_priv)
 
 static int
 nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
-                              struct flow_block_offload *f)
+                              struct flow_block_offload *f, void *data,
+                              void (*cleanup)(struct flow_block_cb *block_cb))
 {
        struct nfp_flower_indr_block_cb_priv *cb_priv;
        struct nfp_flower_priv *priv = app->priv;
@@ -1676,9 +1677,10 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
                cb_priv->app = app;
                list_add(&cb_priv->list, &priv->indr_block_cb_priv);
 
-               block_cb = flow_block_cb_alloc(nfp_flower_setup_indr_block_cb,
-                                              cb_priv, cb_priv,
-                                              nfp_flower_setup_indr_tc_release);
+               block_cb = flow_indr_block_cb_alloc(nfp_flower_setup_indr_block_cb,
+                                                   cb_priv, cb_priv,
+                                                   nfp_flower_setup_indr_tc_release,
+                                                   f, netdev, data, app, cleanup);
                if (IS_ERR(block_cb)) {
                        list_del(&cb_priv->list);
                        kfree(cb_priv);
@@ -1699,7 +1701,7 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
                if (!block_cb)
                        return -ENOENT;
 
-               flow_block_cb_remove(block_cb, f);
+               flow_indr_block_cb_remove(block_cb, f);
                list_del(&block_cb->driver_list);
                return 0;
        default:
@@ -1710,7 +1712,9 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
 
 int
 nfp_flower_indr_setup_tc_cb(struct net_device *netdev, void *cb_priv,
-                           enum tc_setup_type type, void *type_data)
+                           enum tc_setup_type type, void *type_data,
+                           void *data,
+                           void (*cleanup)(struct flow_block_cb *block_cb))
 {
        if (!nfp_fl_is_netdev_to_offload(netdev))
                return -EOPNOTSUPP;
@@ -1718,7 +1722,7 @@ nfp_flower_indr_setup_tc_cb(struct net_device *netdev, void *cb_priv,
        switch (type) {
        case TC_SETUP_BLOCK:
                return nfp_flower_setup_indr_tc_block(netdev, cb_priv,
-                                                     type_data);
+                                                     type_data, data, cleanup);
        default:
                return -EOPNOTSUPP;
        }
index 32b9d77..55cef5b 100644 (file)
@@ -147,7 +147,7 @@ struct pch_gbe_regs {
 #define PCH_GBE_RH_ALM_FULL_8   0x00001000      /* 8 words */
 #define PCH_GBE_RH_ALM_FULL_16  0x00002000      /* 16 words */
 #define PCH_GBE_RH_ALM_FULL_32  0x00003000      /* 32 words */
-/* RX FIFO Read Triger Threshold */
+/* RX FIFO Read Trigger Threshold */
 #define PCH_GBE_RH_RD_TRG_4     0x00000000      /* 4 words */
 #define PCH_GBE_RH_RD_TRG_8     0x00000200      /* 8 words */
 #define PCH_GBE_RH_RD_TRG_16    0x00000400      /* 16 words */
index f7e3ce3..0955619 100644 (file)
@@ -103,15 +103,18 @@ static void ionic_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
                           void *p)
 {
        struct ionic_lif *lif = netdev_priv(netdev);
+       unsigned int offset;
        unsigned int size;
 
        regs->version = IONIC_DEV_CMD_REG_VERSION;
 
+       offset = 0;
        size = IONIC_DEV_INFO_REG_COUNT * sizeof(u32);
-       memcpy_fromio(p, lif->ionic->idev.dev_info_regs->words, size);
+       memcpy_fromio(p + offset, lif->ionic->idev.dev_info_regs->words, size);
 
+       offset += size;
        size = IONIC_DEV_CMD_REG_COUNT * sizeof(u32);
-       memcpy_fromio(p, lif->ionic->idev.dev_cmd_regs->words, size);
+       memcpy_fromio(p + offset, lif->ionic->idev.dev_cmd_regs->words, size);
 }
 
 static int ionic_get_link_ksettings(struct net_device *netdev,
@@ -468,12 +471,18 @@ static void ionic_get_ringparam(struct net_device *netdev,
        ring->rx_pending = lif->nrxq_descs;
 }
 
+static void ionic_set_ringsize(struct ionic_lif *lif, void *arg)
+{
+       struct ethtool_ringparam *ring = arg;
+
+       lif->ntxq_descs = ring->tx_pending;
+       lif->nrxq_descs = ring->rx_pending;
+}
+
 static int ionic_set_ringparam(struct net_device *netdev,
                               struct ethtool_ringparam *ring)
 {
        struct ionic_lif *lif = netdev_priv(netdev);
-       bool running;
-       int err;
 
        if (ring->rx_mini_pending || ring->rx_jumbo_pending) {
                netdev_info(netdev, "Changing jumbo or mini descriptors not supported\n");
@@ -491,22 +500,7 @@ static int ionic_set_ringparam(struct net_device *netdev,
            ring->rx_pending == lif->nrxq_descs)
                return 0;
 
-       err = ionic_wait_for_bit(lif, IONIC_LIF_F_QUEUE_RESET);
-       if (err)
-               return err;
-
-       running = test_bit(IONIC_LIF_F_UP, lif->state);
-       if (running)
-               ionic_stop(netdev);
-
-       lif->ntxq_descs = ring->tx_pending;
-       lif->nrxq_descs = ring->rx_pending;
-
-       if (running)
-               ionic_open(netdev);
-       clear_bit(IONIC_LIF_F_QUEUE_RESET, lif->state);
-
-       return 0;
+       return ionic_reset_queues(lif, ionic_set_ringsize, ring);
 }
 
 static void ionic_get_channels(struct net_device *netdev,
@@ -521,12 +515,17 @@ static void ionic_get_channels(struct net_device *netdev,
        ch->combined_count = lif->nxqs;
 }
 
+static void ionic_set_queuecount(struct ionic_lif *lif, void *arg)
+{
+       struct ethtool_channels *ch = arg;
+
+       lif->nxqs = ch->combined_count;
+}
+
 static int ionic_set_channels(struct net_device *netdev,
                              struct ethtool_channels *ch)
 {
        struct ionic_lif *lif = netdev_priv(netdev);
-       bool running;
-       int err;
 
        if (!ch->combined_count || ch->other_count ||
            ch->rx_count || ch->tx_count)
@@ -535,21 +534,7 @@ static int ionic_set_channels(struct net_device *netdev,
        if (ch->combined_count == lif->nxqs)
                return 0;
 
-       err = ionic_wait_for_bit(lif, IONIC_LIF_F_QUEUE_RESET);
-       if (err)
-               return err;
-
-       running = test_bit(IONIC_LIF_F_UP, lif->state);
-       if (running)
-               ionic_stop(netdev);
-
-       lif->nxqs = ch->combined_count;
-
-       if (running)
-               ionic_open(netdev);
-       clear_bit(IONIC_LIF_F_QUEUE_RESET, lif->state);
-
-       return 0;
+       return ionic_reset_queues(lif, ionic_set_queuecount, ch);
 }
 
 static u32 ionic_get_priv_flags(struct net_device *netdev)
index 9d8c969..5fd31ba 100644 (file)
@@ -113,16 +113,22 @@ static void ionic_link_status_check(struct ionic_lif *lif)
                        netif_carrier_on(netdev);
                }
 
-               if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev))
+               if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev)) {
+                       mutex_lock(&lif->queue_lock);
                        ionic_start_queues(lif);
+                       mutex_unlock(&lif->queue_lock);
+               }
        } else {
                if (netif_carrier_ok(netdev)) {
                        netdev_info(netdev, "Link down\n");
                        netif_carrier_off(netdev);
                }
 
-               if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev))
+               if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev)) {
+                       mutex_lock(&lif->queue_lock);
                        ionic_stop_queues(lif);
+                       mutex_unlock(&lif->queue_lock);
+               }
        }
 
        clear_bit(IONIC_LIF_F_LINK_CHECK_REQUESTED, lif->state);
@@ -862,8 +868,7 @@ static int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr)
        if (f)
                return 0;
 
-       netdev_dbg(lif->netdev, "rx_filter add ADDR %pM (id %d)\n", addr,
-                  ctx.comp.rx_filter_add.filter_id);
+       netdev_dbg(lif->netdev, "rx_filter add ADDR %pM\n", addr);
 
        memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, ETH_ALEN);
        err = ionic_adminq_post_wait(lif, &ctx);
@@ -892,6 +897,9 @@ static int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr)
                return -ENOENT;
        }
 
+       netdev_dbg(lif->netdev, "rx_filter del ADDR %pM (id %d)\n",
+                  addr, f->filter_id);
+
        ctx.cmd.rx_filter_del.filter_id = cpu_to_le32(f->filter_id);
        ionic_rx_filter_free(lif, f);
        spin_unlock_bh(&lif->rx_filters.lock);
@@ -900,9 +908,6 @@ static int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr)
        if (err && err != -EEXIST)
                return err;
 
-       netdev_dbg(lif->netdev, "rx_filter del ADDR %pM (id %d)\n", addr,
-                  ctx.cmd.rx_filter_del.filter_id);
-
        return 0;
 }
 
@@ -1245,6 +1250,7 @@ static int ionic_init_nic_features(struct ionic_lif *lif)
 
        netdev->hw_features |= netdev->hw_enc_features;
        netdev->features |= netdev->hw_features;
+       netdev->vlan_features |= netdev->features & ~NETIF_F_VLAN_FEATURES;
 
        netdev->priv_flags |= IFF_UNICAST_FLT |
                              IFF_LIVE_ADDR_CHANGE;
@@ -1311,7 +1317,7 @@ static int ionic_change_mtu(struct net_device *netdev, int new_mtu)
                return err;
 
        netdev->mtu = new_mtu;
-       err = ionic_reset_queues(lif);
+       err = ionic_reset_queues(lif, NULL, NULL);
 
        return err;
 }
@@ -1323,7 +1329,7 @@ static void ionic_tx_timeout_work(struct work_struct *ws)
        netdev_info(lif->netdev, "Tx Timeout recovery\n");
 
        rtnl_lock();
-       ionic_reset_queues(lif);
+       ionic_reset_queues(lif, NULL, NULL);
        rtnl_unlock();
 }
 
@@ -1349,13 +1355,11 @@ static int ionic_vlan_rx_add_vid(struct net_device *netdev, __be16 proto,
        };
        int err;
 
+       netdev_dbg(netdev, "rx_filter add VLAN %d\n", vid);
        err = ionic_adminq_post_wait(lif, &ctx);
        if (err)
                return err;
 
-       netdev_dbg(netdev, "rx_filter add VLAN %d (id %d)\n", vid,
-                  ctx.comp.rx_filter_add.filter_id);
-
        return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, 0, &ctx);
 }
 
@@ -1380,8 +1384,8 @@ static int ionic_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto,
                return -ENOENT;
        }
 
-       netdev_dbg(netdev, "rx_filter del VLAN %d (id %d)\n", vid,
-                  le32_to_cpu(ctx.cmd.rx_filter_del.filter_id));
+       netdev_dbg(netdev, "rx_filter del VLAN %d (id %d)\n",
+                  vid, f->filter_id);
 
        ctx.cmd.rx_filter_del.filter_id = cpu_to_le32(f->filter_id);
        ionic_rx_filter_free(lif, f);
@@ -1671,6 +1675,14 @@ int ionic_open(struct net_device *netdev)
        if (err)
                goto err_out;
 
+       err = netif_set_real_num_tx_queues(netdev, lif->nxqs);
+       if (err)
+               goto err_txrx_deinit;
+
+       err = netif_set_real_num_rx_queues(netdev, lif->nxqs);
+       if (err)
+               goto err_txrx_deinit;
+
        /* don't start the queues until we have link */
        if (netif_carrier_ok(netdev)) {
                err = ionic_start_queues(lif);
@@ -1692,15 +1704,15 @@ static void ionic_stop_queues(struct ionic_lif *lif)
        if (!test_and_clear_bit(IONIC_LIF_F_UP, lif->state))
                return;
 
-       ionic_txrx_disable(lif);
        netif_tx_disable(lif->netdev);
+       ionic_txrx_disable(lif);
 }
 
 int ionic_stop(struct net_device *netdev)
 {
        struct ionic_lif *lif = netdev_priv(netdev);
 
-       if (!netif_device_present(netdev))
+       if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))
                return 0;
 
        ionic_stop_queues(lif);
@@ -1978,25 +1990,28 @@ static const struct net_device_ops ionic_netdev_ops = {
        .ndo_get_vf_stats       = ionic_get_vf_stats,
 };
 
-int ionic_reset_queues(struct ionic_lif *lif)
+int ionic_reset_queues(struct ionic_lif *lif, ionic_reset_cb cb, void *arg)
 {
        bool running;
        int err = 0;
 
-       /* Put off the next watchdog timeout */
-       netif_trans_update(lif->netdev);
-
-       err = ionic_wait_for_bit(lif, IONIC_LIF_F_QUEUE_RESET);
-       if (err)
-               return err;
-
+       mutex_lock(&lif->queue_lock);
        running = netif_running(lif->netdev);
-       if (running)
+       if (running) {
+               netif_device_detach(lif->netdev);
                err = ionic_stop(lif->netdev);
-       if (!err && running)
-               ionic_open(lif->netdev);
+               if (err)
+                       return err;
+       }
+
+       if (cb)
+               cb(lif, arg);
 
-       clear_bit(IONIC_LIF_F_QUEUE_RESET, lif->state);
+       if (running) {
+               err = ionic_open(lif->netdev);
+               netif_device_attach(lif->netdev);
+       }
+       mutex_unlock(&lif->queue_lock);
 
        return err;
 }
@@ -2143,7 +2158,9 @@ static void ionic_lif_handle_fw_down(struct ionic_lif *lif)
 
        if (test_bit(IONIC_LIF_F_UP, lif->state)) {
                dev_info(ionic->dev, "Surprise FW stop, stopping queues\n");
+               mutex_lock(&lif->queue_lock);
                ionic_stop_queues(lif);
+               mutex_unlock(&lif->queue_lock);
        }
 
        if (netif_running(lif->netdev)) {
@@ -2262,15 +2279,15 @@ static void ionic_lif_deinit(struct ionic_lif *lif)
                cancel_work_sync(&lif->deferred.work);
                cancel_work_sync(&lif->tx_timeout_work);
                ionic_rx_filters_deinit(lif);
+               if (lif->netdev->features & NETIF_F_RXHASH)
+                       ionic_lif_rss_deinit(lif);
        }
 
-       if (lif->netdev->features & NETIF_F_RXHASH)
-               ionic_lif_rss_deinit(lif);
-
        napi_disable(&lif->adminqcq->napi);
        ionic_lif_qcq_deinit(lif, lif->notifyqcq);
        ionic_lif_qcq_deinit(lif, lif->adminqcq);
 
+       mutex_destroy(&lif->queue_lock);
        ionic_lif_reset(lif);
 }
 
@@ -2447,6 +2464,7 @@ static int ionic_lif_init(struct ionic_lif *lif)
                return err;
 
        lif->hw_index = le16_to_cpu(comp.hw_index);
+       mutex_init(&lif->queue_lock);
 
        /* now that we have the hw_index we can figure out our doorbell page */
        lif->dbid_count = le32_to_cpu(lif->ionic->ident.dev.ndbpgs_per_lif);
index c342803..8dc2c5d 100644 (file)
@@ -135,7 +135,6 @@ enum ionic_lif_state_flags {
        IONIC_LIF_F_SW_DEBUG_STATS,
        IONIC_LIF_F_UP,
        IONIC_LIF_F_LINK_CHECK_REQUESTED,
-       IONIC_LIF_F_QUEUE_RESET,
        IONIC_LIF_F_FW_RESET,
 
        /* leave this as last */
@@ -165,6 +164,7 @@ struct ionic_lif {
        unsigned int hw_index;
        unsigned int kern_pid;
        u64 __iomem *kern_dbpage;
+       struct mutex queue_lock;        /* lock for queue structures */
        spinlock_t adminq_lock;         /* lock for AdminQ operations */
        struct ionic_qcq *adminqcq;
        struct ionic_qcq *notifyqcq;
@@ -213,12 +213,6 @@ struct ionic_lif {
 #define lif_to_txq(lif, i)     (&lif_to_txqcq((lif), i)->q)
 #define lif_to_rxq(lif, i)     (&lif_to_txqcq((lif), i)->q)
 
-/* return 0 if successfully set the bit, else non-zero */
-static inline int ionic_wait_for_bit(struct ionic_lif *lif, int bitname)
-{
-       return wait_on_bit_lock(lif->state, bitname, TASK_INTERRUPTIBLE);
-}
-
 static inline u32 ionic_coal_usec_to_hw(struct ionic *ionic, u32 usecs)
 {
        u32 mult = le32_to_cpu(ionic->ident.dev.intr_coal_mult);
@@ -248,6 +242,8 @@ static inline u32 ionic_coal_hw_to_usec(struct ionic *ionic, u32 units)
        return (units * div) / mult;
 }
 
+typedef void (*ionic_reset_cb)(struct ionic_lif *lif, void *arg);
+
 void ionic_link_status_check_request(struct ionic_lif *lif);
 void ionic_get_stats64(struct net_device *netdev,
                       struct rtnl_link_stats64 *ns);
@@ -267,7 +263,7 @@ int ionic_lif_rss_config(struct ionic_lif *lif, u16 types,
 
 int ionic_open(struct net_device *netdev);
 int ionic_stop(struct net_device *netdev);
-int ionic_reset_queues(struct ionic_lif *lif);
+int ionic_reset_queues(struct ionic_lif *lif, ionic_reset_cb cb, void *arg);
 
 static inline void debug_stats_txq_post(struct ionic_qcq *qcq,
                                        struct ionic_txq_desc *desc, bool dbell)
index 80eeb76..cd0076f 100644 (file)
@@ -21,13 +21,16 @@ void ionic_rx_filter_free(struct ionic_lif *lif, struct ionic_rx_filter *f)
 void ionic_rx_filter_replay(struct ionic_lif *lif)
 {
        struct ionic_rx_filter_add_cmd *ac;
+       struct hlist_head new_id_list;
        struct ionic_admin_ctx ctx;
        struct ionic_rx_filter *f;
        struct hlist_head *head;
        struct hlist_node *tmp;
+       unsigned int key;
        unsigned int i;
        int err;
 
+       INIT_HLIST_HEAD(&new_id_list);
        ac = &ctx.cmd.rx_filter_add;
 
        for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
@@ -58,9 +61,30 @@ void ionic_rx_filter_replay(struct ionic_lif *lif)
                                                    ac->mac.addr);
                                        break;
                                }
+                               spin_lock_bh(&lif->rx_filters.lock);
+                               ionic_rx_filter_free(lif, f);
+                               spin_unlock_bh(&lif->rx_filters.lock);
+
+                               continue;
                        }
+
+                       /* remove from old id list, save new id in tmp list */
+                       spin_lock_bh(&lif->rx_filters.lock);
+                       hlist_del(&f->by_id);
+                       spin_unlock_bh(&lif->rx_filters.lock);
+                       f->filter_id = le32_to_cpu(ctx.comp.rx_filter_add.filter_id);
+                       hlist_add_head(&f->by_id, &new_id_list);
                }
        }
+
+       /* rebuild the by_id hash lists with the new filter ids */
+       spin_lock_bh(&lif->rx_filters.lock);
+       hlist_for_each_entry_safe(f, tmp, &new_id_list, by_id) {
+               key = f->filter_id & IONIC_RX_FILTER_HLISTS_MASK;
+               head = &lif->rx_filters.by_id[key];
+               hlist_add_head(&f->by_id, head);
+       }
+       spin_unlock_bh(&lif->rx_filters.lock);
 }
 
 int ionic_rx_filters_init(struct ionic_lif *lif)
@@ -69,10 +93,12 @@ int ionic_rx_filters_init(struct ionic_lif *lif)
 
        spin_lock_init(&lif->rx_filters.lock);
 
+       spin_lock_bh(&lif->rx_filters.lock);
        for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
                INIT_HLIST_HEAD(&lif->rx_filters.by_hash[i]);
                INIT_HLIST_HEAD(&lif->rx_filters.by_id[i]);
        }
+       spin_unlock_bh(&lif->rx_filters.lock);
 
        return 0;
 }
@@ -84,11 +110,13 @@ void ionic_rx_filters_deinit(struct ionic_lif *lif)
        struct hlist_node *tmp;
        unsigned int i;
 
+       spin_lock_bh(&lif->rx_filters.lock);
        for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
                head = &lif->rx_filters.by_id[i];
                hlist_for_each_entry_safe(f, tmp, head, by_id)
                        ionic_rx_filter_free(lif, f);
        }
+       spin_unlock_bh(&lif->rx_filters.lock);
 }
 
 int ionic_rx_filter_save(struct ionic_lif *lif, u32 flow_id, u16 rxq_index,
@@ -124,6 +152,7 @@ int ionic_rx_filter_save(struct ionic_lif *lif, u32 flow_id, u16 rxq_index,
        f->filter_id = le32_to_cpu(ctx->comp.rx_filter_add.filter_id);
        f->rxq_index = rxq_index;
        memcpy(&f->cmd, ac, sizeof(f->cmd));
+       netdev_dbg(lif->netdev, "rx_filter add filter_id %d\n", f->filter_id);
 
        INIT_HLIST_NODE(&f->by_hash);
        INIT_HLIST_NODE(&f->by_id);
index b7f900c..85eb8f2 100644 (file)
@@ -161,12 +161,6 @@ static void ionic_rx_clean(struct ionic_queue *q,
                return;
        }
 
-       /* no packet processing while resetting */
-       if (unlikely(test_bit(IONIC_LIF_F_QUEUE_RESET, q->lif->state))) {
-               stats->dropped++;
-               return;
-       }
-
        stats->pkts++;
        stats->bytes += le16_to_cpu(comp->len);
 
index a49743d..6c2f9ff 100644 (file)
@@ -876,6 +876,8 @@ struct qed_dev {
        struct qed_dbg_feature dbg_features[DBG_FEATURE_NUM];
        u8 engine_for_debug;
        bool disable_ilt_dump;
+       bool                            dbg_bin_dump;
+
        DECLARE_HASHTABLE(connections, 10);
        const struct firmware           *firmware;
 
index 7b76667..d13ec88 100644 (file)
@@ -271,7 +271,7 @@ static void qed_cxt_qm_iids(struct qed_hwfn *p_hwfn,
                vf_tids += segs[NUM_TASK_PF_SEGMENTS].count;
        }
 
-       iids->vf_cids += vf_cids * p_mngr->vf_count;
+       iids->vf_cids = vf_cids;
        iids->tids += vf_tids * p_mngr->vf_count;
 
        DP_VERBOSE(p_hwfn, QED_MSG_ILT,
@@ -465,6 +465,20 @@ static struct qed_ilt_cli_blk *qed_cxt_set_blk(struct qed_ilt_cli_blk *p_blk)
        return p_blk;
 }
 
+static void qed_cxt_ilt_blk_reset(struct qed_hwfn *p_hwfn)
+{
+       struct qed_ilt_client_cfg *clients = p_hwfn->p_cxt_mngr->clients;
+       u32 cli_idx, blk_idx;
+
+       for (cli_idx = 0; cli_idx < MAX_ILT_CLIENTS; cli_idx++) {
+               for (blk_idx = 0; blk_idx < ILT_CLI_PF_BLOCKS; blk_idx++)
+                       clients[cli_idx].pf_blks[blk_idx].total_size = 0;
+
+               for (blk_idx = 0; blk_idx < ILT_CLI_VF_BLOCKS; blk_idx++)
+                       clients[cli_idx].vf_blks[blk_idx].total_size = 0;
+       }
+}
+
 int qed_cxt_cfg_ilt_compute(struct qed_hwfn *p_hwfn, u32 *line_count)
 {
        struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
@@ -484,6 +498,11 @@ int qed_cxt_cfg_ilt_compute(struct qed_hwfn *p_hwfn, u32 *line_count)
 
        p_mngr->pf_start_line = RESC_START(p_hwfn, QED_ILT);
 
+       /* Reset all ILT blocks at the beginning of ILT computing in order
+        * to prevent memory allocation for irrelevant blocks afterwards.
+        */
+       qed_cxt_ilt_blk_reset(p_hwfn);
+
        DP_VERBOSE(p_hwfn, QED_MSG_ILT,
                   "hwfn [%d] - Set context manager starting line to be 0x%08x\n",
                   p_hwfn->my_id, p_hwfn->p_cxt_mngr->pf_start_line);
@@ -1989,8 +2008,8 @@ static void qed_rdma_set_pf_params(struct qed_hwfn *p_hwfn,
        enum protocol_type proto;
 
        if (p_hwfn->mcp_info->func_info.protocol == QED_PCI_ETH_RDMA) {
-               DP_NOTICE(p_hwfn,
-                         "Current day drivers don't support RoCE & iWARP simultaneously on the same PF. Default to RoCE-only\n");
+               DP_VERBOSE(p_hwfn, QED_MSG_SP,
+                          "Current day drivers don't support RoCE & iWARP simultaneously on the same PF. Default to RoCE-only\n");
                p_hwfn->hw_info.personality = QED_PCI_ETH_ROCE;
        }
 
index 57a0dab..3b9bbaf 100644 (file)
@@ -5568,7 +5568,8 @@ static const char * const s_status_str[] = {
 
        /* DBG_STATUS_INVALID_FILTER_TRIGGER_DWORDS */
        "The filter/trigger constraint dword offsets are not enabled for recording",
-
+       /* DBG_STATUS_NO_MATCHING_FRAMING_MODE */
+       "No matching framing mode",
 
        /* DBG_STATUS_VFC_READ_ERROR */
        "Error reading from VFC",
@@ -7505,6 +7506,12 @@ static enum dbg_status format_feature(struct qed_hwfn *p_hwfn,
        if (p_hwfn->cdev->print_dbg_data)
                qed_dbg_print_feature(text_buf, text_size_bytes);
 
+       /* Just return the original binary buffer if requested */
+       if (p_hwfn->cdev->dbg_bin_dump) {
+               vfree(text_buf);
+               return DBG_STATUS_OK;
+       }
+
        /* Free the old dump_buf and point the dump_buf to the newly allocagted
         * and formatted text buffer.
         */
@@ -7732,7 +7739,9 @@ int qed_dbg_mcp_trace_size(struct qed_dev *cdev)
 #define REGDUMP_HEADER_SIZE_SHIFT              0
 #define REGDUMP_HEADER_SIZE_MASK               0xffffff
 #define REGDUMP_HEADER_FEATURE_SHIFT           24
-#define REGDUMP_HEADER_FEATURE_MASK            0x3f
+#define REGDUMP_HEADER_FEATURE_MASK            0x1f
+#define REGDUMP_HEADER_BIN_DUMP_SHIFT          29
+#define REGDUMP_HEADER_BIN_DUMP_MASK           0x1
 #define REGDUMP_HEADER_OMIT_ENGINE_SHIFT       30
 #define REGDUMP_HEADER_OMIT_ENGINE_MASK                0x1
 #define REGDUMP_HEADER_ENGINE_SHIFT            31
@@ -7770,6 +7779,7 @@ static u32 qed_calc_regdump_header(struct qed_dev *cdev,
                          feature, feature_size);
 
        SET_FIELD(res, REGDUMP_HEADER_FEATURE, feature);
+       SET_FIELD(res, REGDUMP_HEADER_BIN_DUMP, 1);
        SET_FIELD(res, REGDUMP_HEADER_OMIT_ENGINE, omit_engine);
        SET_FIELD(res, REGDUMP_HEADER_ENGINE, engine);
 
@@ -7793,6 +7803,7 @@ int qed_dbg_all_data(struct qed_dev *cdev, void *buffer)
                omit_engine = 1;
 
        mutex_lock(&qed_dbg_lock);
+       cdev->dbg_bin_dump = true;
 
        org_engine = qed_get_debug_engine(cdev);
        for (cur_engine = 0; cur_engine < cdev->num_hwfns; cur_engine++) {
@@ -7930,6 +7941,10 @@ int qed_dbg_all_data(struct qed_dev *cdev, void *buffer)
                DP_ERR(cdev, "qed_dbg_mcp_trace failed. rc = %d\n", rc);
        }
 
+       /* Re-populate nvm attribute info */
+       qed_mcp_nvm_info_free(p_hwfn);
+       qed_mcp_nvm_info_populate(p_hwfn);
+
        /* nvm cfg1 */
        rc = qed_dbg_nvm_image(cdev,
                               (u8 *)buffer + offset +
@@ -7992,6 +8007,7 @@ int qed_dbg_all_data(struct qed_dev *cdev, void *buffer)
                       QED_NVM_IMAGE_MDUMP, "QED_NVM_IMAGE_MDUMP", rc);
        }
 
+       cdev->dbg_bin_dump = false;
        mutex_unlock(&qed_dbg_lock);
 
        return 0;
index 1eebf30..dbdac98 100644 (file)
@@ -980,7 +980,7 @@ int qed_llh_add_mac_filter(struct qed_dev *cdev,
        struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
        struct qed_ptt *p_ptt = qed_ptt_acquire(p_hwfn);
        union qed_llh_filter filter = {};
-       u8 filter_idx, abs_ppfid;
+       u8 filter_idx, abs_ppfid = 0;
        u32 high, low, ref_cnt;
        int rc = 0;
 
@@ -1368,6 +1368,8 @@ static void qed_dbg_user_data_free(struct qed_hwfn *p_hwfn)
 
 void qed_resc_free(struct qed_dev *cdev)
 {
+       struct qed_rdma_info *rdma_info;
+       struct qed_hwfn *p_hwfn;
        int i;
 
        if (IS_VF(cdev)) {
@@ -1385,7 +1387,8 @@ void qed_resc_free(struct qed_dev *cdev)
        qed_llh_free(cdev);
 
        for_each_hwfn(cdev, i) {
-               struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+               p_hwfn = cdev->hwfns + i;
+               rdma_info = p_hwfn->p_rdma_info;
 
                qed_cxt_mngr_free(p_hwfn);
                qed_qm_info_free(p_hwfn);
@@ -1404,8 +1407,10 @@ void qed_resc_free(struct qed_dev *cdev)
                        qed_ooo_free(p_hwfn);
                }
 
-               if (QED_IS_RDMA_PERSONALITY(p_hwfn))
+               if (QED_IS_RDMA_PERSONALITY(p_hwfn) && rdma_info) {
+                       qed_spq_unregister_async_cb(p_hwfn, rdma_info->proto);
                        qed_rdma_info_free(p_hwfn);
+               }
 
                qed_iov_free(p_hwfn);
                qed_l2_free(p_hwfn);
@@ -3097,7 +3102,7 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params)
                }
 
                /* Log and clear previous pglue_b errors if such exist */
-               qed_pglueb_rbc_attn_handler(p_hwfn, p_hwfn->p_main_ptt);
+               qed_pglueb_rbc_attn_handler(p_hwfn, p_hwfn->p_main_ptt, true);
 
                /* Enable the PF's internal FID_enable in the PXP */
                rc = qed_pglueb_set_pfid_enable(p_hwfn, p_hwfn->p_main_ptt,
@@ -4467,12 +4472,6 @@ static int qed_get_dev_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
        return 0;
 }
 
-static void qed_nvm_info_free(struct qed_hwfn *p_hwfn)
-{
-       kfree(p_hwfn->nvm_info.image_att);
-       p_hwfn->nvm_info.image_att = NULL;
-}
-
 static int qed_hw_prepare_single(struct qed_hwfn *p_hwfn,
                                 void __iomem *p_regview,
                                 void __iomem *p_doorbells,
@@ -4557,7 +4556,7 @@ static int qed_hw_prepare_single(struct qed_hwfn *p_hwfn,
        return rc;
 err3:
        if (IS_LEAD_HWFN(p_hwfn))
-               qed_nvm_info_free(p_hwfn);
+               qed_mcp_nvm_info_free(p_hwfn);
 err2:
        if (IS_LEAD_HWFN(p_hwfn))
                qed_iov_free_hw_info(p_hwfn->cdev);
@@ -4618,7 +4617,7 @@ int qed_hw_prepare(struct qed_dev *cdev,
                if (rc) {
                        if (IS_PF(cdev)) {
                                qed_init_free(p_hwfn);
-                               qed_nvm_info_free(p_hwfn);
+                               qed_mcp_nvm_info_free(p_hwfn);
                                qed_mcp_free(p_hwfn);
                                qed_hw_hwfn_free(p_hwfn);
                        }
@@ -4652,7 +4651,7 @@ void qed_hw_remove(struct qed_dev *cdev)
 
        qed_iov_free_hw_info(cdev);
 
-       qed_nvm_info_free(p_hwfn);
+       qed_mcp_nvm_info_free(p_hwfn);
 }
 
 static void qed_chain_free_next_ptr(struct qed_dev *cdev,
index b7b974f..5eec1fc 100644 (file)
@@ -257,9 +257,10 @@ out:
 #define PGLUE_ATTENTION_ZLR_VALID              (1 << 25)
 #define PGLUE_ATTENTION_ILT_VALID              (1 << 23)
 
-int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn,
-                               struct qed_ptt *p_ptt)
+int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
+                               bool hw_init)
 {
+       char msg[256];
        u32 tmp;
 
        tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_WR_DETAILS2);
@@ -273,22 +274,23 @@ int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn,
                details = qed_rd(p_hwfn, p_ptt,
                                 PGLUE_B_REG_TX_ERR_WR_DETAILS);
 
-               DP_NOTICE(p_hwfn,
-                         "Illegal write by chip to [%08x:%08x] blocked.\n"
-                         "Details: %08x [PFID %02x, VFID %02x, VF_VALID %02x]\n"
-                         "Details2 %08x [Was_error %02x BME deassert %02x FID_enable deassert %02x]\n",
-                         addr_hi, addr_lo, details,
-                         (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_PFID),
-                         (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VFID),
-                         GET_FIELD(details,
-                                   PGLUE_ATTENTION_DETAILS_VF_VALID) ? 1 : 0,
-                         tmp,
-                         GET_FIELD(tmp,
-                                   PGLUE_ATTENTION_DETAILS2_WAS_ERR) ? 1 : 0,
-                         GET_FIELD(tmp,
-                                   PGLUE_ATTENTION_DETAILS2_BME) ? 1 : 0,
-                         GET_FIELD(tmp,
-                                   PGLUE_ATTENTION_DETAILS2_FID_EN) ? 1 : 0);
+               snprintf(msg, sizeof(msg),
+                        "Illegal write by chip to [%08x:%08x] blocked.\n"
+                        "Details: %08x [PFID %02x, VFID %02x, VF_VALID %02x]\n"
+                        "Details2 %08x [Was_error %02x BME deassert %02x FID_enable deassert %02x]",
+                        addr_hi, addr_lo, details,
+                        (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_PFID),
+                        (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VFID),
+                        !!GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VF_VALID),
+                        tmp,
+                        !!GET_FIELD(tmp, PGLUE_ATTENTION_DETAILS2_WAS_ERR),
+                        !!GET_FIELD(tmp, PGLUE_ATTENTION_DETAILS2_BME),
+                        !!GET_FIELD(tmp, PGLUE_ATTENTION_DETAILS2_FID_EN));
+
+               if (hw_init)
+                       DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "%s\n", msg);
+               else
+                       DP_NOTICE(p_hwfn, "%s\n", msg);
        }
 
        tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_RD_DETAILS2);
@@ -321,8 +323,14 @@ int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn,
        }
 
        tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_WR_DETAILS_ICPL);
-       if (tmp & PGLUE_ATTENTION_ICPL_VALID)
-               DP_NOTICE(p_hwfn, "ICPL error - %08x\n", tmp);
+       if (tmp & PGLUE_ATTENTION_ICPL_VALID) {
+               snprintf(msg, sizeof(msg), "ICPL error - %08x", tmp);
+
+               if (hw_init)
+                       DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "%s\n", msg);
+               else
+                       DP_NOTICE(p_hwfn, "%s\n", msg);
+       }
 
        tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_MASTER_ZLR_ERR_DETAILS);
        if (tmp & PGLUE_ATTENTION_ZLR_VALID) {
@@ -361,7 +369,7 @@ int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn,
 
 static int qed_pglueb_rbc_attn_cb(struct qed_hwfn *p_hwfn)
 {
-       return qed_pglueb_rbc_attn_handler(p_hwfn, p_hwfn->p_dpc_ptt);
+       return qed_pglueb_rbc_attn_handler(p_hwfn, p_hwfn->p_dpc_ptt, false);
 }
 
 static int qed_fw_assertion(struct qed_hwfn *p_hwfn)
@@ -1193,7 +1201,8 @@ static int qed_int_attentions(struct qed_hwfn *p_hwfn)
                        index, attn_bits, attn_acks, asserted_bits,
                        deasserted_bits, p_sb_attn_sw->known_attn);
        } else if (asserted_bits == 0x100) {
-               DP_INFO(p_hwfn, "MFW indication via attention\n");
+               DP_VERBOSE(p_hwfn, NETIF_MSG_INTR,
+                          "MFW indication via attention\n");
        } else {
                DP_VERBOSE(p_hwfn, NETIF_MSG_INTR,
                           "MFW indication [deassertion]\n");
index e09db33..110169e 100644 (file)
@@ -442,7 +442,7 @@ int qed_int_set_timer_res(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
 
 #define QED_MAPPING_MEMORY_SIZE(dev)   (NUM_OF_SBS(dev))
 
-int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn,
-                               struct qed_ptt *p_ptt);
+int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
+                               bool hw_init);
 
 #endif
index d2fe61a..5409a2d 100644 (file)
@@ -2836,8 +2836,6 @@ int qed_iwarp_stop(struct qed_hwfn *p_hwfn)
        if (rc)
                return rc;
 
-       qed_spq_unregister_async_cb(p_hwfn, PROTOCOLID_IWARP);
-
        return qed_iwarp_ll2_stop(p_hwfn);
 }
 
index 9624616..0fd4520 100644 (file)
@@ -3280,6 +3280,13 @@ err0:
        return rc;
 }
 
+void qed_mcp_nvm_info_free(struct qed_hwfn *p_hwfn)
+{
+       kfree(p_hwfn->nvm_info.image_att);
+       p_hwfn->nvm_info.image_att = NULL;
+       p_hwfn->nvm_info.valid = false;
+}
+
 int
 qed_mcp_get_nvm_image_att(struct qed_hwfn *p_hwfn,
                          enum qed_nvm_images image_id,
index 5750b4c..12a705e 100644 (file)
@@ -1220,6 +1220,13 @@ void qed_mcp_read_ufp_config(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
  */
 int qed_mcp_nvm_info_populate(struct qed_hwfn *p_hwfn);
 
+/**
+ * @brief Delete nvm info shadow in the given hardware function
+ *
+ * @param p_hwfn
+ */
+void qed_mcp_nvm_info_free(struct qed_hwfn *p_hwfn);
+
 /**
  * @brief Get the engine affinity configuration.
  *
index 4566815..7271dd7 100644 (file)
@@ -113,7 +113,6 @@ void qed_roce_stop(struct qed_hwfn *p_hwfn)
                        break;
                }
        }
-       qed_spq_unregister_async_cb(p_hwfn, PROTOCOLID_ROCE);
 }
 
 static void qed_rdma_copy_gids(struct qed_rdma_qp *qp, __le32 *src_gid,
index 856051f..adc2c8f 100644 (file)
@@ -81,12 +81,17 @@ static void qed_vf_pf_req_end(struct qed_hwfn *p_hwfn, int req_status)
        mutex_unlock(&(p_hwfn->vf_iov_info->mutex));
 }
 
+#define QED_VF_CHANNEL_USLEEP_ITERATIONS       90
+#define QED_VF_CHANNEL_USLEEP_DELAY            100
+#define QED_VF_CHANNEL_MSLEEP_ITERATIONS       10
+#define QED_VF_CHANNEL_MSLEEP_DELAY            25
+
 static int qed_send_msg2pf(struct qed_hwfn *p_hwfn, u8 *done, u32 resp_size)
 {
        union vfpf_tlvs *p_req = p_hwfn->vf_iov_info->vf2pf_request;
        struct ustorm_trigger_vf_zone trigger;
        struct ustorm_vf_zone *zone_data;
-       int rc = 0, time = 100;
+       int iter, rc = 0;
 
        zone_data = (struct ustorm_vf_zone *)PXP_VF_BAR0_START_USDM_ZONE_B;
 
@@ -126,11 +131,19 @@ static int qed_send_msg2pf(struct qed_hwfn *p_hwfn, u8 *done, u32 resp_size)
        REG_WR(p_hwfn, (uintptr_t)&zone_data->trigger, *((u32 *)&trigger));
 
        /* When PF would be done with the response, it would write back to the
-        * `done' address. Poll until then.
+        * `done' address from a coherent DMA zone. Poll until then.
         */
-       while ((!*done) && time) {
-               msleep(25);
-               time--;
+
+       iter = QED_VF_CHANNEL_USLEEP_ITERATIONS;
+       while (!*done && iter--) {
+               udelay(QED_VF_CHANNEL_USLEEP_DELAY);
+               dma_rmb();
+       }
+
+       iter = QED_VF_CHANNEL_MSLEEP_ITERATIONS;
+       while (!*done && iter--) {
+               msleep(QED_VF_CHANNEL_MSLEEP_DELAY);
+               dma_rmb();
        }
 
        if (!*done) {
index 756c05e..29e2854 100644 (file)
@@ -1229,7 +1229,7 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level,
 
        /* PTP not supported on VFs */
        if (!is_vf)
-               qede_ptp_enable(edev, (mode == QEDE_PROBE_NORMAL));
+               qede_ptp_enable(edev);
 
        edev->ops->register_ops(cdev, &qede_ll_ops, edev);
 
@@ -1318,6 +1318,7 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode)
        if (system_state == SYSTEM_POWER_OFF)
                return;
        qed_ops->common->remove(cdev);
+       edev->cdev = NULL;
 
        /* Since this can happen out-of-sync with other flows,
         * don't release the netdevice until after slowpath stop
index 4c7f7a7..cd5841a 100644 (file)
@@ -412,6 +412,7 @@ void qede_ptp_disable(struct qede_dev *edev)
        if (ptp->tx_skb) {
                dev_kfree_skb_any(ptp->tx_skb);
                ptp->tx_skb = NULL;
+               clear_bit_unlock(QEDE_FLAGS_PTP_TX_IN_PRORGESS, &edev->flags);
        }
 
        /* Disable PTP in HW */
@@ -423,7 +424,7 @@ void qede_ptp_disable(struct qede_dev *edev)
        edev->ptp = NULL;
 }
 
-static int qede_ptp_init(struct qede_dev *edev, bool init_tc)
+static int qede_ptp_init(struct qede_dev *edev)
 {
        struct qede_ptp *ptp;
        int rc;
@@ -444,25 +445,19 @@ static int qede_ptp_init(struct qede_dev *edev, bool init_tc)
        /* Init work queue for Tx timestamping */
        INIT_WORK(&ptp->work, qede_ptp_task);
 
-       /* Init cyclecounter and timecounter. This is done only in the first
-        * load. If done in every load, PTP application will fail when doing
-        * unload / load (e.g. MTU change) while it is running.
-        */
-       if (init_tc) {
-               memset(&ptp->cc, 0, sizeof(ptp->cc));
-               ptp->cc.read = qede_ptp_read_cc;
-               ptp->cc.mask = CYCLECOUNTER_MASK(64);
-               ptp->cc.shift = 0;
-               ptp->cc.mult = 1;
-
-               timecounter_init(&ptp->tc, &ptp->cc,
-                                ktime_to_ns(ktime_get_real()));
-       }
+       /* Init cyclecounter and timecounter */
+       memset(&ptp->cc, 0, sizeof(ptp->cc));
+       ptp->cc.read = qede_ptp_read_cc;
+       ptp->cc.mask = CYCLECOUNTER_MASK(64);
+       ptp->cc.shift = 0;
+       ptp->cc.mult = 1;
 
-       return rc;
+       timecounter_init(&ptp->tc, &ptp->cc, ktime_to_ns(ktime_get_real()));
+
+       return 0;
 }
 
-int qede_ptp_enable(struct qede_dev *edev, bool init_tc)
+int qede_ptp_enable(struct qede_dev *edev)
 {
        struct qede_ptp *ptp;
        int rc;
@@ -483,7 +478,7 @@ int qede_ptp_enable(struct qede_dev *edev, bool init_tc)
 
        edev->ptp = ptp;
 
-       rc = qede_ptp_init(edev, init_tc);
+       rc = qede_ptp_init(edev);
        if (rc)
                goto err1;
 
index 691a14c..89c7f3c 100644 (file)
@@ -41,7 +41,7 @@ void qede_ptp_rx_ts(struct qede_dev *edev, struct sk_buff *skb);
 void qede_ptp_tx_ts(struct qede_dev *edev, struct sk_buff *skb);
 int qede_ptp_hw_ts(struct qede_dev *edev, struct ifreq *req);
 void qede_ptp_disable(struct qede_dev *edev);
-int qede_ptp_enable(struct qede_dev *edev, bool init_tc);
+int qede_ptp_enable(struct qede_dev *edev);
 int qede_ptp_get_ts_info(struct qede_dev *edev, struct ethtool_ts_info *ts);
 
 static inline void qede_ptp_record_rx_ts(struct qede_dev *edev,
index 2d873ae..668ccc9 100644 (file)
@@ -105,6 +105,7 @@ static void qede_rdma_destroy_wq(struct qede_dev *edev)
 
        qede_rdma_cleanup_event(edev);
        destroy_workqueue(edev->rdma_info.rdma_wq);
+       edev->rdma_info.rdma_wq = NULL;
 }
 
 int qede_rdma_dev_add(struct qede_dev *edev, bool recovery)
@@ -325,7 +326,7 @@ static void qede_rdma_add_event(struct qede_dev *edev,
        if (edev->rdma_info.exp_recovery)
                return;
 
-       if (!edev->rdma_info.qedr_dev)
+       if (!edev->rdma_info.qedr_dev || !edev->rdma_info.rdma_wq)
                return;
 
        /* We don't want the cleanup flow to start while we're allocating and
index 8d7b9bb..1003763 100644 (file)
@@ -269,7 +269,7 @@ static ssize_t qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj,
                                     struct bin_attribute *attr, char *buf,
                                     loff_t offset, size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        int ret;
 
@@ -286,7 +286,7 @@ static ssize_t qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj,
                                      struct bin_attribute *attr, char *buf,
                                      loff_t offset, size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        int ret;
 
@@ -315,7 +315,7 @@ static ssize_t qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj,
                                     struct bin_attribute *attr, char *buf,
                                     loff_t offset, size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        u64 data;
        int ret;
@@ -337,7 +337,7 @@ static ssize_t qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj,
                                      struct bin_attribute *attr, char *buf,
                                      loff_t offset, size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        u64 data;
        int ret;
@@ -402,7 +402,7 @@ static ssize_t qlcnic_sysfs_write_pm_config(struct file *filp,
                                            char *buf, loff_t offset,
                                            size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_pm_func_cfg *pm_cfg;
        u32 id, action, pci_func;
@@ -452,7 +452,7 @@ static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp,
                                           char *buf, loff_t offset,
                                           size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_pm_func_cfg *pm_cfg;
        u8 pci_func;
@@ -545,7 +545,7 @@ static ssize_t qlcnic_sysfs_write_esw_config(struct file *file,
                                             char *buf, loff_t offset,
                                             size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_esw_func_cfg *esw_cfg;
        struct qlcnic_npar_info *npar;
@@ -629,7 +629,7 @@ static ssize_t qlcnic_sysfs_read_esw_config(struct file *file,
                                            char *buf, loff_t offset,
                                            size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_esw_func_cfg *esw_cfg;
        u8 pci_func;
@@ -681,7 +681,7 @@ static ssize_t qlcnic_sysfs_write_npar_config(struct file *file,
                                              char *buf, loff_t offset,
                                              size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_info nic_info;
        struct qlcnic_npar_func_cfg *np_cfg;
@@ -728,7 +728,7 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
                                             char *buf, loff_t offset,
                                             size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_npar_func_cfg *np_cfg;
        struct qlcnic_info nic_info;
@@ -775,7 +775,7 @@ static ssize_t qlcnic_sysfs_get_port_stats(struct file *file,
                                           char *buf, loff_t offset,
                                           size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_esw_statistics port_stats;
        int ret;
@@ -810,7 +810,7 @@ static ssize_t qlcnic_sysfs_get_esw_stats(struct file *file,
                                          char *buf, loff_t offset,
                                          size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_esw_statistics esw_stats;
        int ret;
@@ -845,7 +845,7 @@ static ssize_t qlcnic_sysfs_clear_esw_stats(struct file *file,
                                            char *buf, loff_t offset,
                                            size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        int ret;
 
@@ -875,7 +875,7 @@ static ssize_t qlcnic_sysfs_clear_port_stats(struct file *file,
                                             size_t size)
 {
 
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        int ret;
 
@@ -904,7 +904,7 @@ static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,
                                            char *buf, loff_t offset,
                                            size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_pci_func_cfg *pci_cfg;
        struct qlcnic_pci_info *pci_info;
@@ -946,7 +946,7 @@ static ssize_t qlcnic_83xx_sysfs_flash_read_handler(struct file *filp,
 {
        unsigned char *p_read_buf;
        int  ret, count;
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
 
        if (!size)
@@ -1124,7 +1124,7 @@ static ssize_t qlcnic_83xx_sysfs_flash_write_handler(struct file *filp,
        int  ret;
        static int flash_mode;
        unsigned long data;
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
 
        ret = kstrtoul(buf, 16, &data);
index 40efe60..fcdecdd 100644 (file)
@@ -47,15 +47,23 @@ static int rmnet_unregister_real_device(struct net_device *real_dev)
        return 0;
 }
 
-static int rmnet_register_real_device(struct net_device *real_dev)
+static int rmnet_register_real_device(struct net_device *real_dev,
+                                     struct netlink_ext_ack *extack)
 {
        struct rmnet_port *port;
        int rc, entry;
 
        ASSERT_RTNL();
 
-       if (rmnet_is_real_dev_registered(real_dev))
+       if (rmnet_is_real_dev_registered(real_dev)) {
+               port = rmnet_get_port_rtnl(real_dev);
+               if (port->rmnet_mode != RMNET_EPMODE_VND) {
+                       NL_SET_ERR_MSG_MOD(extack, "bridge device already exists");
+                       return -EINVAL;
+               }
+
                return 0;
+       }
 
        port = kzalloc(sizeof(*port), GFP_KERNEL);
        if (!port)
@@ -133,7 +141,7 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
 
        mux_id = nla_get_u16(data[IFLA_RMNET_MUX_ID]);
 
-       err = rmnet_register_real_device(real_dev);
+       err = rmnet_register_real_device(real_dev, extack);
        if (err)
                goto err0;
 
@@ -422,7 +430,7 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
        }
 
        if (port->rmnet_mode != RMNET_EPMODE_VND) {
-               NL_SET_ERR_MSG_MOD(extack, "bridge device already exists");
+               NL_SET_ERR_MSG_MOD(extack, "more than one bridge dev attached");
                return -EINVAL;
        }
 
@@ -433,7 +441,7 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
                return -EBUSY;
        }
 
-       err = rmnet_register_real_device(slave_dev);
+       err = rmnet_register_real_device(slave_dev, extack);
        if (err)
                return -EBUSY;
 
index dad84ec..b660ddb 100644 (file)
@@ -2114,8 +2114,11 @@ static void rtl_release_firmware(struct rtl8169_private *tp)
 void r8169_apply_firmware(struct rtl8169_private *tp)
 {
        /* TODO: release firmware if rtl_fw_write_firmware signals failure. */
-       if (tp->rtl_fw)
+       if (tp->rtl_fw) {
                rtl_fw_write_firmware(tp, tp->rtl_fw);
+               /* At least one firmware doesn't reset tp->ocp_base. */
+               tp->ocp_base = OCP_STD_PHY_BASE;
+       }
 }
 
 static void rtl8168_config_eee_mac(struct rtl8169_private *tp)
index a442bcf..99f7aae 100644 (file)
@@ -1450,6 +1450,7 @@ static void ravb_tx_timeout_work(struct work_struct *work)
        struct ravb_private *priv = container_of(work, struct ravb_private,
                                                 work);
        struct net_device *ndev = priv->ndev;
+       int error;
 
        netif_tx_stop_all_queues(ndev);
 
@@ -1458,15 +1459,36 @@ static void ravb_tx_timeout_work(struct work_struct *work)
                ravb_ptp_stop(ndev);
 
        /* Wait for DMA stopping */
-       ravb_stop_dma(ndev);
+       if (ravb_stop_dma(ndev)) {
+               /* If ravb_stop_dma() fails, the hardware is still operating
+                * for TX and/or RX. So, this should not call the following
+                * functions because ravb_dmac_init() is possible to fail too.
+                * Also, this should not retry ravb_stop_dma() again and again
+                * here because it's possible to wait forever. So, this just
+                * re-enables the TX and RX and skip the following
+                * re-initialization procedure.
+                */
+               ravb_rcv_snd_enable(ndev);
+               goto out;
+       }
 
        ravb_ring_free(ndev, RAVB_BE);
        ravb_ring_free(ndev, RAVB_NC);
 
        /* Device init */
-       ravb_dmac_init(ndev);
+       error = ravb_dmac_init(ndev);
+       if (error) {
+               /* If ravb_dmac_init() fails, descriptors are freed. So, this
+                * should return here to avoid re-enabling the TX and RX in
+                * ravb_emac_init().
+                */
+               netdev_err(ndev, "%s: ravb_dmac_init() failed, error %d\n",
+                          __func__, error);
+               return;
+       }
        ravb_emac_init(ndev);
 
+out:
        /* Initialise PTP Clock driver */
        if (priv->chip_id == RCAR_GEN2)
                ravb_ptp_init(ndev, priv->pdev);
index 7585cd2..fc99e71 100644 (file)
@@ -647,10 +647,10 @@ static int rocker_dma_rings_init(struct rocker *rocker)
 err_dma_event_ring_bufs_alloc:
        rocker_dma_ring_destroy(rocker, &rocker->event_ring);
 err_dma_event_ring_create:
+       rocker_dma_cmd_ring_waits_free(rocker);
+err_dma_cmd_ring_waits_alloc:
        rocker_dma_ring_bufs_free(rocker, &rocker->cmd_ring,
                                  PCI_DMA_BIDIRECTIONAL);
-err_dma_cmd_ring_waits_alloc:
-       rocker_dma_cmd_ring_waits_free(rocker);
 err_dma_cmd_ring_bufs_alloc:
        rocker_dma_ring_destroy(rocker, &rocker->cmd_ring);
        return err;
index 90410f9..1c4fea9 100644 (file)
@@ -2274,7 +2274,7 @@ static int smc_drv_probe(struct platform_device *pdev)
                ret = try_toggle_control_gpio(&pdev->dev, &lp->power_gpio,
                                              "power", 0, 0, 100);
                if (ret)
-                       return ret;
+                       goto out_free_netdev;
 
                /*
                 * Optional reset GPIO configured? Minimum 100 ns reset needed
@@ -2283,7 +2283,7 @@ static int smc_drv_probe(struct platform_device *pdev)
                ret = try_toggle_control_gpio(&pdev->dev, &lp->reset_gpio,
                                              "reset", 0, 0, 100);
                if (ret)
-                       return ret;
+                       goto out_free_netdev;
 
                /*
                 * Need to wait for optional EEPROM to load, max 750 us according
index 328bc38..0f366cc 100644 (file)
@@ -1044,8 +1044,9 @@ static int netsec_process_rx(struct netsec_priv *priv, int budget)
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 next:
-               if ((skb && napi_gro_receive(&priv->napi, skb) != GRO_DROP) ||
-                   xdp_result) {
+               if (skb)
+                       napi_gro_receive(&priv->napi, skb);
+               if (skb || xdp_result) {
                        ndev->stats.rx_packets++;
                        ndev->stats.rx_bytes += xdp.data_end - xdp.data;
                }
index f263844..81b554d 100644 (file)
@@ -1191,7 +1191,7 @@ static int ave_init(struct net_device *ndev)
        ret = regmap_update_bits(priv->regmap, SG_ETPINMODE,
                                 priv->pinmode_mask, priv->pinmode_val);
        if (ret)
-               return ret;
+               goto out_reset_assert;
 
        ave_global_reset(ndev);
 
index 1492648..6d778bc 100644 (file)
@@ -1850,7 +1850,8 @@ static int am65_cpsw_nuss_init_ndev_2g(struct am65_cpsw_common *common)
        port->ndev->max_mtu = AM65_CPSW_MAX_PACKET_SIZE;
        port->ndev->hw_features = NETIF_F_SG |
                                  NETIF_F_RXCSUM |
-                                 NETIF_F_HW_CSUM;
+                                 NETIF_F_HW_CSUM |
+                                 NETIF_F_HW_TC;
        port->ndev->features = port->ndev->hw_features |
                               NETIF_F_HW_VLAN_CTAG_FILTER;
        port->ndev->vlan_features |=  NETIF_F_SG;
index fbaf3c9..f34c790 100644 (file)
 #define XAE_RAF_TXVSTRPMODE_MASK       0x00000180 /* Tx VLAN STRIP mode */
 #define XAE_RAF_RXVSTRPMODE_MASK       0x00000600 /* Rx VLAN STRIP mode */
 #define XAE_RAF_NEWFNCENBL_MASK                0x00000800 /* New function mode */
-/* Exteneded Multicast Filtering mode */
+/* Extended Multicast Filtering mode */
 #define XAE_RAF_EMULTIFLTRENBL_MASK    0x00001000
 #define XAE_RAF_STATSRST_MASK          0x00002000 /* Stats. Counter Reset */
 #define XAE_RAF_RXBADFRMEN_MASK                0x00004000 /* Recv Bad Frame Enable */
index 7526658..dec52b7 100644 (file)
@@ -1615,11 +1615,11 @@ static int geneve_changelink(struct net_device *dev, struct nlattr *tb[],
                             struct netlink_ext_ack *extack)
 {
        struct geneve_dev *geneve = netdev_priv(dev);
+       enum ifla_geneve_df df = geneve->df;
        struct geneve_sock *gs4, *gs6;
        struct ip_tunnel_info info;
        bool metadata;
        bool use_udp6_rx_checksums;
-       enum ifla_geneve_df df;
        bool ttl_inherit;
        int err;
 
@@ -1649,6 +1649,7 @@ static int geneve_changelink(struct net_device *dev, struct nlattr *tb[],
        geneve->collect_md = metadata;
        geneve->use_udp6_rx_checksums = use_udp6_rx_checksums;
        geneve->ttl_inherit = ttl_inherit;
+       geneve->df = df;
        geneve_unquiesce(geneve, gs4, gs6);
 
        return 0;
index 2a6ec53..a4b3fce 100644 (file)
@@ -1242,7 +1242,7 @@ static int rr_open(struct net_device *dev)
                rrpriv->info = NULL;
        }
        if (rrpriv->rx_ctrl) {
-               pci_free_consistent(pdev, sizeof(struct ring_ctrl),
+               pci_free_consistent(pdev, 256 * sizeof(struct ring_ctrl),
                                    rrpriv->rx_ctrl, rrpriv->rx_ctrl_dma);
                rrpriv->rx_ctrl = NULL;
        }
index 5a37514..c11f32f 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Copyright 2009-2017 Analog Devices Inc.
  *
- * http://www.analog.com/ADF7242
+ * https://www.analog.com/ADF7242
  */
 
 #include <linux/kernel.h>
@@ -1262,7 +1262,7 @@ static int adf7242_probe(struct spi_device *spi)
                                             WQ_MEM_RECLAIM);
        if (unlikely(!lp->wqueue)) {
                ret = -ENOMEM;
-               goto err_hw_init;
+               goto err_alloc_wq;
        }
 
        ret = adf7242_hw_init(lp);
@@ -1294,6 +1294,8 @@ static int adf7242_probe(struct spi_device *spi)
        return ret;
 
 err_hw_init:
+       destroy_workqueue(lp->wqueue);
+err_alloc_wq:
        mutex_destroy(&lp->bmux);
        ieee802154_free_hw(lp->hw);
 
index 55226b2..ac7e5a0 100644 (file)
@@ -500,6 +500,13 @@ static int gsi_channel_stop_command(struct gsi_channel *channel)
        int ret;
 
        state = gsi_channel_state(channel);
+
+       /* Channel could have entered STOPPED state since last call
+        * if it timed out.  If so, we're done.
+        */
+       if (state == GSI_CHANNEL_STATE_STOPPED)
+               return 0;
+
        if (state != GSI_CHANNEL_STATE_STARTED &&
            state != GSI_CHANNEL_STATE_STOP_IN_PROC)
                return -EINVAL;
@@ -789,20 +796,11 @@ int gsi_channel_start(struct gsi *gsi, u32 channel_id)
 int gsi_channel_stop(struct gsi *gsi, u32 channel_id)
 {
        struct gsi_channel *channel = &gsi->channel[channel_id];
-       enum gsi_channel_state state;
        u32 retries;
        int ret;
 
        gsi_channel_freeze(channel);
 
-       /* Channel could have entered STOPPED state since last call if the
-        * STOP command timed out.  We won't stop a channel if stopping it
-        * was successful previously (so we still want the freeze above).
-        */
-       state = gsi_channel_state(channel);
-       if (state == GSI_CHANNEL_STATE_STOPPED)
-               return 0;
-
        /* RX channels might require a little time to enter STOPPED state */
        retries = channel->toward_ipa ? 0 : GSI_CHANNEL_STOP_RX_RETRIES;
 
index c9ab865..d92dd3f 100644 (file)
@@ -586,6 +586,21 @@ u32 ipa_cmd_tag_process_count(void)
        return 4;
 }
 
+void ipa_cmd_tag_process(struct ipa *ipa)
+{
+       u32 count = ipa_cmd_tag_process_count();
+       struct gsi_trans *trans;
+
+       trans = ipa_cmd_trans_alloc(ipa, count);
+       if (trans) {
+               ipa_cmd_tag_process_add(trans);
+               gsi_trans_commit_wait(trans);
+       } else {
+               dev_err(&ipa->pdev->dev,
+                       "error allocating %u entry tag transaction\n", count);
+       }
+}
+
 static struct ipa_cmd_info *
 ipa_cmd_info_alloc(struct ipa_endpoint *endpoint, u32 tre_count)
 {
index e440aa6..1a646e0 100644 (file)
@@ -171,6 +171,14 @@ void ipa_cmd_tag_process_add(struct gsi_trans *trans);
  */
 u32 ipa_cmd_tag_process_count(void);
 
+/**
+ * ipa_cmd_tag_process() - Perform a tag process
+ *
+ * @Return:    The number of elements to allocate in a transaction
+ *             to hold tag process commands
+ */
+void ipa_cmd_tag_process(struct ipa *ipa);
+
 /**
  * ipa_cmd_trans_alloc() - Allocate a transaction for the command TX endpoint
  * @ipa:       IPA pointer
index 52d4b84..de2768d 100644 (file)
@@ -44,7 +44,6 @@ static const struct ipa_gsi_endpoint_data ipa_gsi_endpoint_data[] = {
                .endpoint = {
                        .seq_type       = IPA_SEQ_INVALID,
                        .config = {
-                               .checksum       = true,
                                .aggregation    = true,
                                .status_enable  = true,
                                .rx = {
index 9f50d0d..9e58e49 100644 (file)
@@ -1450,6 +1450,8 @@ void ipa_endpoint_suspend(struct ipa *ipa)
        if (ipa->modem_netdev)
                ipa_modem_suspend(ipa->modem_netdev);
 
+       ipa_cmd_tag_process(ipa);
+
        ipa_endpoint_suspend_one(ipa->name_map[IPA_ENDPOINT_AP_LAN_RX]);
        ipa_endpoint_suspend_one(ipa->name_map[IPA_ENDPOINT_AP_COMMAND_TX]);
 }
index dc4a5c2..d323adb 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <linux/types.h>
 
+#include "ipa_gsi.h"
 #include "gsi_trans.h"
 #include "ipa.h"
 #include "ipa_endpoint.h"
index 3cf1860..0a40f3d 100644 (file)
@@ -8,7 +8,9 @@
 
 #include <linux/types.h>
 
+struct gsi;
 struct gsi_trans;
+struct ipa_gsi_endpoint_data;
 
 /**
  * ipa_gsi_trans_complete() - GSI transaction completion callback
index 03a1d0e..7341337 100644 (file)
@@ -119,7 +119,7 @@ struct qmi_elem_info ipa_driver_init_complete_rsp_ei[] = {
                        sizeof_field(struct ipa_driver_init_complete_rsp,
                                     rsp),
                .tlv_type       = 0x02,
-               .elem_size      = offsetof(struct ipa_driver_init_complete_rsp,
+               .offset         = offsetof(struct ipa_driver_init_complete_rsp,
                                           rsp),
                .ei_array       = qmi_response_type_v01_ei,
        },
@@ -137,7 +137,7 @@ struct qmi_elem_info ipa_init_complete_ind_ei[] = {
                        sizeof_field(struct ipa_init_complete_ind,
                                     status),
                .tlv_type       = 0x02,
-               .elem_size      = offsetof(struct ipa_init_complete_ind,
+               .offset         = offsetof(struct ipa_init_complete_ind,
                                           status),
                .ei_array       = qmi_response_type_v01_ei,
        },
@@ -218,7 +218,7 @@ struct qmi_elem_info ipa_init_modem_driver_req_ei[] = {
                        sizeof_field(struct ipa_init_modem_driver_req,
                                     platform_type_valid),
                .tlv_type       = 0x10,
-               .elem_size      = offsetof(struct ipa_init_modem_driver_req,
+               .offset         = offsetof(struct ipa_init_modem_driver_req,
                                           platform_type_valid),
        },
        {
index e56547b..9159846 100644 (file)
@@ -4052,9 +4052,8 @@ static int macsec_newlink(struct net *net, struct net_device *dev,
                return err;
 
        netdev_lockdep_set_classes(dev);
-       lockdep_set_class_and_subclass(&dev->addr_list_lock,
-                                      &macsec_netdev_addr_lock_key,
-                                      dev->lower_level);
+       lockdep_set_class(&dev->addr_list_lock,
+                         &macsec_netdev_addr_lock_key);
 
        err = netdev_upper_dev_link(real_dev, dev, extack);
        if (err < 0)
index 6a6cc9f..4942f61 100644 (file)
@@ -880,9 +880,8 @@ static struct lock_class_key macvlan_netdev_addr_lock_key;
 static void macvlan_set_lockdep_class(struct net_device *dev)
 {
        netdev_lockdep_set_classes(dev);
-       lockdep_set_class_and_subclass(&dev->addr_list_lock,
-                                      &macvlan_netdev_addr_lock_key,
-                                      dev->lower_level);
+       lockdep_set_class(&dev->addr_list_lock,
+                         &macvlan_netdev_addr_lock_key);
 }
 
 static int macvlan_init(struct net_device *dev)
index 2908e0a..23950e7 100644 (file)
@@ -302,7 +302,7 @@ nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port)
        rtnl_lock();
        err = nsim_bpf_init(ns);
        if (err)
-               goto err_free_netdev;
+               goto err_rtnl_unlock;
 
        nsim_ipsec_init(ns);
 
@@ -316,8 +316,8 @@ nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port)
 err_ipsec_teardown:
        nsim_ipsec_teardown(ns);
        nsim_bpf_uninit(ns);
+err_rtnl_unlock:
        rtnl_unlock();
-err_free_netdev:
        free_netdev(dev);
        return ERR_PTR(err);
 }
index f257023..e351d65 100644 (file)
@@ -480,8 +480,7 @@ config MICROCHIP_T1_PHY
 config MICROSEMI_PHY
        tristate "Microsemi PHYs"
        depends on MACSEC || MACSEC=n
-       select CRYPTO_AES
-       select CRYPTO_ECB
+       select CRYPTO_LIB_AES if MACSEC
        help
          Currently supports VSC8514, VSC8530, VSC8531, VSC8540 and VSC8541 PHYs
 
index ecbd5e0..acb0aae 100644 (file)
@@ -1260,6 +1260,7 @@ static int dp83640_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr)
                dp83640->hwts_rx_en = 1;
                dp83640->layer = PTP_CLASS_L4;
                dp83640->version = PTP_CLASS_V1;
+               cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
                break;
        case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
        case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
@@ -1267,6 +1268,7 @@ static int dp83640_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr)
                dp83640->hwts_rx_en = 1;
                dp83640->layer = PTP_CLASS_L4;
                dp83640->version = PTP_CLASS_V2;
+               cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
                break;
        case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
        case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
@@ -1274,6 +1276,7 @@ static int dp83640_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr)
                dp83640->hwts_rx_en = 1;
                dp83640->layer = PTP_CLASS_L2;
                dp83640->version = PTP_CLASS_V2;
+               cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
                break;
        case HWTSTAMP_FILTER_PTP_V2_EVENT:
        case HWTSTAMP_FILTER_PTP_V2_SYNC:
@@ -1281,6 +1284,7 @@ static int dp83640_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr)
                dp83640->hwts_rx_en = 1;
                dp83640->layer = PTP_CLASS_L4 | PTP_CLASS_L2;
                dp83640->version = PTP_CLASS_V2;
+               cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
                break;
        default:
                return -ERANGE;
index b4d3dc4..d53ca88 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/phy.h>
 #include <dt-bindings/net/mscc-phy-vsc8531.h>
 
-#include <crypto/skcipher.h>
+#include <crypto/aes.h>
 
 #include <net/macsec.h>
 
@@ -500,39 +500,17 @@ static u32 vsc8584_macsec_flow_context_id(struct macsec_flow *flow)
 static int vsc8584_macsec_derive_key(const u8 key[MACSEC_KEYID_LEN],
                                     u16 key_len, u8 hkey[16])
 {
-       struct crypto_skcipher *tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0);
-       struct skcipher_request *req = NULL;
-       struct scatterlist src, dst;
-       DECLARE_CRYPTO_WAIT(wait);
-       u32 input[4] = {0};
+       const u8 input[AES_BLOCK_SIZE] = {0};
+       struct crypto_aes_ctx ctx;
        int ret;
 
-       if (IS_ERR(tfm))
-               return PTR_ERR(tfm);
-
-       req = skcipher_request_alloc(tfm, GFP_KERNEL);
-       if (!req) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
-                                     CRYPTO_TFM_REQ_MAY_SLEEP, crypto_req_done,
-                                     &wait);
-       ret = crypto_skcipher_setkey(tfm, key, key_len);
-       if (ret < 0)
-               goto out;
-
-       sg_init_one(&src, input, 16);
-       sg_init_one(&dst, hkey, 16);
-       skcipher_request_set_crypt(req, &src, &dst, 16, NULL);
-
-       ret = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
+       ret = aes_expandkey(&ctx, key, key_len);
+       if (ret)
+               return ret;
 
-out:
-       skcipher_request_free(req);
-       crypto_free_skcipher(tfm);
-       return ret;
+       aes_encrypt(&ctx, hkey, input);
+       memzero_explicit(&ctx, sizeof(ctx));
+       return 0;
 }
 
 static int vsc8584_macsec_transformation(struct phy_device *phydev,
index 1de3938..56cfae9 100644 (file)
@@ -840,7 +840,7 @@ static void phy_error(struct phy_device *phydev)
  * phy_disable_interrupts - Disable the PHY interrupts from the PHY side
  * @phydev: target phy_device struct
  */
-static int phy_disable_interrupts(struct phy_device *phydev)
+int phy_disable_interrupts(struct phy_device *phydev)
 {
        int err;
 
index 04946de..b4978c5 100644 (file)
@@ -794,8 +794,10 @@ static int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id,
 
        /* Grab the bits from PHYIR2, and put them in the lower half */
        phy_reg = mdiobus_read(bus, addr, MII_PHYSID2);
-       if (phy_reg < 0)
-               return -EIO;
+       if (phy_reg < 0) {
+               /* returning -ENODEV doesn't stop bus scanning */
+               return (phy_reg == -EIO || phy_reg == -ENODEV) ? -ENODEV : -EIO;
+       }
 
        *phy_id |= phy_reg;
 
@@ -1090,6 +1092,10 @@ int phy_init_hw(struct phy_device *phydev)
        if (ret < 0)
                return ret;
 
+       ret = phy_disable_interrupts(phydev);
+       if (ret)
+               return ret;
+
        if (phydev->drv->config_init)
                ret = phydev->drv->config_init(phydev);
 
index 0ab65fb..3b7c70e 100644 (file)
@@ -1463,6 +1463,8 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,
                                   struct ethtool_pauseparam *pause)
 {
        struct phylink_link_state *config = &pl->link_config;
+       bool manual_changed;
+       int pause_state;
 
        ASSERT_RTNL();
 
@@ -1477,15 +1479,15 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,
            !pause->autoneg && pause->rx_pause != pause->tx_pause)
                return -EINVAL;
 
-       mutex_lock(&pl->state_mutex);
-       config->pause = 0;
+       pause_state = 0;
        if (pause->autoneg)
-               config->pause |= MLO_PAUSE_AN;
+               pause_state |= MLO_PAUSE_AN;
        if (pause->rx_pause)
-               config->pause |= MLO_PAUSE_RX;
+               pause_state |= MLO_PAUSE_RX;
        if (pause->tx_pause)
-               config->pause |= MLO_PAUSE_TX;
+               pause_state |= MLO_PAUSE_TX;
 
+       mutex_lock(&pl->state_mutex);
        /*
         * See the comments for linkmode_set_pause(), wrt the deficiencies
         * with the current implementation.  A solution to this issue would
@@ -1502,18 +1504,35 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,
        linkmode_set_pause(config->advertising, pause->tx_pause,
                           pause->rx_pause);
 
-       /* If we have a PHY, phylib will call our link state function if the
-        * mode has changed, which will trigger a resolve and update the MAC
-        * configuration.
+       manual_changed = (config->pause ^ pause_state) & MLO_PAUSE_AN ||
+                        (!(pause_state & MLO_PAUSE_AN) &&
+                          (config->pause ^ pause_state) & MLO_PAUSE_TXRX_MASK);
+
+       config->pause = pause_state;
+
+       if (!pl->phydev && !test_bit(PHYLINK_DISABLE_STOPPED,
+                                    &pl->phylink_disable_state))
+               phylink_pcs_config(pl, true, &pl->link_config);
+
+       mutex_unlock(&pl->state_mutex);
+
+       /* If we have a PHY, a change of the pause frame advertisement will
+        * cause phylib to renegotiate (if AN is enabled) which will in turn
+        * call our phylink_phy_change() and trigger a resolve.  Note that
+        * we can't hold our state mutex while calling phy_set_asym_pause().
         */
-       if (pl->phydev) {
+       if (pl->phydev)
                phy_set_asym_pause(pl->phydev, pause->rx_pause,
                                   pause->tx_pause);
-       } else if (!test_bit(PHYLINK_DISABLE_STOPPED,
-                            &pl->phylink_disable_state)) {
-               phylink_pcs_config(pl, true, &pl->link_config);
+
+       /* If the manual pause settings changed, make sure we trigger a
+        * resolve to update their state; we can not guarantee that the
+        * link will cycle.
+        */
+       if (manual_changed) {
+               pl->mac_link_dropped = true;
+               phylink_run_resolve(pl);
        }
-       mutex_unlock(&pl->state_mutex);
 
        return 0;
 }
index 93da7d3..74568ae 100644 (file)
@@ -122,10 +122,13 @@ static int lan87xx_read_status(struct phy_device *phydev)
                if (rc < 0)
                        return rc;
 
-               /* Wait max 640 ms to detect energy */
-               phy_read_poll_timeout(phydev, MII_LAN83C185_CTRL_STATUS, rc,
-                                     rc & MII_LAN83C185_ENERGYON, 10000,
-                                     640000, true);
+               /* Wait max 640 ms to detect energy and the timeout is not
+                * an actual error.
+                */
+               read_poll_timeout(phy_read, rc,
+                                 rc & MII_LAN83C185_ENERGYON || rc < 0,
+                                 10000, 640000, true, phydev,
+                                 MII_LAN83C185_CTRL_STATUS);
                if (rc < 0)
                        return rc;
 
index 858b012..7adeb91 100644 (file)
@@ -62,6 +62,7 @@
 #include <net/rtnetlink.h>
 #include <net/sock.h>
 #include <net/xdp.h>
+#include <net/ip_tunnels.h>
 #include <linux/seq_file.h>
 #include <linux/uio.h>
 #include <linux/skb_array.h>
@@ -1351,6 +1352,7 @@ static void tun_net_init(struct net_device *dev)
        switch (tun->flags & TUN_TYPE_MASK) {
        case IFF_TUN:
                dev->netdev_ops = &tun_netdev_ops;
+               dev->header_ops = &ip_tunnel_header_ops;
 
                /* Point-to-Point TUN Device */
                dev->hard_header_len = 0;
index 4e514f5..fd3a04d 100644 (file)
@@ -187,6 +187,7 @@ static int ax88172a_bind(struct usbnet *dev, struct usb_interface *intf)
        ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf, 0);
        if (ret < ETH_ALEN) {
                netdev_err(dev->net, "Failed to read MAC address: %d\n", ret);
+               ret = -EIO;
                goto free;
        }
        memcpy(dev->net->dev_addr, buf, ETH_ALEN);
index 9507114..a38e868 100644 (file)
@@ -1491,10 +1491,10 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                }
 
                if (pkt_cnt == 0) {
-                       /* Skip IP alignment psudo header */
-                       skb_pull(skb, 2);
                        skb->len = pkt_len;
-                       skb_set_tail_pointer(skb, pkt_len);
+                       /* Skip IP alignment pseudo header */
+                       skb_pull(skb, 2);
+                       skb_set_tail_pointer(skb, skb->len);
                        skb->truesize = pkt_len + sizeof(struct sk_buff);
                        ax88179_rx_checksum(skb, pkt_hdr);
                        return 1;
@@ -1503,8 +1503,9 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                ax_skb = skb_clone(skb, GFP_ATOMIC);
                if (ax_skb) {
                        ax_skb->len = pkt_len;
-                       ax_skb->data = skb->data + 2;
-                       skb_set_tail_pointer(ax_skb, pkt_len);
+                       /* Skip IP alignment pseudo header */
+                       skb_pull(ax_skb, 2);
+                       skb_set_tail_pointer(ax_skb, ax_skb->len);
                        ax_skb->truesize = pkt_len + sizeof(struct sk_buff);
                        ax88179_rx_checksum(ax_skb, pkt_hdr);
                        usbnet_skb_return(dev, ax_skb);
index bb8c34d..5f123a8 100644 (file)
@@ -1390,8 +1390,9 @@ static void hso_serial_set_termios(struct tty_struct *tty, struct ktermios *old)
        unsigned long flags;
 
        if (old)
-               hso_dbg(0x16, "Termios called with: cflags new[%d] - old[%d]\n",
-                       tty->termios.c_cflag, old->c_cflag);
+               hso_dbg(0x16, "Termios called with: cflags new[%u] - old[%u]\n",
+                       (unsigned int)tty->termios.c_cflag,
+                       (unsigned int)old->c_cflag);
 
        /* the actual setup */
        spin_lock_irqsave(&serial->serial_lock, flags);
index 31b1d4b..07c42c0 100644 (file)
@@ -1370,6 +1370,7 @@ static const struct usb_device_id products[] = {
        {QMI_QUIRK_SET_DTR(0x1e0e, 0x9001, 5)}, /* SIMCom 7100E, 7230E, 7600E ++ */
        {QMI_QUIRK_SET_DTR(0x2c7c, 0x0121, 4)}, /* Quectel EC21 Mini PCIe */
        {QMI_QUIRK_SET_DTR(0x2c7c, 0x0191, 4)}, /* Quectel EG91 */
+       {QMI_QUIRK_SET_DTR(0x2c7c, 0x0195, 4)}, /* Quectel EG95 */
        {QMI_FIXED_INTF(0x2c7c, 0x0296, 4)},    /* Quectel BG96 */
        {QMI_QUIRK_SET_DTR(0x2cb7, 0x0104, 4)}, /* Fibocom NL678 series */
        {QMI_FIXED_INTF(0x0489, 0xe0b4, 0)},    /* Foxconn T77W968 LTE */
index 355be77..bb4ccbd 100644 (file)
@@ -1287,11 +1287,14 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
 
        /* Init all registers */
        ret = smsc95xx_reset(dev);
+       if (ret)
+               goto free_pdata;
 
        /* detect device revision as different features may be available */
        ret = smsc95xx_read_reg(dev, ID_REV, &val);
        if (ret < 0)
-               return ret;
+               goto free_pdata;
+
        val >>= 16;
        pdata->chip_id = val;
        pdata->mdix_ctrl = get_mdix_status(dev->net);
@@ -1317,6 +1320,10 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
        schedule_delayed_work(&pdata->carrier_check, CARRIER_CHECK_DELAY);
 
        return 0;
+
+free_pdata:
+       kfree(pdata);
+       return ret;
 }
 
 static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf)
@@ -1324,7 +1331,7 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf)
        struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
 
        if (pdata) {
-               cancel_delayed_work(&pdata->carrier_check);
+               cancel_delayed_work_sync(&pdata->carrier_check);
                netif_dbg(dev, ifdown, dev->net, "free pdata\n");
                kfree(pdata);
                pdata = NULL;
index e8085ab..89d85dc 100644 (file)
@@ -1380,6 +1380,8 @@ static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
                        struct vxlan_rdst *rd;
 
                        if (rcu_access_pointer(f->nh)) {
+                               if (*idx < cb->args[2])
+                                       goto skip_nh;
                                err = vxlan_fdb_info(skb, vxlan, f,
                                                     NETLINK_CB(cb->skb).portid,
                                                     cb->nlh->nlmsg_seq,
@@ -1387,6 +1389,8 @@ static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
                                                     NLM_F_MULTI, NULL);
                                if (err < 0)
                                        goto out;
+skip_nh:
+                               *idx += 1;
                                continue;
                        }
 
index c84536b..f70336b 100644 (file)
@@ -71,8 +71,10 @@ static int x25_data_indication(struct net_device *dev, struct sk_buff *skb)
 {
        unsigned char *ptr;
 
-       if (skb_cow(skb, 1))
+       if (skb_cow(skb, 1)) {
+               kfree_skb(skb);
                return NET_RX_DROP;
+       }
 
        skb_push(skb, 1);
        skb_reset_network_header(skb);
index e30d91a..b286843 100644 (file)
@@ -128,10 +128,12 @@ static int lapbeth_data_indication(struct net_device *dev, struct sk_buff *skb)
 {
        unsigned char *ptr;
 
-       skb_push(skb, 1);
-
-       if (skb_cow(skb, 1))
+       if (skb_cow(skb, 1)) {
+               kfree_skb(skb);
                return NET_RX_DROP;
+       }
+
+       skb_push(skb, 1);
 
        ptr  = skb->data;
        *ptr = X25_IFACE_DATA;
@@ -303,7 +305,6 @@ static void lapbeth_setup(struct net_device *dev)
        dev->netdev_ops      = &lapbeth_netdev_ops;
        dev->needs_free_netdev = true;
        dev->type            = ARPHRD_X25;
-       dev->hard_header_len = 3;
        dev->mtu             = 1000;
        dev->addr_len        = 0;
 }
@@ -324,6 +325,14 @@ static int lapbeth_new_device(struct net_device *dev)
        if (!ndev)
                goto out;
 
+       /* When transmitting data:
+        * first this driver removes a pseudo header of 1 byte,
+        * then the lapb module prepends an LAPB header of at most 3 bytes,
+        * then this driver prepends a length field of 2 bytes,
+        * then the underlying Ethernet device prepends its own header.
+        */
+       ndev->hard_header_len = -1 + 3 + 2 + dev->hard_header_len;
+
        lapbeth = netdev_priv(ndev);
        lapbeth->axdev = ndev;
 
index 69773d2..84640a0 100644 (file)
@@ -183,7 +183,7 @@ static inline void x25_asy_unlock(struct x25_asy *sl)
        netif_wake_queue(sl->dev);
 }
 
-/* Send one completely decapsulated IP datagram to the IP layer. */
+/* Send an LAPB frame to the LAPB module to process. */
 
 static void x25_asy_bump(struct x25_asy *sl)
 {
@@ -195,13 +195,12 @@ static void x25_asy_bump(struct x25_asy *sl)
        count = sl->rcount;
        dev->stats.rx_bytes += count;
 
-       skb = dev_alloc_skb(count+1);
+       skb = dev_alloc_skb(count);
        if (skb == NULL) {
                netdev_warn(sl->dev, "memory squeeze, dropping packet\n");
                dev->stats.rx_dropped++;
                return;
        }
-       skb_push(skb, 1);       /* LAPB internal control */
        skb_put_data(skb, sl->rbuff, count);
        skb->protocol = x25_type_trans(skb, sl->dev);
        err = lapb_data_received(skb->dev, skb);
@@ -209,7 +208,6 @@ static void x25_asy_bump(struct x25_asy *sl)
                kfree_skb(skb);
                printk(KERN_DEBUG "x25_asy: data received err - %d\n", err);
        } else {
-               netif_rx(skb);
                dev->stats.rx_packets++;
        }
 }
@@ -356,12 +354,21 @@ static netdev_tx_t x25_asy_xmit(struct sk_buff *skb,
  */
 
 /*
- *     Called when I frame data arrives. We did the work above - throw it
- *     at the net layer.
+ *     Called when I frame data arrive. We add a pseudo header for upper
+ *     layers and pass it to upper layers.
  */
 
 static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb)
 {
+       if (skb_cow(skb, 1)) {
+               kfree_skb(skb);
+               return NET_RX_DROP;
+       }
+       skb_push(skb, 1);
+       skb->data[0] = X25_IFACE_DATA;
+
+       skb->protocol = x25_type_trans(skb, dev);
+
        return netif_rx(skb);
 }
 
@@ -657,7 +664,7 @@ static void x25_asy_unesc(struct x25_asy *sl, unsigned char s)
        switch (s) {
        case X25_END:
                if (!test_and_clear_bit(SLF_ERROR, &sl->flags) &&
-                   sl->rcount > 2)
+                   sl->rcount >= 2)
                        x25_asy_bump(sl);
                clear_bit(SLF_ESCAPE, &sl->flags);
                sl->rcount = 0;
index 3ac3f85..c9f65e9 100644 (file)
@@ -45,17 +45,18 @@ static int wg_open(struct net_device *dev)
        if (dev_v6)
                dev_v6->cnf.addr_gen_mode = IN6_ADDR_GEN_MODE_NONE;
 
+       mutex_lock(&wg->device_update_lock);
        ret = wg_socket_init(wg, wg->incoming_port);
        if (ret < 0)
-               return ret;
-       mutex_lock(&wg->device_update_lock);
+               goto out;
        list_for_each_entry(peer, &wg->peer_list, peer_list) {
                wg_packet_send_staged_packets(peer);
                if (peer->persistent_keepalive_interval)
                        wg_packet_send_keepalive(peer);
        }
+out:
        mutex_unlock(&wg->device_update_lock);
-       return 0;
+       return ret;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -225,6 +226,7 @@ static void wg_destruct(struct net_device *dev)
        list_del(&wg->device_list);
        rtnl_unlock();
        mutex_lock(&wg->device_update_lock);
+       rcu_assign_pointer(wg->creating_net, NULL);
        wg->incoming_port = 0;
        wg_socket_reinit(wg, NULL, NULL);
        /* The final references are cleared in the below calls to destroy_workqueue. */
@@ -240,13 +242,11 @@ static void wg_destruct(struct net_device *dev)
        skb_queue_purge(&wg->incoming_handshakes);
        free_percpu(dev->tstats);
        free_percpu(wg->incoming_handshakes_worker);
-       if (wg->have_creating_net_ref)
-               put_net(wg->creating_net);
        kvfree(wg->index_hashtable);
        kvfree(wg->peer_hashtable);
        mutex_unlock(&wg->device_update_lock);
 
-       pr_debug("%s: Interface deleted\n", dev->name);
+       pr_debug("%s: Interface destroyed\n", dev->name);
        free_netdev(dev);
 }
 
@@ -262,6 +262,7 @@ static void wg_setup(struct net_device *dev)
                             max(sizeof(struct ipv6hdr), sizeof(struct iphdr));
 
        dev->netdev_ops = &netdev_ops;
+       dev->header_ops = &ip_tunnel_header_ops;
        dev->hard_header_len = 0;
        dev->addr_len = 0;
        dev->needed_headroom = DATA_PACKET_HEAD_ROOM;
@@ -292,7 +293,7 @@ static int wg_newlink(struct net *src_net, struct net_device *dev,
        struct wg_device *wg = netdev_priv(dev);
        int ret = -ENOMEM;
 
-       wg->creating_net = src_net;
+       rcu_assign_pointer(wg->creating_net, src_net);
        init_rwsem(&wg->static_identity.lock);
        mutex_init(&wg->socket_update_lock);
        mutex_init(&wg->device_update_lock);
@@ -393,30 +394,26 @@ static struct rtnl_link_ops link_ops __read_mostly = {
        .newlink                = wg_newlink,
 };
 
-static int wg_netdevice_notification(struct notifier_block *nb,
-                                    unsigned long action, void *data)
+static void wg_netns_pre_exit(struct net *net)
 {
-       struct net_device *dev = ((struct netdev_notifier_info *)data)->dev;
-       struct wg_device *wg = netdev_priv(dev);
-
-       ASSERT_RTNL();
-
-       if (action != NETDEV_REGISTER || dev->netdev_ops != &netdev_ops)
-               return 0;
+       struct wg_device *wg;
 
-       if (dev_net(dev) == wg->creating_net && wg->have_creating_net_ref) {
-               put_net(wg->creating_net);
-               wg->have_creating_net_ref = false;
-       } else if (dev_net(dev) != wg->creating_net &&
-                  !wg->have_creating_net_ref) {
-               wg->have_creating_net_ref = true;
-               get_net(wg->creating_net);
+       rtnl_lock();
+       list_for_each_entry(wg, &device_list, device_list) {
+               if (rcu_access_pointer(wg->creating_net) == net) {
+                       pr_debug("%s: Creating namespace exiting\n", wg->dev->name);
+                       netif_carrier_off(wg->dev);
+                       mutex_lock(&wg->device_update_lock);
+                       rcu_assign_pointer(wg->creating_net, NULL);
+                       wg_socket_reinit(wg, NULL, NULL);
+                       mutex_unlock(&wg->device_update_lock);
+               }
        }
-       return 0;
+       rtnl_unlock();
 }
 
-static struct notifier_block netdevice_notifier = {
-       .notifier_call = wg_netdevice_notification
+static struct pernet_operations pernet_ops = {
+       .pre_exit = wg_netns_pre_exit
 };
 
 int __init wg_device_init(void)
@@ -429,18 +426,18 @@ int __init wg_device_init(void)
                return ret;
 #endif
 
-       ret = register_netdevice_notifier(&netdevice_notifier);
+       ret = register_pernet_device(&pernet_ops);
        if (ret)
                goto error_pm;
 
        ret = rtnl_link_register(&link_ops);
        if (ret)
-               goto error_netdevice;
+               goto error_pernet;
 
        return 0;
 
-error_netdevice:
-       unregister_netdevice_notifier(&netdevice_notifier);
+error_pernet:
+       unregister_pernet_device(&pernet_ops);
 error_pm:
 #ifdef CONFIG_PM_SLEEP
        unregister_pm_notifier(&pm_notifier);
@@ -451,7 +448,7 @@ error_pm:
 void wg_device_uninit(void)
 {
        rtnl_link_unregister(&link_ops);
-       unregister_netdevice_notifier(&netdevice_notifier);
+       unregister_pernet_device(&pernet_ops);
 #ifdef CONFIG_PM_SLEEP
        unregister_pm_notifier(&pm_notifier);
 #endif
index b15a8be..4d0144e 100644 (file)
@@ -40,7 +40,7 @@ struct wg_device {
        struct net_device *dev;
        struct crypt_queue encrypt_queue, decrypt_queue;
        struct sock __rcu *sock4, *sock6;
-       struct net *creating_net;
+       struct net __rcu *creating_net;
        struct noise_static_identity static_identity;
        struct workqueue_struct *handshake_receive_wq, *handshake_send_wq;
        struct workqueue_struct *packet_crypt_wq;
@@ -56,7 +56,6 @@ struct wg_device {
        unsigned int num_peers, device_update_gen;
        u32 fwmark;
        u16 incoming_port;
-       bool have_creating_net_ref;
 };
 
 int wg_device_init(void);
index 802099c..20a4f3c 100644 (file)
@@ -511,11 +511,15 @@ static int wg_set_device(struct sk_buff *skb, struct genl_info *info)
        if (flags & ~__WGDEVICE_F_ALL)
                goto out;
 
-       ret = -EPERM;
-       if ((info->attrs[WGDEVICE_A_LISTEN_PORT] ||
-            info->attrs[WGDEVICE_A_FWMARK]) &&
-           !ns_capable(wg->creating_net->user_ns, CAP_NET_ADMIN))
-               goto out;
+       if (info->attrs[WGDEVICE_A_LISTEN_PORT] || info->attrs[WGDEVICE_A_FWMARK]) {
+               struct net *net;
+               rcu_read_lock();
+               net = rcu_dereference(wg->creating_net);
+               ret = !net || !ns_capable(net->user_ns, CAP_NET_ADMIN) ? -EPERM : 0;
+               rcu_read_unlock();
+               if (ret)
+                       goto out;
+       }
 
        ++wg->device_update_gen;
 
index 6264336..201a226 100644 (file)
@@ -617,8 +617,8 @@ wg_noise_handshake_consume_initiation(struct message_handshake_initiation *src,
        memcpy(handshake->hash, hash, NOISE_HASH_LEN);
        memcpy(handshake->chaining_key, chaining_key, NOISE_HASH_LEN);
        handshake->remote_index = src->sender_index;
-       if ((s64)(handshake->last_initiation_consumption -
-           (initiation_consumption = ktime_get_coarse_boottime_ns())) < 0)
+       initiation_consumption = ktime_get_coarse_boottime_ns();
+       if ((s64)(handshake->last_initiation_consumption - initiation_consumption) < 0)
                handshake->last_initiation_consumption = initiation_consumption;
        handshake->state = HANDSHAKE_CONSUMED_INITIATION;
        up_write(&handshake->lock);
index c58df43..dfb674e 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/skbuff.h>
 #include <linux/ip.h>
 #include <linux/ipv6.h>
+#include <net/ip_tunnels.h>
 
 struct wg_device;
 struct wg_peer;
@@ -65,25 +66,9 @@ struct packet_cb {
 #define PACKET_CB(skb) ((struct packet_cb *)((skb)->cb))
 #define PACKET_PEER(skb) (PACKET_CB(skb)->keypair->entry.peer)
 
-/* Returns either the correct skb->protocol value, or 0 if invalid. */
-static inline __be16 wg_examine_packet_protocol(struct sk_buff *skb)
-{
-       if (skb_network_header(skb) >= skb->head &&
-           (skb_network_header(skb) + sizeof(struct iphdr)) <=
-                   skb_tail_pointer(skb) &&
-           ip_hdr(skb)->version == 4)
-               return htons(ETH_P_IP);
-       if (skb_network_header(skb) >= skb->head &&
-           (skb_network_header(skb) + sizeof(struct ipv6hdr)) <=
-                   skb_tail_pointer(skb) &&
-           ipv6_hdr(skb)->version == 6)
-               return htons(ETH_P_IPV6);
-       return 0;
-}
-
 static inline bool wg_check_packet_protocol(struct sk_buff *skb)
 {
-       __be16 real_protocol = wg_examine_packet_protocol(skb);
+       __be16 real_protocol = ip_tunnel_parse_protocol(skb);
        return real_protocol && skb->protocol == real_protocol;
 }
 
index 9143814..2c9551e 100644 (file)
@@ -387,7 +387,7 @@ static void wg_packet_consume_data_done(struct wg_peer *peer,
         */
        skb->ip_summed = CHECKSUM_UNNECESSARY;
        skb->csum_level = ~0; /* All levels */
-       skb->protocol = wg_examine_packet_protocol(skb);
+       skb->protocol = ip_tunnel_parse_protocol(skb);
        if (skb->protocol == htons(ETH_P_IP)) {
                len = ntohs(ip_hdr(skb)->tot_len);
                if (unlikely(len < sizeof(struct iphdr)))
@@ -414,14 +414,8 @@ static void wg_packet_consume_data_done(struct wg_peer *peer,
        if (unlikely(routed_peer != peer))
                goto dishonest_packet_peer;
 
-       if (unlikely(napi_gro_receive(&peer->napi, skb) == GRO_DROP)) {
-               ++dev->stats.rx_dropped;
-               net_dbg_ratelimited("%s: Failed to give packet to userspace from peer %llu (%pISpfsc)\n",
-                                   dev->name, peer->internal_id,
-                                   &peer->endpoint.addr);
-       } else {
-               update_rx_stats(peer, message_data_len(len_before_trim));
-       }
+       napi_gro_receive(&peer->napi, skb);
+       update_rx_stats(peer, message_data_len(len_before_trim));
        return;
 
 dishonest_packet_peer:
index f901802..c33e2c8 100644 (file)
@@ -347,6 +347,7 @@ static void set_sock_opts(struct socket *sock)
 
 int wg_socket_init(struct wg_device *wg, u16 port)
 {
+       struct net *net;
        int ret;
        struct udp_tunnel_sock_cfg cfg = {
                .sk_user_data = wg,
@@ -371,37 +372,47 @@ int wg_socket_init(struct wg_device *wg, u16 port)
        };
 #endif
 
+       rcu_read_lock();
+       net = rcu_dereference(wg->creating_net);
+       net = net ? maybe_get_net(net) : NULL;
+       rcu_read_unlock();
+       if (unlikely(!net))
+               return -ENONET;
+
 #if IS_ENABLED(CONFIG_IPV6)
 retry:
 #endif
 
-       ret = udp_sock_create(wg->creating_net, &port4, &new4);
+       ret = udp_sock_create(net, &port4, &new4);
        if (ret < 0) {
                pr_err("%s: Could not create IPv4 socket\n", wg->dev->name);
-               return ret;
+               goto out;
        }
        set_sock_opts(new4);
-       setup_udp_tunnel_sock(wg->creating_net, new4, &cfg);
+       setup_udp_tunnel_sock(net, new4, &cfg);
 
 #if IS_ENABLED(CONFIG_IPV6)
        if (ipv6_mod_enabled()) {
                port6.local_udp_port = inet_sk(new4->sk)->inet_sport;
-               ret = udp_sock_create(wg->creating_net, &port6, &new6);
+               ret = udp_sock_create(net, &port6, &new6);
                if (ret < 0) {
                        udp_tunnel_sock_release(new4);
                        if (ret == -EADDRINUSE && !port && retries++ < 100)
                                goto retry;
                        pr_err("%s: Could not create IPv6 socket\n",
                               wg->dev->name);
-                       return ret;
+                       goto out;
                }
                set_sock_opts(new6);
-               setup_udp_tunnel_sock(wg->creating_net, new6, &cfg);
+               setup_udp_tunnel_sock(net, new6, &cfg);
        }
 #endif
 
        wg_socket_reinit(wg, new4->sk, new6 ? new6->sk : NULL);
-       return 0;
+       ret = 0;
+out:
+       put_net(net);
+       return ret;
 }
 
 void wg_socket_reinit(struct wg_device *wg, struct sock *new4,
index 342a7e5..05a6197 100644 (file)
@@ -820,7 +820,7 @@ err_free_irq:
        ath10k_ahb_release_irq_legacy(ar);
 
 err_free_pipes:
-       ath10k_pci_free_pipes(ar);
+       ath10k_pci_release_resource(ar);
 
 err_resource_deinit:
        ath10k_ahb_resource_deinit(ar);
index 1d941d5..cfde779 100644 (file)
@@ -3473,6 +3473,28 @@ int ath10k_pci_setup_resource(struct ath10k *ar)
 
        timer_setup(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, 0);
 
+       ar_pci->attr = kmemdup(pci_host_ce_config_wlan,
+                              sizeof(pci_host_ce_config_wlan),
+                              GFP_KERNEL);
+       if (!ar_pci->attr)
+               return -ENOMEM;
+
+       ar_pci->pipe_config = kmemdup(pci_target_ce_config_wlan,
+                                     sizeof(pci_target_ce_config_wlan),
+                                     GFP_KERNEL);
+       if (!ar_pci->pipe_config) {
+               ret = -ENOMEM;
+               goto err_free_attr;
+       }
+
+       ar_pci->serv_to_pipe = kmemdup(pci_target_service_to_ce_map_wlan,
+                                      sizeof(pci_target_service_to_ce_map_wlan),
+                                      GFP_KERNEL);
+       if (!ar_pci->serv_to_pipe) {
+               ret = -ENOMEM;
+               goto err_free_pipe_config;
+       }
+
        if (QCA_REV_6174(ar) || QCA_REV_9377(ar))
                ath10k_pci_override_ce_config(ar);
 
@@ -3480,18 +3502,31 @@ int ath10k_pci_setup_resource(struct ath10k *ar)
        if (ret) {
                ath10k_err(ar, "failed to allocate copy engine pipes: %d\n",
                           ret);
-               return ret;
+               goto err_free_serv_to_pipe;
        }
 
        return 0;
+
+err_free_serv_to_pipe:
+       kfree(ar_pci->serv_to_pipe);
+err_free_pipe_config:
+       kfree(ar_pci->pipe_config);
+err_free_attr:
+       kfree(ar_pci->attr);
+       return ret;
 }
 
 void ath10k_pci_release_resource(struct ath10k *ar)
 {
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
        ath10k_pci_rx_retry_sync(ar);
        netif_napi_del(&ar->napi);
        ath10k_pci_ce_deinit(ar);
        ath10k_pci_free_pipes(ar);
+       kfree(ar_pci->attr);
+       kfree(ar_pci->pipe_config);
+       kfree(ar_pci->serv_to_pipe);
 }
 
 static const struct ath10k_bus_ops ath10k_pci_bus_ops = {
@@ -3601,30 +3636,6 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
 
        timer_setup(&ar_pci->ps_timer, ath10k_pci_ps_timer, 0);
 
-       ar_pci->attr = kmemdup(pci_host_ce_config_wlan,
-                              sizeof(pci_host_ce_config_wlan),
-                              GFP_KERNEL);
-       if (!ar_pci->attr) {
-               ret = -ENOMEM;
-               goto err_free;
-       }
-
-       ar_pci->pipe_config = kmemdup(pci_target_ce_config_wlan,
-                                     sizeof(pci_target_ce_config_wlan),
-                                     GFP_KERNEL);
-       if (!ar_pci->pipe_config) {
-               ret = -ENOMEM;
-               goto err_free;
-       }
-
-       ar_pci->serv_to_pipe = kmemdup(pci_target_service_to_ce_map_wlan,
-                                      sizeof(pci_target_service_to_ce_map_wlan),
-                                      GFP_KERNEL);
-       if (!ar_pci->serv_to_pipe) {
-               ret = -ENOMEM;
-               goto err_free;
-       }
-
        ret = ath10k_pci_setup_resource(ar);
        if (ret) {
                ath10k_err(ar, "failed to setup resource: %d\n", ret);
@@ -3705,10 +3716,9 @@ err_unsupported:
 
 err_free_irq:
        ath10k_pci_free_irq(ar);
-       ath10k_pci_rx_retry_sync(ar);
 
 err_deinit_irq:
-       ath10k_pci_deinit_irq(ar);
+       ath10k_pci_release_resource(ar);
 
 err_sleep:
        ath10k_pci_sleep_sync(ar);
@@ -3720,29 +3730,18 @@ err_free_pipes:
 err_core_destroy:
        ath10k_core_destroy(ar);
 
-err_free:
-       kfree(ar_pci->attr);
-       kfree(ar_pci->pipe_config);
-       kfree(ar_pci->serv_to_pipe);
-
        return ret;
 }
 
 static void ath10k_pci_remove(struct pci_dev *pdev)
 {
        struct ath10k *ar = pci_get_drvdata(pdev);
-       struct ath10k_pci *ar_pci;
 
        ath10k_dbg(ar, ATH10K_DBG_PCI, "pci remove\n");
 
        if (!ar)
                return;
 
-       ar_pci = ath10k_pci_priv(ar);
-
-       if (!ar_pci)
-               return;
-
        ath10k_core_unregister(ar);
        ath10k_pci_free_irq(ar);
        ath10k_pci_deinit_irq(ar);
@@ -3750,9 +3749,6 @@ static void ath10k_pci_remove(struct pci_dev *pdev)
        ath10k_pci_sleep_sync(ar);
        ath10k_pci_release(ar);
        ath10k_core_destroy(ar);
-       kfree(ar_pci->attr);
-       kfree(ar_pci->pipe_config);
-       kfree(ar_pci->serv_to_pipe);
 }
 
 MODULE_DEVICE_TABLE(pci, ath10k_pci_id_table);
index 4ed21da..3f563e0 100644 (file)
@@ -733,11 +733,13 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
                        return;
                }
 
+               rx_buf->skb = nskb;
+
                usb_fill_int_urb(urb, hif_dev->udev,
                                 usb_rcvintpipe(hif_dev->udev,
                                                 USB_REG_IN_PIPE),
                                 nskb->data, MAX_REG_IN_BUF_SIZE,
-                                ath9k_hif_usb_reg_in_cb, nskb, 1);
+                                ath9k_hif_usb_reg_in_cb, rx_buf, 1);
        }
 
 resubmit:
index bc8c15f..080e5aa 100644 (file)
@@ -897,7 +897,6 @@ static void wil_rx_handle_eapol(struct wil6210_vif *vif, struct sk_buff *skb)
 void wil_netif_rx(struct sk_buff *skb, struct net_device *ndev, int cid,
                  struct wil_net_stats *stats, bool gro)
 {
-       gro_result_t rc = GRO_NORMAL;
        struct wil6210_vif *vif = ndev_to_vif(ndev);
        struct wil6210_priv *wil = ndev_to_wil(ndev);
        struct wireless_dev *wdev = vif_to_wdev(vif);
@@ -908,22 +907,16 @@ void wil_netif_rx(struct sk_buff *skb, struct net_device *ndev, int cid,
         */
        int mcast = is_multicast_ether_addr(da);
        struct sk_buff *xmit_skb = NULL;
-       static const char * const gro_res_str[] = {
-               [GRO_MERGED]            = "GRO_MERGED",
-               [GRO_MERGED_FREE]       = "GRO_MERGED_FREE",
-               [GRO_HELD]              = "GRO_HELD",
-               [GRO_NORMAL]            = "GRO_NORMAL",
-               [GRO_DROP]              = "GRO_DROP",
-               [GRO_CONSUMED]          = "GRO_CONSUMED",
-       };
 
        if (wdev->iftype == NL80211_IFTYPE_STATION) {
                sa = wil_skb_get_sa(skb);
                if (mcast && ether_addr_equal(sa, ndev->dev_addr)) {
                        /* mcast packet looped back to us */
-                       rc = GRO_DROP;
                        dev_kfree_skb(skb);
-                       goto stats;
+                       ndev->stats.rx_dropped++;
+                       stats->rx_dropped++;
+                       wil_dbg_txrx(wil, "Rx drop %d bytes\n", len);
+                       return;
                }
        } else if (wdev->iftype == NL80211_IFTYPE_AP && !vif->ap_isolate) {
                if (mcast) {
@@ -967,26 +960,16 @@ void wil_netif_rx(struct sk_buff *skb, struct net_device *ndev, int cid,
                        wil_rx_handle_eapol(vif, skb);
 
                if (gro)
-                       rc = napi_gro_receive(&wil->napi_rx, skb);
+                       napi_gro_receive(&wil->napi_rx, skb);
                else
                        netif_rx_ni(skb);
-               wil_dbg_txrx(wil, "Rx complete %d bytes => %s\n",
-                            len, gro_res_str[rc]);
-       }
-stats:
-       /* statistics. rc set to GRO_NORMAL for AP bridging */
-       if (unlikely(rc == GRO_DROP)) {
-               ndev->stats.rx_dropped++;
-               stats->rx_dropped++;
-               wil_dbg_txrx(wil, "Rx drop %d bytes\n", len);
-       } else {
-               ndev->stats.rx_packets++;
-               stats->rx_packets++;
-               ndev->stats.rx_bytes += len;
-               stats->rx_bytes += len;
-               if (mcast)
-                       ndev->stats.multicast++;
        }
+       ndev->stats.rx_packets++;
+       stats->rx_packets++;
+       ndev->stats.rx_bytes += len;
+       stats->rx_bytes += len;
+       if (mcast)
+               ndev->stats.multicast++;
 }
 
 void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
index 7987a28..27116c7 100644 (file)
@@ -271,6 +271,8 @@ static int iwl_dbg_tlv_alloc_trigger(struct iwl_trans *trans,
 {
        struct iwl_fw_ini_trigger_tlv *trig = (void *)tlv->data;
        u32 tp = le32_to_cpu(trig->time_point);
+       struct iwl_ucode_tlv *dup = NULL;
+       int ret;
 
        if (le32_to_cpu(tlv->length) < sizeof(*trig))
                return -EINVAL;
@@ -283,10 +285,20 @@ static int iwl_dbg_tlv_alloc_trigger(struct iwl_trans *trans,
                return -EINVAL;
        }
 
-       if (!le32_to_cpu(trig->occurrences))
+       if (!le32_to_cpu(trig->occurrences)) {
+               dup = kmemdup(tlv, sizeof(*tlv) + le32_to_cpu(tlv->length),
+                               GFP_KERNEL);
+               if (!dup)
+                       return -ENOMEM;
+               trig = (void *)dup->data;
                trig->occurrences = cpu_to_le32(-1);
+               tlv = dup;
+       }
+
+       ret = iwl_dbg_tlv_add(tlv, &trans->dbg.time_point[tp].trig_list);
+       kfree(dup);
 
-       return iwl_dbg_tlv_add(tlv, &trans->dbg.time_point[tp].trig_list);
+       return ret;
 }
 
 static int (*dbg_tlv_alloc[])(struct iwl_trans *trans,
index fee01cb..2797799 100644 (file)
@@ -1189,17 +1189,15 @@ static int iwl_mvm_inactivity_check(struct iwl_mvm *mvm, u8 alloc_for_sta)
        for_each_set_bit(i, &changetid_queues, IWL_MAX_HW_QUEUES)
                iwl_mvm_change_queue_tid(mvm, i);
 
+       rcu_read_unlock();
+
        if (free_queue >= 0 && alloc_for_sta != IWL_MVM_INVALID_STA) {
                ret = iwl_mvm_free_inactive_queue(mvm, free_queue, queue_owner,
                                                  alloc_for_sta);
-               if (ret) {
-                       rcu_read_unlock();
+               if (ret)
                        return ret;
-               }
        }
 
-       rcu_read_unlock();
-
        return free_queue;
 }
 
index 65d65c6..e02bafb 100644 (file)
@@ -582,6 +582,8 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
        IWL_DEV_INFO(0x30DC, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name),
        IWL_DEV_INFO(0x31DC, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_name),
        IWL_DEV_INFO(0x31DC, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name),
+       IWL_DEV_INFO(0xA370, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_name),
+       IWL_DEV_INFO(0xA370, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name),
 
        IWL_DEV_INFO(0x271C, 0x0214, iwl9260_2ac_cfg, iwl9260_1_name),
 
index dfe625a..3d7db6f 100644 (file)
@@ -301,6 +301,7 @@ struct mt76_hw_cap {
 #define MT_DRV_TX_ALIGNED4_SKBS                BIT(1)
 #define MT_DRV_SW_RX_AIRTIME           BIT(2)
 #define MT_DRV_RX_DMA_HDR              BIT(3)
+#define MT_DRV_HW_MGMT_TXQ             BIT(4)
 
 struct mt76_driver_ops {
        u32 drv_flags;
index 26cb711..83dfa6d 100644 (file)
@@ -642,8 +642,10 @@ mt7603_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)
 {
        struct mt7603_dev *dev = hw->priv;
 
+       mutex_lock(&dev->mt76.mutex);
        dev->coverage_class = max_t(s16, coverage_class, 0);
        mt7603_mac_set_timing(dev);
+       mutex_unlock(&dev->mt76.mutex);
 }
 
 static void mt7603_tx(struct ieee80211_hw *hw,
index fd3ef48..d06afcf 100644 (file)
@@ -234,10 +234,11 @@ mt7615_queues_acq(struct seq_file *s, void *data)
        int i;
 
        for (i = 0; i < 16; i++) {
-               int j, acs = i / 4, index = i % 4;
+               int j, wmm_idx = i % MT7615_MAX_WMM_SETS;
+               int acs = i / MT7615_MAX_WMM_SETS;
                u32 ctrl, val, qlen = 0;
 
-               val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, index));
+               val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, wmm_idx));
                ctrl = BIT(31) | BIT(15) | (acs << 8);
 
                for (j = 0; j < 32; j++) {
@@ -245,11 +246,11 @@ mt7615_queues_acq(struct seq_file *s, void *data)
                                continue;
 
                        mt76_wr(dev, MT_PLE_FL_Q0_CTRL,
-                               ctrl | (j + (index << 5)));
+                               ctrl | (j + (wmm_idx << 5)));
                        qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL,
                                               GENMASK(11, 0));
                }
-               seq_printf(s, "AC%d%d: queued=%d\n", acs, index, qlen);
+               seq_printf(s, "AC%d%d: queued=%d\n", wmm_idx, acs, qlen);
        }
 
        return 0;
index 5a12461..e5a965d 100644 (file)
@@ -36,10 +36,10 @@ static int
 mt7622_init_tx_queues_multi(struct mt7615_dev *dev)
 {
        static const u8 wmm_queue_map[] = {
-               MT7622_TXQ_AC0,
-               MT7622_TXQ_AC1,
-               MT7622_TXQ_AC2,
-               MT7622_TXQ_AC3,
+               [IEEE80211_AC_BK] = MT7622_TXQ_AC0,
+               [IEEE80211_AC_BE] = MT7622_TXQ_AC1,
+               [IEEE80211_AC_VI] = MT7622_TXQ_AC2,
+               [IEEE80211_AC_VO] = MT7622_TXQ_AC3,
        };
        int ret;
        int i;
@@ -100,6 +100,7 @@ mt7615_tx_cleanup(struct mt7615_dev *dev)
        int i;
 
        mt76_queue_tx_cleanup(dev, MT_TXQ_MCU, false);
+       mt76_queue_tx_cleanup(dev, MT_TXQ_PSD, false);
        if (is_mt7615(&dev->mt76)) {
                mt76_queue_tx_cleanup(dev, MT_TXQ_BE, false);
        } else {
index edac37e..22e4eab 100644 (file)
@@ -72,8 +72,7 @@ static int mt7615_eeprom_load(struct mt7615_dev *dev, u32 addr)
 {
        int ret;
 
-       ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_SIZE +
-                                          MT7615_EEPROM_EXTRA_DATA);
+       ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_FULL_SIZE);
        if (ret < 0)
                return ret;
 
index 40fed7a..a024dee 100644 (file)
@@ -17,7 +17,7 @@
 #define MT7615_EEPROM_TXDPD_SIZE               216
 #define MT7615_EEPROM_TXDPD_COUNT              (44 + 3)
 
-#define MT7615_EEPROM_EXTRA_DATA               (MT7615_EEPROM_TXDPD_OFFSET + \
+#define MT7615_EEPROM_FULL_SIZE                        (MT7615_EEPROM_TXDPD_OFFSET + \
                                                 MT7615_EEPROM_TXDPD_COUNT * \
                                                 MT7615_EEPROM_TXDPD_SIZE)
 
index 9f1c6ca..d97315e 100644 (file)
@@ -526,22 +526,16 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
        fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2;
        fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4;
 
-       if (ieee80211_is_data(fc) || ieee80211_is_bufferable_mmpdu(fc)) {
-               q_idx = wmm_idx * MT7615_MAX_WMM_SETS +
-                       skb_get_queue_mapping(skb);
-               p_fmt = is_usb ? MT_TX_TYPE_SF : MT_TX_TYPE_CT;
-       } else if (beacon) {
-               if (ext_phy)
-                       q_idx = MT_LMAC_BCN1;
-               else
-                       q_idx = MT_LMAC_BCN0;
+       if (beacon) {
                p_fmt = MT_TX_TYPE_FW;
+               q_idx = ext_phy ? MT_LMAC_BCN1 : MT_LMAC_BCN0;
+       } else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) {
+               p_fmt = is_usb ? MT_TX_TYPE_SF : MT_TX_TYPE_CT;
+               q_idx = ext_phy ? MT_LMAC_ALTX1 : MT_LMAC_ALTX0;
        } else {
-               if (ext_phy)
-                       q_idx = MT_LMAC_ALTX1;
-               else
-                       q_idx = MT_LMAC_ALTX0;
                p_fmt = is_usb ? MT_TX_TYPE_SF : MT_TX_TYPE_CT;
+               q_idx = wmm_idx * MT7615_MAX_WMM_SETS +
+                       mt7615_lmac_mapping(dev, skb_get_queue_mapping(skb));
        }
 
        val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) |
index f0d4b29..81608ab 100644 (file)
@@ -124,21 +124,6 @@ enum tx_pkt_type {
        MT_TX_TYPE_FW,
 };
 
-enum tx_pkt_queue_idx {
-       MT_LMAC_AC00,
-       MT_LMAC_AC01,
-       MT_LMAC_AC02,
-       MT_LMAC_AC03,
-       MT_LMAC_ALTX0 = 0x10,
-       MT_LMAC_BMC0,
-       MT_LMAC_BCN0,
-       MT_LMAC_PSMP0,
-       MT_LMAC_ALTX1,
-       MT_LMAC_BMC1,
-       MT_LMAC_BCN1,
-       MT_LMAC_PSMP1,
-};
-
 enum tx_port_idx {
        MT_TX_PORT_IDX_LMAC,
        MT_TX_PORT_IDX_MCU
index c26f99b..beaca81 100644 (file)
@@ -397,6 +397,7 @@ mt7615_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
        struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
        struct mt7615_dev *dev = mt7615_hw_dev(hw);
 
+       queue = mt7615_lmac_mapping(dev, queue);
        queue += mvif->wmm_idx * MT7615_MAX_WMM_SETS;
 
        return mt7615_mcu_set_wmm(dev, queue, params);
@@ -735,9 +736,12 @@ static void
 mt7615_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)
 {
        struct mt7615_phy *phy = mt7615_hw_phy(hw);
+       struct mt7615_dev *dev = phy->dev;
 
+       mutex_lock(&dev->mt76.mutex);
        phy->coverage_class = max_t(s16, coverage_class, 0);
        mt7615_mac_set_timing(phy);
+       mutex_unlock(&dev->mt76.mutex);
 }
 
 static int
index e670393..2e99845 100644 (file)
@@ -146,7 +146,7 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
        static const struct mt76_driver_ops drv_ops = {
                /* txwi_size = txd size + txp size */
                .txwi_size = MT_TXD_SIZE + sizeof(struct mt7615_txp_common),
-               .drv_flags = MT_DRV_TXWI_NO_FREE,
+               .drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ,
                .survey_flags = SURVEY_INFO_TIME_TX |
                                SURVEY_INFO_TIME_RX |
                                SURVEY_INFO_TIME_BSS_RX,
index d6176d3..3e7d51b 100644 (file)
@@ -282,6 +282,21 @@ struct mt7615_dev {
        struct list_head wd_head;
 };
 
+enum tx_pkt_queue_idx {
+       MT_LMAC_AC00,
+       MT_LMAC_AC01,
+       MT_LMAC_AC02,
+       MT_LMAC_AC03,
+       MT_LMAC_ALTX0 = 0x10,
+       MT_LMAC_BMC0,
+       MT_LMAC_BCN0,
+       MT_LMAC_PSMP0,
+       MT_LMAC_ALTX1,
+       MT_LMAC_BMC1,
+       MT_LMAC_BCN1,
+       MT_LMAC_PSMP1,
+};
+
 enum {
        HW_BSSID_0 = 0x0,
        HW_BSSID_1,
@@ -447,6 +462,21 @@ static inline u16 mt7615_wtbl_size(struct mt7615_dev *dev)
                return MT7615_WTBL_SIZE;
 }
 
+static inline u8 mt7615_lmac_mapping(struct mt7615_dev *dev, u8 ac)
+{
+       static const u8 lmac_queue_map[] = {
+               [IEEE80211_AC_BK] = MT_LMAC_AC00,
+               [IEEE80211_AC_BE] = MT_LMAC_AC01,
+               [IEEE80211_AC_VI] = MT_LMAC_AC02,
+               [IEEE80211_AC_VO] = MT_LMAC_AC03,
+       };
+
+       if (WARN_ON_ONCE(ac >= ARRAY_SIZE(lmac_queue_map)))
+               return MT_LMAC_AC01; /* BE */
+
+       return lmac_queue_map[ac];
+}
+
 void mt7615_dma_reset(struct mt7615_dev *dev);
 void mt7615_scan_work(struct work_struct *work);
 void mt7615_roc_work(struct work_struct *work);
index a50077e..5be6704 100644 (file)
@@ -270,7 +270,7 @@ static int mt7663u_probe(struct usb_interface *usb_intf,
 {
        static const struct mt76_driver_ops drv_ops = {
                .txwi_size = MT_USB_TXD_SIZE,
-               .drv_flags = MT_DRV_RX_DMA_HDR,
+               .drv_flags = MT_DRV_RX_DMA_HDR | MT_DRV_HW_MGMT_TXQ,
                .tx_prepare_skb = mt7663u_tx_prepare_skb,
                .tx_complete_skb = mt7663u_tx_complete_skb,
                .tx_status_data = mt7663u_tx_status_data,
@@ -329,25 +329,26 @@ static int mt7663u_probe(struct usb_interface *usb_intf,
        if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON,
                            FW_STATE_PWR_ON << 1, 500)) {
                dev_err(dev->mt76.dev, "Timeout for power on\n");
-               return -EIO;
+               ret = -EIO;
+               goto error;
        }
 
 alloc_queues:
        ret = mt76u_alloc_mcu_queue(&dev->mt76);
        if (ret)
-               goto error;
+               goto error_free_q;
 
        ret = mt76u_alloc_queues(&dev->mt76);
        if (ret)
-               goto error;
+               goto error_free_q;
 
        ret = mt7663u_register_device(dev);
        if (ret)
-               goto error_freeq;
+               goto error_free_q;
 
        return 0;
 
-error_freeq:
+error_free_q:
        mt76u_queues_deinit(&dev->mt76);
 error:
        mt76u_deinit(&dev->mt76);
index cbbe986..5fda6e7 100644 (file)
@@ -456,8 +456,9 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
        tasklet_disable(&dev->mt76.tx_tasklet);
        napi_disable(&dev->mt76.tx_napi);
 
-       for (i = 0; i < ARRAY_SIZE(dev->mt76.napi); i++)
+       mt76_for_each_q_rx(&dev->mt76, i) {
                napi_disable(&dev->mt76.napi[i]);
+       }
 
        mutex_lock(&dev->mt76.mutex);
 
@@ -515,7 +516,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
 
        tasklet_enable(&dev->mt76.pre_tbtt_tasklet);
 
-       for (i = 0; i < ARRAY_SIZE(dev->mt76.napi); i++) {
+       mt76_for_each_q_rx(&dev->mt76, i) {
                napi_enable(&dev->mt76.napi[i]);
                napi_schedule(&dev->mt76.napi[i]);
        }
index 0575c25..05b5650 100644 (file)
@@ -716,9 +716,12 @@ static void
 mt7915_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)
 {
        struct mt7915_phy *phy = mt7915_hw_phy(hw);
+       struct mt7915_dev *dev = phy->dev;
 
+       mutex_lock(&dev->mt76.mutex);
        phy->coverage_class = max_t(s16, coverage_class, 0);
        mt7915_mac_set_timing(phy);
+       mutex_unlock(&dev->mt76.mutex);
 }
 
 static int
index fca38ea..f10c98a 100644 (file)
@@ -264,6 +264,13 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
                skb_set_queue_mapping(skb, qid);
        }
 
+       if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) &&
+           !ieee80211_is_data(hdr->frame_control) &&
+           !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) {
+               qid = MT_TXQ_PSD;
+               skb_set_queue_mapping(skb, qid);
+       }
+
        if (!(wcid->tx_info & MT_WCID_TX_INFO_SET))
                ieee80211_get_tx_rates(info->control.vif, sta, skb,
                                       info->control.rates, 1);
index fb97ea2..87382b2 100644 (file)
@@ -1010,17 +1010,18 @@ static void mt76u_tx_kick(struct mt76_dev *dev, struct mt76_queue *q)
 static u8 mt76u_ac_to_hwq(struct mt76_dev *dev, u8 ac)
 {
        if (mt76_chip(dev) == 0x7663) {
-               static const u8 wmm_queue_map[] = {
-                       [IEEE80211_AC_VO] = 0,
-                       [IEEE80211_AC_VI] = 1,
-                       [IEEE80211_AC_BE] = 2,
-                       [IEEE80211_AC_BK] = 4,
+               static const u8 lmac_queue_map[] = {
+                       /* ac to lmac mapping */
+                       [IEEE80211_AC_BK] = 0,
+                       [IEEE80211_AC_BE] = 1,
+                       [IEEE80211_AC_VI] = 2,
+                       [IEEE80211_AC_VO] = 4,
                };
 
-               if (WARN_ON(ac >= ARRAY_SIZE(wmm_queue_map)))
-                       return 2; /* BE */
+               if (WARN_ON(ac >= ARRAY_SIZE(lmac_queue_map)))
+                       return 1; /* BE */
 
-               return wmm_queue_map[ac];
+               return lmac_queue_map[ac];
        }
 
        return mt76_ac_to_hwq(ac);
@@ -1066,11 +1067,16 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)
 
 static void mt76u_free_tx(struct mt76_dev *dev)
 {
-       struct mt76_queue *q;
-       int i, j;
+       int i;
 
        for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+               struct mt76_queue *q;
+               int j;
+
                q = dev->q_tx[i].q;
+               if (!q)
+                       continue;
+
                for (j = 0; j < q->ndesc; j++)
                        usb_free_urb(q->entry[j].urb);
        }
@@ -1078,17 +1084,22 @@ static void mt76u_free_tx(struct mt76_dev *dev)
 
 void mt76u_stop_tx(struct mt76_dev *dev)
 {
-       struct mt76_queue_entry entry;
-       struct mt76_queue *q;
-       int i, j, ret;
+       int ret;
 
        ret = wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(&dev->phy),
                                 HZ / 5);
        if (!ret) {
+               struct mt76_queue_entry entry;
+               struct mt76_queue *q;
+               int i, j;
+
                dev_err(dev->dev, "timed out waiting for pending tx\n");
 
                for (i = 0; i < IEEE80211_NUM_ACS; i++) {
                        q = dev->q_tx[i].q;
+                       if (!q)
+                               continue;
+
                        for (j = 0; j < q->ndesc; j++)
                                usb_kill_urb(q->entry[j].urb);
                }
@@ -1100,6 +1111,8 @@ void mt76u_stop_tx(struct mt76_dev *dev)
                 */
                for (i = 0; i < IEEE80211_NUM_ACS; i++) {
                        q = dev->q_tx[i].q;
+                       if (!q)
+                               continue;
 
                        /* Assure we are in sync with killed tasklet. */
                        spin_lock_bh(&q->lock);
index 482c6c8..8828005 100644 (file)
@@ -63,6 +63,8 @@ module_param_named(max_queues, xennet_max_queues, uint, 0644);
 MODULE_PARM_DESC(max_queues,
                 "Maximum number of queues per virtual interface");
 
+#define XENNET_TIMEOUT  (5 * HZ)
+
 static const struct ethtool_ops xennet_ethtool_ops;
 
 struct netfront_cb {
@@ -1334,12 +1336,15 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
 
        netif_carrier_off(netdev);
 
-       xenbus_switch_state(dev, XenbusStateInitialising);
-       wait_event(module_wq,
-                  xenbus_read_driver_state(dev->otherend) !=
-                  XenbusStateClosed &&
-                  xenbus_read_driver_state(dev->otherend) !=
-                  XenbusStateUnknown);
+       do {
+               xenbus_switch_state(dev, XenbusStateInitialising);
+               err = wait_event_timeout(module_wq,
+                                xenbus_read_driver_state(dev->otherend) !=
+                                XenbusStateClosed &&
+                                xenbus_read_driver_state(dev->otherend) !=
+                                XenbusStateUnknown, XENNET_TIMEOUT);
+       } while (!err);
+
        return netdev;
 
  exit:
@@ -2139,28 +2144,43 @@ static const struct attribute_group xennet_dev_group = {
 };
 #endif /* CONFIG_SYSFS */
 
-static int xennet_remove(struct xenbus_device *dev)
+static void xennet_bus_close(struct xenbus_device *dev)
 {
-       struct netfront_info *info = dev_get_drvdata(&dev->dev);
-
-       dev_dbg(&dev->dev, "%s\n", dev->nodename);
+       int ret;
 
-       if (xenbus_read_driver_state(dev->otherend) != XenbusStateClosed) {
+       if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed)
+               return;
+       do {
                xenbus_switch_state(dev, XenbusStateClosing);
-               wait_event(module_wq,
-                          xenbus_read_driver_state(dev->otherend) ==
-                          XenbusStateClosing ||
-                          xenbus_read_driver_state(dev->otherend) ==
-                          XenbusStateUnknown);
+               ret = wait_event_timeout(module_wq,
+                                  xenbus_read_driver_state(dev->otherend) ==
+                                  XenbusStateClosing ||
+                                  xenbus_read_driver_state(dev->otherend) ==
+                                  XenbusStateClosed ||
+                                  xenbus_read_driver_state(dev->otherend) ==
+                                  XenbusStateUnknown,
+                                  XENNET_TIMEOUT);
+       } while (!ret);
+
+       if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed)
+               return;
 
+       do {
                xenbus_switch_state(dev, XenbusStateClosed);
-               wait_event(module_wq,
-                          xenbus_read_driver_state(dev->otherend) ==
-                          XenbusStateClosed ||
-                          xenbus_read_driver_state(dev->otherend) ==
-                          XenbusStateUnknown);
-       }
+               ret = wait_event_timeout(module_wq,
+                                  xenbus_read_driver_state(dev->otherend) ==
+                                  XenbusStateClosed ||
+                                  xenbus_read_driver_state(dev->otherend) ==
+                                  XenbusStateUnknown,
+                                  XENNET_TIMEOUT);
+       } while (!ret);
+}
+
+static int xennet_remove(struct xenbus_device *dev)
+{
+       struct netfront_info *info = dev_get_drvdata(&dev->dev);
 
+       xennet_bus_close(dev);
        xennet_disconnect_backend(info);
 
        if (info->netdev->reg_state == NETREG_REGISTERED)
index 91d4d5b..ba6c486 100644 (file)
@@ -198,6 +198,7 @@ int s3fwrn5_recv_frame(struct nci_dev *ndev, struct sk_buff *skb,
        case S3FWRN5_MODE_FW:
                return s3fwrn5_fw_recv_frame(ndev, skb);
        default:
+               kfree_skb(skb);
                return -ENODEV;
        }
 }
index ccbb5b4..4502f9c 100644 (file)
@@ -679,18 +679,8 @@ static umode_t region_visible(struct kobject *kobj, struct attribute *a, int n)
                return a->mode;
        }
 
-       if (a == &dev_attr_align.attr) {
-               int i;
-
-               for (i = 0; i < nd_region->ndr_mappings; i++) {
-                       struct nd_mapping *nd_mapping = &nd_region->mapping[i];
-                       struct nvdimm *nvdimm = nd_mapping->nvdimm;
-
-                       if (test_bit(NDD_LABELING, &nvdimm->flags))
-                               return a->mode;
-               }
-               return 0;
-       }
+       if (a == &dev_attr_align.attr)
+               return a->mode;
 
        if (a != &dev_attr_set_cookie.attr
                        && a != &dev_attr_available_size.attr)
index 89b8597..4cef69b 100644 (file)
@@ -95,7 +95,7 @@ static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm,
        struct encrypted_key_payload *epayload;
        struct device *dev = &nvdimm->dev;
 
-       keyref = lookup_user_key(id, 0, 0);
+       keyref = lookup_user_key(id, 0, KEY_NEED_SEARCH);
        if (IS_ERR(keyref))
                return NULL;
 
index c2c5bc4..4ee2330 100644 (file)
@@ -1102,6 +1102,9 @@ static int nvme_identify_ns_descs(struct nvme_ctrl *ctrl, unsigned nsid,
        int pos;
        int len;
 
+       if (ctrl->quirks & NVME_QUIRK_NO_NS_DESC_LIST)
+               return 0;
+
        c.identify.opcode = nvme_admin_identify;
        c.identify.nsid = cpu_to_le32(nsid);
        c.identify.cns = NVME_ID_CNS_NS_DESC_LIST;
@@ -1115,12 +1118,6 @@ static int nvme_identify_ns_descs(struct nvme_ctrl *ctrl, unsigned nsid,
        if (status) {
                dev_warn(ctrl->device,
                        "Identify Descriptors failed (%d)\n", status);
-                /*
-                 * Don't treat an error as fatal, as we potentially already
-                 * have a NGUID or EUI-64.
-                 */
-               if (status > 0 && !(status & NVME_SC_DNR))
-                       status = 0;
                goto free_data;
        }
 
@@ -1974,7 +1971,7 @@ static int __nvme_revalidate_disk(struct gendisk *disk, struct nvme_id_ns *id)
        if (ns->head->disk) {
                nvme_update_disk_info(ns->head->disk, ns, id);
                blk_queue_stack_limits(ns->head->disk->queue, ns->queue);
-               revalidate_disk(ns->head->disk);
+               nvme_mpath_update_disk_size(ns->head->disk);
        }
 #endif
        return 0;
@@ -4174,6 +4171,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
        ctrl->dev = dev;
        ctrl->ops = ops;
        ctrl->quirks = quirks;
+       ctrl->numa_node = NUMA_NO_NODE;
        INIT_WORK(&ctrl->scan_work, nvme_scan_work);
        INIT_WORK(&ctrl->async_event_work, nvme_async_event_work);
        INIT_WORK(&ctrl->fw_act_work, nvme_fw_act_work);
index da78e49..6650947 100644 (file)
@@ -409,15 +409,14 @@ static void nvme_mpath_set_live(struct nvme_ns *ns)
 {
        struct nvme_ns_head *head = ns->head;
 
-       lockdep_assert_held(&ns->head->lock);
-
        if (!head->disk)
                return;
 
-       if (!(head->disk->flags & GENHD_FL_UP))
+       if (!test_and_set_bit(NVME_NSHEAD_DISK_LIVE, &head->flags))
                device_add_disk(&head->subsys->dev, head->disk,
                                nvme_ns_id_attr_groups);
 
+       mutex_lock(&head->lock);
        if (nvme_path_is_optimized(ns)) {
                int node, srcu_idx;
 
@@ -426,9 +425,10 @@ static void nvme_mpath_set_live(struct nvme_ns *ns)
                        __nvme_find_path(head, node);
                srcu_read_unlock(&head->srcu, srcu_idx);
        }
+       mutex_unlock(&head->lock);
 
-       synchronize_srcu(&ns->head->srcu);
-       kblockd_schedule_work(&ns->head->requeue_work);
+       synchronize_srcu(&head->srcu);
+       kblockd_schedule_work(&head->requeue_work);
 }
 
 static int nvme_parse_ana_log(struct nvme_ctrl *ctrl, void *data,
@@ -483,14 +483,12 @@ static inline bool nvme_state_is_live(enum nvme_ana_state state)
 static void nvme_update_ns_ana_state(struct nvme_ana_group_desc *desc,
                struct nvme_ns *ns)
 {
-       mutex_lock(&ns->head->lock);
        ns->ana_grpid = le32_to_cpu(desc->grpid);
        ns->ana_state = desc->state;
        clear_bit(NVME_NS_ANA_PENDING, &ns->flags);
 
        if (nvme_state_is_live(ns->ana_state))
                nvme_mpath_set_live(ns);
-       mutex_unlock(&ns->head->lock);
 }
 
 static int nvme_update_ana_state(struct nvme_ctrl *ctrl,
@@ -640,38 +638,45 @@ static ssize_t ana_state_show(struct device *dev, struct device_attribute *attr,
 }
 DEVICE_ATTR_RO(ana_state);
 
-static int nvme_set_ns_ana_state(struct nvme_ctrl *ctrl,
+static int nvme_lookup_ana_group_desc(struct nvme_ctrl *ctrl,
                struct nvme_ana_group_desc *desc, void *data)
 {
-       struct nvme_ns *ns = data;
+       struct nvme_ana_group_desc *dst = data;
 
-       if (ns->ana_grpid == le32_to_cpu(desc->grpid)) {
-               nvme_update_ns_ana_state(desc, ns);
-               return -ENXIO; /* just break out of the loop */
-       }
+       if (desc->grpid != dst->grpid)
+               return 0;
 
-       return 0;
+       *dst = *desc;
+       return -ENXIO; /* just break out of the loop */
 }
 
 void nvme_mpath_add_disk(struct nvme_ns *ns, struct nvme_id_ns *id)
 {
        if (nvme_ctrl_use_ana(ns->ctrl)) {
+               struct nvme_ana_group_desc desc = {
+                       .grpid = id->anagrpid,
+                       .state = 0,
+               };
+
                mutex_lock(&ns->ctrl->ana_lock);
                ns->ana_grpid = le32_to_cpu(id->anagrpid);
-               nvme_parse_ana_log(ns->ctrl, ns, nvme_set_ns_ana_state);
+               nvme_parse_ana_log(ns->ctrl, &desc, nvme_lookup_ana_group_desc);
                mutex_unlock(&ns->ctrl->ana_lock);
+               if (desc.state) {
+                       /* found the group desc: update */
+                       nvme_update_ns_ana_state(&desc, ns);
+               }
        } else {
-               mutex_lock(&ns->head->lock);
                ns->ana_state = NVME_ANA_OPTIMIZED; 
                nvme_mpath_set_live(ns);
-               mutex_unlock(&ns->head->lock);
        }
 
        if (bdi_cap_stable_pages_required(ns->queue->backing_dev_info)) {
-               struct backing_dev_info *info =
-                                       ns->head->disk->queue->backing_dev_info;
+               struct gendisk *disk = ns->head->disk;
 
-               info->capabilities |= BDI_CAP_STABLE_WRITES;
+               if (disk)
+                       disk->queue->backing_dev_info->capabilities |=
+                                       BDI_CAP_STABLE_WRITES;
        }
 }
 
@@ -686,6 +691,14 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head)
        kblockd_schedule_work(&head->requeue_work);
        flush_work(&head->requeue_work);
        blk_cleanup_queue(head->disk->queue);
+       if (!test_bit(NVME_NSHEAD_DISK_LIVE, &head->flags)) {
+               /*
+                * if device_add_disk wasn't called, prevent
+                * disk release to put a bogus reference on the
+                * request queue
+                */
+               head->disk->queue = NULL;
+       }
        put_disk(head->disk);
 }
 
index c0f4226..09ffc32 100644 (file)
@@ -129,6 +129,13 @@ enum nvme_quirks {
         * Don't change the value of the temperature threshold feature
         */
        NVME_QUIRK_NO_TEMP_THRESH_CHANGE        = (1 << 14),
+
+       /*
+        * The controller doesn't handle the Identify Namespace
+        * Identification Descriptor list subcommand despite claiming
+        * NVMe 1.3 compliance.
+        */
+       NVME_QUIRK_NO_NS_DESC_LIST              = (1 << 15),
 };
 
 /*
@@ -364,6 +371,8 @@ struct nvme_ns_head {
        spinlock_t              requeue_lock;
        struct work_struct      requeue_work;
        struct mutex            lock;
+       unsigned long           flags;
+#define NVME_NSHEAD_DISK_LIVE  0
        struct nvme_ns __rcu    *current_path[];
 #endif
 };
@@ -602,6 +611,16 @@ static inline void nvme_trace_bio_complete(struct request *req,
                trace_block_bio_complete(ns->head->disk->queue, req->bio);
 }
 
+static inline void nvme_mpath_update_disk_size(struct gendisk *disk)
+{
+       struct block_device *bdev = bdget_disk(disk, 0);
+
+       if (bdev) {
+               bd_set_size(bdev, get_capacity(disk) << SECTOR_SHIFT);
+               bdput(bdev);
+       }
+}
+
 extern struct device_attribute dev_attr_ana_grpid;
 extern struct device_attribute dev_attr_ana_state;
 extern struct device_attribute subsys_attr_iopolicy;
@@ -677,6 +696,9 @@ static inline void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys)
 static inline void nvme_mpath_start_freeze(struct nvme_subsystem *subsys)
 {
 }
+static inline void nvme_mpath_update_disk_size(struct gendisk *disk)
+{
+}
 #endif /* CONFIG_NVME_MULTIPATH */
 
 #ifdef CONFIG_NVM
index e2bacd3..d4b1ff7 100644 (file)
@@ -1593,7 +1593,7 @@ static int nvme_alloc_admin_tags(struct nvme_dev *dev)
 
                dev->admin_tagset.queue_depth = NVME_AQ_MQ_TAG_DEPTH;
                dev->admin_tagset.timeout = ADMIN_TIMEOUT;
-               dev->admin_tagset.numa_node = dev_to_node(dev->dev);
+               dev->admin_tagset.numa_node = dev->ctrl.numa_node;
                dev->admin_tagset.cmd_size = sizeof(struct nvme_iod);
                dev->admin_tagset.flags = BLK_MQ_F_NO_SCHED;
                dev->admin_tagset.driver_data = dev;
@@ -1669,6 +1669,8 @@ static int nvme_pci_configure_admin_queue(struct nvme_dev *dev)
        if (result)
                return result;
 
+       dev->ctrl.numa_node = dev_to_node(dev->dev);
+
        nvmeq = &dev->queues[0];
        aqa = nvmeq->q_depth - 1;
        aqa |= aqa << 16;
@@ -2257,7 +2259,7 @@ static void nvme_dev_add(struct nvme_dev *dev)
                if (dev->io_queues[HCTX_TYPE_POLL])
                        dev->tagset.nr_maps++;
                dev->tagset.timeout = NVME_IO_TIMEOUT;
-               dev->tagset.numa_node = dev_to_node(dev->dev);
+               dev->tagset.numa_node = dev->ctrl.numa_node;
                dev->tagset.queue_depth =
                                min_t(int, dev->q_depth, BLK_MQ_MAX_DEPTH) - 1;
                dev->tagset.cmd_size = sizeof(struct nvme_iod);
@@ -3097,6 +3099,8 @@ static const struct pci_device_id nvme_id_table[] = {
        { PCI_VDEVICE(INTEL, 0x5845),   /* Qemu emulated controller */
                .driver_data = NVME_QUIRK_IDENTIFY_CNS |
                                NVME_QUIRK_DISABLE_WRITE_ZEROES, },
+       { PCI_DEVICE(0x126f, 0x2263),   /* Silicon Motion unidentified */
+               .driver_data = NVME_QUIRK_NO_NS_DESC_LIST, },
        { PCI_DEVICE(0x1bb1, 0x0100),   /* Seagate Nytro Flash Storage */
                .driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, },
        { PCI_DEVICE(0x1c58, 0x0003),   /* HGST adapter */
@@ -3120,6 +3124,8 @@ static const struct pci_device_id nvme_id_table[] = {
        { PCI_DEVICE(0x1cc1, 0x8201),   /* ADATA SX8200PNP 512GB */
                .driver_data = NVME_QUIRK_NO_DEEPEST_PS |
                                NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+       { PCI_DEVICE(0x1c5c, 0x1504),   /* SK Hynix PC400 */
+               .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
        { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
        { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001),
                .driver_data = NVME_QUIRK_SINGLE_VECTOR },
index f8f856d..13506a8 100644 (file)
@@ -470,7 +470,7 @@ static int nvme_rdma_create_queue_ib(struct nvme_rdma_queue *queue)
         * Spread I/O queues completion vectors according their queue index.
         * Admin queues can always go on completion vector 0.
         */
-       comp_vector = idx == 0 ? idx : idx - 1;
+       comp_vector = (idx == 0 ? idx : idx - 1) % ibdev->num_comp_vectors;
 
        /* Polling queues need direct cq polling context */
        if (nvme_rdma_poll_queue(queue))
index 3345ec7..f3a9181 100644 (file)
@@ -1382,6 +1382,9 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl,
        if (nctrl->opts->tos >= 0)
                ip_sock_set_tos(queue->sock->sk, nctrl->opts->tos);
 
+       /* Set 10 seconds timeout for icresp recvmsg */
+       queue->sock->sk->sk_rcvtimeo = 10 * HZ;
+
        queue->sock->sk->sk_allocation = GFP_ATOMIC;
        nvme_tcp_set_queue_io_cpu(queue);
        queue->request = NULL;
@@ -1532,7 +1535,7 @@ static struct blk_mq_tag_set *nvme_tcp_alloc_tagset(struct nvme_ctrl *nctrl,
                set->ops = &nvme_tcp_admin_mq_ops;
                set->queue_depth = NVME_AQ_MQ_TAG_DEPTH;
                set->reserved_tags = 2; /* connect + keep-alive */
-               set->numa_node = NUMA_NO_NODE;
+               set->numa_node = nctrl->numa_node;
                set->flags = BLK_MQ_F_BLOCKING;
                set->cmd_size = sizeof(struct nvme_tcp_request);
                set->driver_data = ctrl;
@@ -1544,7 +1547,7 @@ static struct blk_mq_tag_set *nvme_tcp_alloc_tagset(struct nvme_ctrl *nctrl,
                set->ops = &nvme_tcp_mq_ops;
                set->queue_depth = nctrl->sqsize + 1;
                set->reserved_tags = 1; /* fabric connect */
-               set->numa_node = NUMA_NO_NODE;
+               set->numa_node = nctrl->numa_node;
                set->flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING;
                set->cmd_size = sizeof(struct nvme_tcp_request);
                set->driver_data = ctrl;
index 0d54e73..6344e73 100644 (file)
@@ -340,7 +340,7 @@ static int nvme_loop_configure_admin_queue(struct nvme_loop_ctrl *ctrl)
        ctrl->admin_tag_set.ops = &nvme_loop_admin_mq_ops;
        ctrl->admin_tag_set.queue_depth = NVME_AQ_MQ_TAG_DEPTH;
        ctrl->admin_tag_set.reserved_tags = 2; /* connect + keep-alive */
-       ctrl->admin_tag_set.numa_node = NUMA_NO_NODE;
+       ctrl->admin_tag_set.numa_node = ctrl->ctrl.numa_node;
        ctrl->admin_tag_set.cmd_size = sizeof(struct nvme_loop_iod) +
                NVME_INLINE_SG_CNT * sizeof(struct scatterlist);
        ctrl->admin_tag_set.driver_data = ctrl;
@@ -512,7 +512,7 @@ static int nvme_loop_create_io_queues(struct nvme_loop_ctrl *ctrl)
        ctrl->tag_set.ops = &nvme_loop_mq_ops;
        ctrl->tag_set.queue_depth = ctrl->ctrl.opts->queue_size;
        ctrl->tag_set.reserved_tags = 1; /* fabric connect */
-       ctrl->tag_set.numa_node = NUMA_NO_NODE;
+       ctrl->tag_set.numa_node = ctrl->ctrl.numa_node;
        ctrl->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
        ctrl->tag_set.cmd_size = sizeof(struct nvme_loop_iod) +
                NVME_INLINE_SG_CNT * sizeof(struct scatterlist);
index a04afe7..ef6f818 100644 (file)
@@ -314,10 +314,15 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
                                 child, addr);
 
                        if (of_mdiobus_child_is_phy(child)) {
+                               /* -ENODEV is the return code that PHYLIB has
+                                * standardized on to indicate that bus
+                                * scanning should continue.
+                                */
                                rc = of_mdiobus_register_phy(mdio, child, addr);
-                               if (rc && rc != -ENODEV)
+                               if (!rc)
+                                       break;
+                               if (rc != -ENODEV)
                                        goto unregister;
-                               break;
                        }
                }
        }
index 9a58735..314f306 100644 (file)
@@ -902,6 +902,10 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table)
                return -EINVAL;
        }
 
+       mutex_lock(&opp_table->lock);
+       opp_table->parsed_static_opps = 1;
+       mutex_unlock(&opp_table->lock);
+
        val = prop->value;
        while (nr) {
                unsigned long freq = be32_to_cpup(val++) * 1000;
index e1d097e..31478c0 100644 (file)
@@ -33,7 +33,7 @@ void flush_cpu_work(void);
 struct op_sample {
        unsigned long eip;
        unsigned long event;
-       unsigned long data[0];
+       unsigned long data[];
 };
 
 struct op_entry;
index e386d4e..9a64cf9 100644 (file)
@@ -546,9 +546,10 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
 
        vmd->irq_domain = pci_msi_create_irq_domain(fn, &vmd_msi_domain_info,
                                                    x86_vector_domain);
-       irq_domain_free_fwnode(fn);
-       if (!vmd->irq_domain)
+       if (!vmd->irq_domain) {
+               irq_domain_free_fwnode(fn);
                return -ENODEV;
+       }
 
        pci_add_resource(&resources, &vmd->resources[0]);
        pci_add_resource_offset(&resources, &vmd->resources[1], offset[0]);
index ce09627..c9338f9 100644 (file)
@@ -4638,8 +4638,7 @@ static int pci_pm_reset(struct pci_dev *dev, int probe)
  * pcie_wait_for_link_delay - Wait until link is active or inactive
  * @pdev: Bridge device
  * @active: waiting for active or inactive?
- * @delay: Delay to wait after link has become active (in ms). Specify %0
- *        for no delay.
+ * @delay: Delay to wait after link has become active (in ms)
  *
  * Use this to wait till link becomes active or inactive.
  */
@@ -4680,7 +4679,7 @@ static bool pcie_wait_for_link_delay(struct pci_dev *pdev, bool active,
                msleep(10);
                timeout -= 10;
        }
-       if (active && ret && delay)
+       if (active && ret)
                msleep(delay);
        else if (ret != active)
                pci_info(pdev, "Data Link Layer Link Active not %s in 1000 msec\n",
@@ -4801,28 +4800,17 @@ void pci_bridge_wait_for_secondary_bus(struct pci_dev *dev)
        if (!pcie_downstream_port(dev))
                return;
 
-       /*
-        * Per PCIe r5.0, sec 6.6.1, for downstream ports that support
-        * speeds > 5 GT/s, we must wait for link training to complete
-        * before the mandatory delay.
-        *
-        * We can only tell when link training completes via DLL Link
-        * Active, which is required for downstream ports that support
-        * speeds > 5 GT/s (sec 7.5.3.6).  Unfortunately some common
-        * devices do not implement Link Active reporting even when it's
-        * required, so we'll check for that directly instead of checking
-        * the supported link speed.  We assume devices without Link Active
-        * reporting can train in 100 ms regardless of speed.
-        */
-       if (dev->link_active_reporting) {
-               pci_dbg(dev, "waiting for link to train\n");
-               if (!pcie_wait_for_link_delay(dev, true, 0)) {
+       if (pcie_get_speed_cap(dev) <= PCIE_SPEED_5_0GT) {
+               pci_dbg(dev, "waiting %d ms for downstream link\n", delay);
+               msleep(delay);
+       } else {
+               pci_dbg(dev, "waiting %d ms for downstream link, after activation\n",
+                       delay);
+               if (!pcie_wait_for_link_delay(dev, true, delay)) {
                        /* Did not train, no need to wait any further */
                        return;
                }
        }
-       pci_dbg(child, "waiting %d ms to become accessible\n", delay);
-       msleep(delay);
 
        if (!pci_device_is_present(child)) {
                pci_dbg(child, "waiting additional %d ms to become accessible\n", delay);
index 812bfc3..2ea61ab 100644 (file)
@@ -2330,6 +2330,19 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f1, quirk_disable_aspm_l0s);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f4, quirk_disable_aspm_l0s);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1508, quirk_disable_aspm_l0s);
 
+static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
+{
+       pci_info(dev, "Disabling ASPM L0s/L1\n");
+       pci_disable_link_state(dev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
+}
+
+/*
+ * ASM1083/1085 PCIe-PCI bridge devices cause AER timeout errors on the
+ * upstream PCIe root port when ASPM is enabled. At least L0s mode is affected;
+ * disable both L0s and L1 for now to be safe.
+ */
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
+
 /*
  * Some Pericom PCIe-to-PCI bridges in reverse mode need the PCIe Retrain
  * Link bit cleared after starting the link retrain process to allow this
index 1b8e337..87c4be9 100644 (file)
@@ -1718,6 +1718,7 @@ static struct platform_driver cci_pmu_driver = {
        .driver = {
                   .name = DRIVER_NAME,
                   .of_match_table = arm_cci_pmu_matches,
+                  .suppress_bind_attrs = true,
                  },
        .probe = cci_pmu_probe,
        .remove = cci_pmu_remove,
index d50edef..7b7d23f 100644 (file)
@@ -1545,6 +1545,7 @@ static struct platform_driver arm_ccn_driver = {
        .driver = {
                .name = "arm-ccn",
                .of_match_table = arm_ccn_match,
+               .suppress_bind_attrs = true,
        },
        .probe = arm_ccn_probe,
        .remove = arm_ccn_remove,
index 518d060..96ed93c 100644 (file)
@@ -757,6 +757,7 @@ static struct platform_driver dsu_pmu_driver = {
        .driver = {
                .name   = DRVNAME,
                .of_match_table = of_match_ptr(dsu_pmu_of_match),
+               .suppress_bind_attrs = true,
        },
        .probe = dsu_pmu_device_probe,
        .remove = dsu_pmu_device_remove,
index 48e28ef..4cdb35d 100644 (file)
@@ -742,6 +742,7 @@ static int smmu_pmu_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, smmu_pmu);
 
        smmu_pmu->pmu = (struct pmu) {
+               .module         = THIS_MODULE,
                .task_ctx_nr    = perf_invalid_context,
                .pmu_enable     = smmu_pmu_enable,
                .pmu_disable    = smmu_pmu_disable,
@@ -859,6 +860,7 @@ static void smmu_pmu_shutdown(struct platform_device *pdev)
 static struct platform_driver smmu_pmu_driver = {
        .driver = {
                .name = "arm-smmu-v3-pmcg",
+               .suppress_bind_attrs = true,
        },
        .probe = smmu_pmu_probe,
        .remove = smmu_pmu_remove,
index d80f487..e51ddb6 100644 (file)
@@ -1226,6 +1226,7 @@ static struct platform_driver arm_spe_pmu_driver = {
        .driver = {
                .name           = DRVNAME,
                .of_match_table = of_match_ptr(arm_spe_pmu_of_match),
+               .suppress_bind_attrs = true,
        },
        .probe  = arm_spe_pmu_device_probe,
        .remove = arm_spe_pmu_device_remove,
index 90884d1..397540a 100644 (file)
@@ -512,6 +512,7 @@ static int ddr_perf_init(struct ddr_pmu *pmu, void __iomem *base,
 {
        *pmu = (struct ddr_pmu) {
                .pmu = (struct pmu) {
+                       .module       = THIS_MODULE,
                        .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
                        .task_ctx_nr = perf_invalid_context,
                        .attr_groups = attr_groups,
@@ -706,6 +707,7 @@ static struct platform_driver imx_ddr_pmu_driver = {
        .driver         = {
                .name   = "imx-ddr-pmu",
                .of_match_table = imx_ddr_pmu_dt_ids,
+               .suppress_bind_attrs = true,
        },
        .probe          = ddr_perf_probe,
        .remove         = ddr_perf_remove,
index 15713fa..5e3645c 100644 (file)
@@ -378,6 +378,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
                              ddrc_pmu->sccl_id, ddrc_pmu->index_id);
        ddrc_pmu->pmu = (struct pmu) {
                .name           = name,
+               .module         = THIS_MODULE,
                .task_ctx_nr    = perf_invalid_context,
                .event_init     = hisi_uncore_pmu_event_init,
                .pmu_enable     = hisi_uncore_pmu_enable,
@@ -418,6 +419,7 @@ static struct platform_driver hisi_ddrc_pmu_driver = {
        .driver = {
                .name = "hisi_ddrc_pmu",
                .acpi_match_table = ACPI_PTR(hisi_ddrc_pmu_acpi_match),
+               .suppress_bind_attrs = true,
        },
        .probe = hisi_ddrc_pmu_probe,
        .remove = hisi_ddrc_pmu_remove,
index dcc5600..5eb8168 100644 (file)
@@ -390,6 +390,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev)
                              hha_pmu->sccl_id, hha_pmu->index_id);
        hha_pmu->pmu = (struct pmu) {
                .name           = name,
+               .module         = THIS_MODULE,
                .task_ctx_nr    = perf_invalid_context,
                .event_init     = hisi_uncore_pmu_event_init,
                .pmu_enable     = hisi_uncore_pmu_enable,
@@ -430,6 +431,7 @@ static struct platform_driver hisi_hha_pmu_driver = {
        .driver = {
                .name = "hisi_hha_pmu",
                .acpi_match_table = ACPI_PTR(hisi_hha_pmu_acpi_match),
+               .suppress_bind_attrs = true,
        },
        .probe = hisi_hha_pmu_probe,
        .remove = hisi_hha_pmu_remove,
index 7719ae4..3e8b5ea 100644 (file)
@@ -380,6 +380,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
                              l3c_pmu->sccl_id, l3c_pmu->index_id);
        l3c_pmu->pmu = (struct pmu) {
                .name           = name,
+               .module         = THIS_MODULE,
                .task_ctx_nr    = perf_invalid_context,
                .event_init     = hisi_uncore_pmu_event_init,
                .pmu_enable     = hisi_uncore_pmu_enable,
@@ -420,6 +421,7 @@ static struct platform_driver hisi_l3c_pmu_driver = {
        .driver = {
                .name = "hisi_l3c_pmu",
                .acpi_match_table = ACPI_PTR(hisi_l3c_pmu_acpi_match),
+               .suppress_bind_attrs = true,
        },
        .probe = hisi_l3c_pmu_probe,
        .remove = hisi_l3c_pmu_remove,
index 21d6991..4da37f6 100644 (file)
@@ -1028,6 +1028,7 @@ static struct platform_driver l2_cache_pmu_driver = {
        .driver = {
                .name = "qcom-l2cache-pmu",
                .acpi_match_table = ACPI_PTR(l2_cache_pmu_acpi_match),
+               .suppress_bind_attrs = true,
        },
        .probe = l2_cache_pmu_probe,
        .remove = l2_cache_pmu_remove,
index 656e830..9ddb577 100644 (file)
@@ -814,6 +814,7 @@ static struct platform_driver qcom_l3_cache_pmu_driver = {
        .driver = {
                .name = "qcom-l3cache-pmu",
                .acpi_match_table = ACPI_PTR(qcom_l3_cache_pmu_acpi_match),
+               .suppress_bind_attrs = true,
        },
        .probe = qcom_l3_cache_pmu_probe,
 };
index 51b31d6..aac9823 100644 (file)
@@ -1017,6 +1017,7 @@ static struct platform_driver tx2_uncore_driver = {
        .driver = {
                .name           = "tx2-uncore-pmu",
                .acpi_match_table = ACPI_PTR(tx2_uncore_acpi_match),
+               .suppress_bind_attrs = true,
        },
        .probe = tx2_uncore_probe,
        .remove = tx2_uncore_remove,
index 46ee680..edac28c 100644 (file)
@@ -1975,6 +1975,7 @@ static struct platform_driver xgene_pmu_driver = {
                .name           = "xgene-pmu",
                .of_match_table = xgene_pmu_of_match,
                .acpi_match_table = ACPI_PTR(xgene_pmu_acpi_match),
+               .suppress_bind_attrs = true,
        },
 };
 
index 8569273..e5842e4 100644 (file)
@@ -545,13 +545,14 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
        struct sun4i_usb_phy_data *data =
                container_of(work, struct sun4i_usb_phy_data, detect.work);
        struct phy *phy0 = data->phys[0].phy;
-       struct sun4i_usb_phy *phy = phy_get_drvdata(phy0);
+       struct sun4i_usb_phy *phy;
        bool force_session_end, id_notify = false, vbus_notify = false;
        int id_det, vbus_det;
 
-       if (phy0 == NULL)
+       if (!phy0)
                return;
 
+       phy = phy_get_drvdata(phy0);
        id_det = sun4i_usb_phy0_get_id_det(data);
        vbus_det = sun4i_usb_phy0_get_vbus_det(data);
 
index c2a35be..360b1eb 100644 (file)
@@ -134,7 +134,7 @@ static inline void combo_phy_w32_off_mask(void __iomem *base, unsigned int reg,
 
        reg_val = readl(base + reg);
        reg_val &= ~mask;
-       reg_val |= FIELD_PREP(mask, val);
+       reg_val |= val;
        writel(reg_val, base + reg);
 }
 
@@ -169,7 +169,7 @@ static int intel_cbphy_pcie_en_pad_refclk(struct intel_cbphy_iphy *iphy)
                return 0;
 
        combo_phy_w32_off_mask(cbphy->app_base, PCIE_PHY_GEN_CTRL,
-                              PCIE_PHY_CLK_PAD, 0);
+                              PCIE_PHY_CLK_PAD, FIELD_PREP(PCIE_PHY_CLK_PAD, 0));
 
        /* Delay for stable clock PLL */
        usleep_range(50, 100);
@@ -192,14 +192,14 @@ static int intel_cbphy_pcie_dis_pad_refclk(struct intel_cbphy_iphy *iphy)
                return 0;
 
        combo_phy_w32_off_mask(cbphy->app_base, PCIE_PHY_GEN_CTRL,
-                              PCIE_PHY_CLK_PAD, 1);
+                              PCIE_PHY_CLK_PAD, FIELD_PREP(PCIE_PHY_CLK_PAD, 1));
 
        return 0;
 }
 
 static int intel_cbphy_set_mode(struct intel_combo_phy *cbphy)
 {
-       enum intel_combo_mode cb_mode = PHY_PCIE_MODE;
+       enum intel_combo_mode cb_mode;
        enum aggregated_mode aggr = cbphy->aggr_mode;
        struct device *dev = cbphy->dev;
        enum intel_phy_mode mode;
@@ -224,6 +224,8 @@ static int intel_cbphy_set_mode(struct intel_combo_phy *cbphy)
 
                cb_mode = SATA0_SATA1_MODE;
                break;
+       default:
+               return -EINVAL;
        }
 
        ret = regmap_write(cbphy->hsiocfg, REG_COMBO_MODE(cbphy->bid), cb_mode);
@@ -385,7 +387,7 @@ static int intel_cbphy_calibrate(struct phy *phy)
 
        /* trigger auto RX adaptation */
        combo_phy_w32_off_mask(cr_base, CR_ADDR(PCS_XF_ATE_OVRD_IN_2, id),
-                              ADAPT_REQ_MSK, 3);
+                              ADAPT_REQ_MSK, FIELD_PREP(ADAPT_REQ_MSK, 3));
        /* Wait RX adaptation to finish */
        ret = readl_poll_timeout(cr_base + CR_ADDR(PCS_XF_RX_ADAPT_ACK, id),
                                 val, val & RX_ADAPT_ACK_BIT, 10, 5000);
@@ -396,7 +398,7 @@ static int intel_cbphy_calibrate(struct phy *phy)
 
        /* Stop RX adaptation */
        combo_phy_w32_off_mask(cr_base, CR_ADDR(PCS_XF_ATE_OVRD_IN_2, id),
-                              ADAPT_REQ_MSK, 0);
+                              ADAPT_REQ_MSK, FIELD_PREP(ADAPT_REQ_MSK, 0));
 
        return ret;
 }
index a7c6c94..8af8c6c 100644 (file)
@@ -607,8 +607,8 @@ static int inno_dsidphy_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, inno);
 
        inno->phy_base = devm_platform_ioremap_resource(pdev, 0);
-       if (!inno->phy_base)
-               return -ENOMEM;
+       if (IS_ERR(inno->phy_base))
+               return PTR_ERR(inno->phy_base);
 
        inno->ref_clk = devm_clk_get(dev, "ref");
        if (IS_ERR(inno->ref_clk)) {
index 2c1a7d7..77fb23b 100644 (file)
@@ -43,7 +43,7 @@ struct samsung_usb2_phy_driver {
        struct regmap *reg_pmu;
        struct regmap *reg_sys;
        spinlock_t lock;
-       struct samsung_usb2_phy_instance instances[0];
+       struct samsung_usb2_phy_instance instances[];
 };
 
 struct samsung_usb2_common_phy {
index 0a166d5..a174b3c 100644 (file)
@@ -72,7 +72,7 @@ struct serdes_am654_clk_mux {
 #define to_serdes_am654_clk_mux(_hw)   \
                container_of(_hw, struct serdes_am654_clk_mux, hw)
 
-static struct regmap_config serdes_am654_regmap_config = {
+static const struct regmap_config serdes_am654_regmap_config = {
        .reg_bits = 32,
        .val_bits = 32,
        .reg_stride = 4,
index 30ea5b2..33c4cf0 100644 (file)
@@ -117,7 +117,7 @@ struct wiz_clk_mux {
 struct wiz_clk_divider {
        struct clk_hw           hw;
        struct regmap_field     *field;
-       struct clk_div_table    *table;
+       const struct clk_div_table      *table;
        struct clk_init_data    clk_data;
 };
 
@@ -131,7 +131,7 @@ struct wiz_clk_mux_sel {
 
 struct wiz_clk_div_sel {
        struct regmap_field     *field;
-       struct clk_div_table    *table;
+       const struct clk_div_table      *table;
        const char              *node_name;
 };
 
@@ -173,7 +173,7 @@ static struct wiz_clk_mux_sel clk_mux_sel_10g[] = {
        },
 };
 
-static struct clk_div_table clk_div_table[] = {
+static const struct clk_div_table clk_div_table[] = {
        { .val = 0, .div = 1, },
        { .val = 1, .div = 2, },
        { .val = 2, .div = 4, },
@@ -559,7 +559,7 @@ static const struct clk_ops wiz_clk_div_ops = {
 
 static int wiz_div_clk_register(struct wiz *wiz, struct device_node *node,
                                struct regmap_field *field,
-                               struct clk_div_table *table)
+                               const struct clk_div_table *table)
 {
        struct device *dev = wiz->dev;
        struct wiz_clk_divider *div;
@@ -756,7 +756,7 @@ static const struct reset_control_ops wiz_phy_reset_ops = {
        .deassert = wiz_phy_reset_deassert,
 };
 
-static struct regmap_config wiz_regmap_config = {
+static const struct regmap_config wiz_regmap_config = {
        .reg_bits = 32,
        .val_bits = 32,
        .reg_stride = 4,
index cb7e0f0..1f81569 100644 (file)
@@ -824,13 +824,12 @@ int imx_pinctrl_probe(struct platform_device *pdev,
                                return -EINVAL;
                        }
 
-                       ipctl->input_sel_base = devm_of_iomap(&pdev->dev, np,
-                                                             0, NULL);
+                       ipctl->input_sel_base = of_iomap(np, 0);
                        of_node_put(np);
-                       if (IS_ERR(ipctl->input_sel_base)) {
+                       if (!ipctl->input_sel_base) {
                                dev_err(&pdev->dev,
                                        "iomuxc input select base address not found\n");
-                               return PTR_ERR(ipctl->input_sel_base);
+                               return -ENOMEM;
                        }
                }
        }
index 0ff7c55..615174a 100644 (file)
@@ -800,6 +800,21 @@ static void byt_gpio_disable_free(struct pinctrl_dev *pctl_dev,
        pm_runtime_put(vg->dev);
 }
 
+static void byt_gpio_direct_irq_check(struct intel_pinctrl *vg,
+                                     unsigned int offset)
+{
+       void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
+
+       /*
+        * Before making any direction modifications, do a check if gpio is set
+        * for direct IRQ. On Bay Trail, setting GPIO to output does not make
+        * sense, so let's at least inform the caller before they shoot
+        * themselves in the foot.
+        */
+       if (readl(conf_reg) & BYT_DIRECT_IRQ_EN)
+               dev_info_once(vg->dev, "Potential Error: Setting GPIO with direct_irq_en to output");
+}
+
 static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
                                  struct pinctrl_gpio_range *range,
                                  unsigned int offset,
@@ -807,7 +822,6 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
 {
        struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctl_dev);
        void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
-       void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
        unsigned long flags;
        u32 value;
 
@@ -817,14 +831,8 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
        value &= ~BYT_DIR_MASK;
        if (input)
                value |= BYT_OUTPUT_EN;
-       else if (readl(conf_reg) & BYT_DIRECT_IRQ_EN)
-               /*
-                * Before making any direction modifications, do a check if gpio
-                * is set for direct IRQ.  On baytrail, setting GPIO to output
-                * does not make sense, so let's at least inform the caller before
-                * they shoot themselves in the foot.
-                */
-               dev_info_once(vg->dev, "Potential Error: Setting GPIO with direct_irq_en to output");
+       else
+               byt_gpio_direct_irq_check(vg, offset);
 
        writel(value, val_reg);
 
@@ -1165,19 +1173,50 @@ static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
 
 static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
 {
-       return pinctrl_gpio_direction_input(chip->base + offset);
+       struct intel_pinctrl *vg = gpiochip_get_data(chip);
+       void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
+       unsigned long flags;
+       u32 reg;
+
+       raw_spin_lock_irqsave(&byt_lock, flags);
+
+       reg = readl(val_reg);
+       reg &= ~BYT_DIR_MASK;
+       reg |= BYT_OUTPUT_EN;
+       writel(reg, val_reg);
+
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
+       return 0;
 }
 
+/*
+ * Note despite the temptation this MUST NOT be converted into a call to
+ * pinctrl_gpio_direction_output() + byt_gpio_set() that does not work this
+ * MUST be done as a single BYT_VAL_REG register write.
+ * See the commit message of the commit adding this comment for details.
+ */
 static int byt_gpio_direction_output(struct gpio_chip *chip,
                                     unsigned int offset, int value)
 {
-       int ret = pinctrl_gpio_direction_output(chip->base + offset);
+       struct intel_pinctrl *vg = gpiochip_get_data(chip);
+       void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
+       unsigned long flags;
+       u32 reg;
 
-       if (ret)
-               return ret;
+       raw_spin_lock_irqsave(&byt_lock, flags);
+
+       byt_gpio_direct_irq_check(vg, offset);
 
-       byt_gpio_set(chip, offset, value);
+       reg = readl(val_reg);
+       reg &= ~BYT_DIR_MASK;
+       if (value)
+               reg |= BYT_LEVEL;
+       else
+               reg &= ~BYT_LEVEL;
 
+       writel(reg, val_reg);
+
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
        return 0;
 }
 
index 3e5760f..d4a192d 100644 (file)
@@ -252,7 +252,7 @@ static const struct amd_pingroup kerncz_groups[] = {
        {
                .name = "uart0",
                .pins = uart0_pins,
-               .npins = 9,
+               .npins = 5,
        },
        {
                .name = "uart1",
index e06fb88..1f47a66 100644 (file)
@@ -126,10 +126,7 @@ static int mcp23s08_spi_regmap_init(struct mcp23s08 *mcp, struct device *dev,
        copy->name = name;
 
        mcp->regmap = devm_regmap_init(dev, &mcp23sxx_spi_regmap, mcp, copy);
-       if (IS_ERR(mcp->regmap))
-               return PTR_ERR(mcp->regmap);
-
-       return 0;
+       return PTR_ERR_OR_ZERO(mcp->regmap);
 }
 
 static int mcp23s08_probe(struct spi_device *spi)
index 1e0614d..f3a8a46 100644 (file)
@@ -958,7 +958,7 @@ static int pcs_parse_pinconf(struct pcs_device *pcs, struct device_node *np,
 }
 
 /**
- * smux_parse_one_pinctrl_entry() - parses a device tree mux entry
+ * pcs_parse_one_pinctrl_entry() - parses a device tree mux entry
  * @pctldev: pin controller device
  * @pcs: pinctrl driver instance
  * @np: device node of the mux entry
index 38c33a7..ec50a3b 100644 (file)
@@ -367,7 +367,8 @@ static const char * const wci20_groups[] = {
 
 static const char * const qpic_pad_groups[] = {
        "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio9", "gpio10",
-       "gpio11", "gpio17",
+       "gpio11", "gpio17", "gpio15", "gpio12", "gpio13", "gpio14", "gpio5",
+       "gpio6", "gpio7", "gpio8",
 };
 
 static const char * const burn0_groups[] = {
index fe0be8a..092a48e 100644 (file)
@@ -170,6 +170,7 @@ struct pmic_gpio_state {
        struct regmap   *map;
        struct pinctrl_dev *ctrl;
        struct gpio_chip chip;
+       struct irq_chip irq;
 };
 
 static const struct pinconf_generic_params pmic_gpio_bindings[] = {
@@ -917,16 +918,6 @@ static int pmic_gpio_populate(struct pmic_gpio_state *state,
        return 0;
 }
 
-static struct irq_chip pmic_gpio_irq_chip = {
-       .name = "spmi-gpio",
-       .irq_ack = irq_chip_ack_parent,
-       .irq_mask = irq_chip_mask_parent,
-       .irq_unmask = irq_chip_unmask_parent,
-       .irq_set_type = irq_chip_set_type_parent,
-       .irq_set_wake = irq_chip_set_wake_parent,
-       .flags = IRQCHIP_MASK_ON_SUSPEND,
-};
-
 static int pmic_gpio_domain_translate(struct irq_domain *domain,
                                      struct irq_fwspec *fwspec,
                                      unsigned long *hwirq,
@@ -1053,8 +1044,16 @@ static int pmic_gpio_probe(struct platform_device *pdev)
        if (!parent_domain)
                return -ENXIO;
 
+       state->irq.name = "spmi-gpio",
+       state->irq.irq_ack = irq_chip_ack_parent,
+       state->irq.irq_mask = irq_chip_mask_parent,
+       state->irq.irq_unmask = irq_chip_unmask_parent,
+       state->irq.irq_set_type = irq_chip_set_type_parent,
+       state->irq.irq_set_wake = irq_chip_set_wake_parent,
+       state->irq.flags = IRQCHIP_MASK_ON_SUSPEND,
+
        girq = &state->chip.irq;
-       girq->chip = &pmic_gpio_irq_chip;
+       girq->chip = &state->irq;
        girq->default_type = IRQ_TYPE_NONE;
        girq->handler = handle_level_irq;
        girq->fwnode = of_node_to_fwnode(state->dev->of_node);
index 21661f6..195cfe5 100644 (file)
@@ -731,8 +731,8 @@ static int tegra_pinctrl_resume(struct device *dev)
 }
 
 const struct dev_pm_ops tegra_pinctrl_pm = {
-       .suspend = &tegra_pinctrl_suspend,
-       .resume = &tegra_pinctrl_resume
+       .suspend_noirq = &tegra_pinctrl_suspend,
+       .resume_noirq = &tegra_pinctrl_resume
 };
 
 static bool tegra_pinctrl_gpio_node_has_range(struct tegra_pmx *pmx)
index 877aade..8f4acdc 100644 (file)
@@ -441,6 +441,7 @@ static int asus_wmi_battery_add(struct power_supply *battery)
         * battery is named BATT.
         */
        if (strcmp(battery->desc->name, "BAT0") != 0 &&
+           strcmp(battery->desc->name, "BAT1") != 0 &&
            strcmp(battery->desc->name, "BATT") != 0)
                return -ENODEV;
 
index 1409a5b..4f6f7f0 100644 (file)
@@ -13,6 +13,9 @@
 #define INTEL_RAPL_PRIO_DEVID_0        0x3451
 #define INTEL_CFG_MBOX_DEVID_0 0x3459
 
+#define INTEL_RAPL_PRIO_DEVID_1 0x3251
+#define INTEL_CFG_MBOX_DEVID_1  0x3259
+
 /*
  * Validate maximum commands in a single request.
  * This is enough to handle command to every core in one ioctl, or all
index d84e217..95f01e7 100644 (file)
@@ -147,6 +147,7 @@ static long isst_if_mbox_proc_cmd(u8 *cmd_ptr, int *write_only, int resume)
 
 static const struct pci_device_id isst_if_mbox_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, INTEL_CFG_MBOX_DEVID_0)},
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, INTEL_CFG_MBOX_DEVID_1)},
        { 0 },
 };
 MODULE_DEVICE_TABLE(pci, isst_if_mbox_ids);
index 3584859..aa17fd7 100644 (file)
@@ -72,6 +72,7 @@ static long isst_if_mmio_rd_wr(u8 *cmd_ptr, int *write_only, int resume)
 
 static const struct pci_device_id isst_if_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, INTEL_RAPL_PRIO_DEVID_0)},
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, INTEL_RAPL_PRIO_DEVID_1)},
        { 0 },
 };
 MODULE_DEVICE_TABLE(pci, isst_if_ids);
index ff7f0a4..0f6fced 100644 (file)
@@ -885,11 +885,19 @@ static ssize_t dispatch_proc_write(struct file *file,
 
        if (!ibm || !ibm->write)
                return -EINVAL;
+       if (count > PAGE_SIZE - 1)
+               return -EINVAL;
+
+       kernbuf = kmalloc(count + 1, GFP_KERNEL);
+       if (!kernbuf)
+               return -ENOMEM;
 
-       kernbuf = strndup_user(userbuf, PAGE_SIZE);
-       if (IS_ERR(kernbuf))
-               return PTR_ERR(kernbuf);
+       if (copy_from_user(kernbuf, userbuf, count)) {
+               kfree(kernbuf);
+               return -EFAULT;
+       }
 
+       kernbuf[count] = 0;
        ret = ibm->write(kernbuf);
        if (ret == 0)
                ret = count;
index 0e90c5d..eb8ed28 100644 (file)
@@ -39,7 +39,7 @@ struct rio_id_table {
        u16 start;      /* logical minimal id */
        u32 max;        /* max number of IDs in table */
        spinlock_t lock;
-       unsigned long table[0];
+       unsigned long table[];
 };
 
 static int next_destid = 0;
index 8f677f5..edb1c4f 100644 (file)
@@ -684,7 +684,7 @@ config REGULATOR_MT6323
 
 config REGULATOR_MT6358
        tristate "MediaTek MT6358 PMIC"
-       depends on MFD_MT6397 && BROKEN
+       depends on MFD_MT6397
        help
          Say y here to select this option to enable the power regulator of
          MediaTek MT6358 PMIC.
index e8f1633..0796e4a 100644 (file)
@@ -31,7 +31,7 @@ obj-$(CONFIG_REGULATOR_BD70528) += bd70528-regulator.o
 obj-$(CONFIG_REGULATOR_BD71828) += bd71828-regulator.o
 obj-$(CONFIG_REGULATOR_BD718XX) += bd718x7-regulator.o
 obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o
-obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
+obj-$(CONFIG_REGULATOR_DA903X) += da903x-regulator.o
 obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
 obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o
 obj-$(CONFIG_REGULATOR_DA9062) += da9062-regulator.o
diff --git a/drivers/regulator/da903x-regulator.c b/drivers/regulator/da903x-regulator.c
new file mode 100644 (file)
index 0000000..770e694
--- /dev/null
@@ -0,0 +1,494 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Regulators driver for Dialog Semiconductor DA903x
+//
+// Copyright (C) 2006-2008 Marvell International Ltd.
+// Copyright (C) 2008 Compulab Ltd.
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/da903x.h>
+
+/* DA9030 Registers */
+#define DA9030_INVAL           (-1)
+#define DA9030_LDO1011         (0x10)
+#define DA9030_LDO15           (0x11)
+#define DA9030_LDO1416         (0x12)
+#define DA9030_LDO1819         (0x13)
+#define DA9030_LDO17           (0x14)
+#define DA9030_BUCK2DVM1       (0x15)
+#define DA9030_BUCK2DVM2       (0x16)
+#define DA9030_RCTL11          (0x17)
+#define DA9030_RCTL21          (0x18)
+#define DA9030_LDO1            (0x90)
+#define DA9030_LDO23           (0x91)
+#define DA9030_LDO45           (0x92)
+#define DA9030_LDO6            (0x93)
+#define DA9030_LDO78           (0x94)
+#define DA9030_LDO912          (0x95)
+#define DA9030_BUCK            (0x96)
+#define DA9030_RCTL12          (0x97)
+#define DA9030_RCTL22          (0x98)
+#define DA9030_LDO_UNLOCK      (0xa0)
+#define DA9030_LDO_UNLOCK_MASK (0xe0)
+#define DA9034_OVER1           (0x10)
+
+/* DA9034 Registers */
+#define DA9034_INVAL           (-1)
+#define DA9034_OVER2           (0x11)
+#define DA9034_OVER3           (0x12)
+#define DA9034_LDO643          (0x13)
+#define DA9034_LDO987          (0x14)
+#define DA9034_LDO1110         (0x15)
+#define DA9034_LDO1312         (0x16)
+#define DA9034_LDO1514         (0x17)
+#define DA9034_VCC1            (0x20)
+#define DA9034_ADTV1           (0x23)
+#define DA9034_ADTV2           (0x24)
+#define DA9034_AVRC            (0x25)
+#define DA9034_CDTV1           (0x26)
+#define DA9034_CDTV2           (0x27)
+#define DA9034_CVRC            (0x28)
+#define DA9034_SDTV1           (0x29)
+#define DA9034_SDTV2           (0x2a)
+#define DA9034_SVRC            (0x2b)
+#define DA9034_MDTV1           (0x32)
+#define DA9034_MDTV2           (0x33)
+#define DA9034_MVRC            (0x34)
+
+/* DA9035 Registers. DA9034 Registers are comptabile to DA9035. */
+#define DA9035_OVER3           (0x12)
+#define DA9035_VCC2            (0x1f)
+#define DA9035_3DTV1           (0x2c)
+#define DA9035_3DTV2           (0x2d)
+#define DA9035_3VRC            (0x2e)
+#define DA9035_AUTOSKIP                (0x2f)
+
+struct da903x_regulator_info {
+       struct regulator_desc desc;
+
+       int     max_uV;
+       int     vol_reg;
+       int     vol_shift;
+       int     vol_nbits;
+       int     update_reg;
+       int     update_bit;
+       int     enable_reg;
+       int     enable_bit;
+};
+
+static inline struct device *to_da903x_dev(struct regulator_dev *rdev)
+{
+       return rdev_get_dev(rdev)->parent->parent;
+}
+
+static inline int check_range(struct da903x_regulator_info *info,
+                               int min_uV, int max_uV)
+{
+       if (min_uV < info->desc.min_uV || min_uV > info->max_uV)
+               return -EINVAL;
+
+       return 0;
+}
+
+/* DA9030/DA9034 common operations */
+static int da903x_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       struct device *da9034_dev = to_da903x_dev(rdev);
+       uint8_t val, mask;
+
+       if (rdev->desc->n_voltages == 1)
+               return -EINVAL;
+
+       val = selector << info->vol_shift;
+       mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+
+       return da903x_update(da9034_dev, info->vol_reg, val, mask);
+}
+
+static int da903x_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       struct device *da9034_dev = to_da903x_dev(rdev);
+       uint8_t val, mask;
+       int ret;
+
+       if (rdev->desc->n_voltages == 1)
+               return 0;
+
+       ret = da903x_read(da9034_dev, info->vol_reg, &val);
+       if (ret)
+               return ret;
+
+       mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+       val = (val & mask) >> info->vol_shift;
+
+       return val;
+}
+
+static int da903x_enable(struct regulator_dev *rdev)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       struct device *da9034_dev = to_da903x_dev(rdev);
+
+       return da903x_set_bits(da9034_dev, info->enable_reg,
+                                       1 << info->enable_bit);
+}
+
+static int da903x_disable(struct regulator_dev *rdev)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       struct device *da9034_dev = to_da903x_dev(rdev);
+
+       return da903x_clr_bits(da9034_dev, info->enable_reg,
+                                       1 << info->enable_bit);
+}
+
+static int da903x_is_enabled(struct regulator_dev *rdev)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       struct device *da9034_dev = to_da903x_dev(rdev);
+       uint8_t reg_val;
+       int ret;
+
+       ret = da903x_read(da9034_dev, info->enable_reg, &reg_val);
+       if (ret)
+               return ret;
+
+       return !!(reg_val & (1 << info->enable_bit));
+}
+
+/* DA9030 specific operations */
+static int da9030_set_ldo1_15_voltage_sel(struct regulator_dev *rdev,
+                                         unsigned selector)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       struct device *da903x_dev = to_da903x_dev(rdev);
+       uint8_t val, mask;
+       int ret;
+
+       val = selector << info->vol_shift;
+       mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+       val |= DA9030_LDO_UNLOCK; /* have to set UNLOCK bits */
+       mask |= DA9030_LDO_UNLOCK_MASK;
+
+       /* write twice */
+       ret = da903x_update(da903x_dev, info->vol_reg, val, mask);
+       if (ret)
+               return ret;
+
+       return da903x_update(da903x_dev, info->vol_reg, val, mask);
+}
+
+static int da9030_map_ldo14_voltage(struct regulator_dev *rdev,
+                                   int min_uV, int max_uV)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       int thresh, sel;
+
+       if (check_range(info, min_uV, max_uV)) {
+               pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV);
+               return -EINVAL;
+       }
+
+       thresh = (info->max_uV + info->desc.min_uV) / 2;
+       if (min_uV < thresh) {
+               sel = DIV_ROUND_UP(thresh - min_uV, info->desc.uV_step);
+               sel |= 0x4;
+       } else {
+               sel = DIV_ROUND_UP(min_uV - thresh, info->desc.uV_step);
+       }
+
+       return sel;
+}
+
+static int da9030_list_ldo14_voltage(struct regulator_dev *rdev,
+                                    unsigned selector)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       int volt;
+
+       if (selector & 0x4)
+               volt = rdev->desc->min_uV +
+                      rdev->desc->uV_step * (3 - (selector & ~0x4));
+       else
+               volt = (info->max_uV + rdev->desc->min_uV) / 2 +
+                      rdev->desc->uV_step * (selector & ~0x4);
+
+       if (volt > info->max_uV)
+               return -EINVAL;
+
+       return volt;
+}
+
+/* DA9034 specific operations */
+static int da9034_set_dvc_voltage_sel(struct regulator_dev *rdev,
+                                     unsigned selector)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       struct device *da9034_dev = to_da903x_dev(rdev);
+       uint8_t val, mask;
+       int ret;
+
+       val = selector << info->vol_shift;
+       mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+
+       ret = da903x_update(da9034_dev, info->vol_reg, val, mask);
+       if (ret)
+               return ret;
+
+       ret = da903x_set_bits(da9034_dev, info->update_reg,
+                                       1 << info->update_bit);
+       return ret;
+}
+
+static const struct linear_range da9034_ldo12_ranges[] = {
+       REGULATOR_LINEAR_RANGE(1700000, 0, 7, 50000),
+       REGULATOR_LINEAR_RANGE(2700000, 8, 15, 50000),
+};
+
+static const struct regulator_ops da903x_regulator_ldo_ops = {
+       .set_voltage_sel = da903x_set_voltage_sel,
+       .get_voltage_sel = da903x_get_voltage_sel,
+       .list_voltage   = regulator_list_voltage_linear,
+       .map_voltage    = regulator_map_voltage_linear,
+       .enable         = da903x_enable,
+       .disable        = da903x_disable,
+       .is_enabled     = da903x_is_enabled,
+};
+
+/* NOTE: this is dedicated for the insane DA9030 LDO14 */
+static const struct regulator_ops da9030_regulator_ldo14_ops = {
+       .set_voltage_sel = da903x_set_voltage_sel,
+       .get_voltage_sel = da903x_get_voltage_sel,
+       .list_voltage   = da9030_list_ldo14_voltage,
+       .map_voltage    = da9030_map_ldo14_voltage,
+       .enable         = da903x_enable,
+       .disable        = da903x_disable,
+       .is_enabled     = da903x_is_enabled,
+};
+
+/* NOTE: this is dedicated for the DA9030 LDO1 and LDO15 that have locks  */
+static const struct regulator_ops da9030_regulator_ldo1_15_ops = {
+       .set_voltage_sel = da9030_set_ldo1_15_voltage_sel,
+       .get_voltage_sel = da903x_get_voltage_sel,
+       .list_voltage   = regulator_list_voltage_linear,
+       .map_voltage    = regulator_map_voltage_linear,
+       .enable         = da903x_enable,
+       .disable        = da903x_disable,
+       .is_enabled     = da903x_is_enabled,
+};
+
+static const struct regulator_ops da9034_regulator_dvc_ops = {
+       .set_voltage_sel = da9034_set_dvc_voltage_sel,
+       .get_voltage_sel = da903x_get_voltage_sel,
+       .list_voltage   = regulator_list_voltage_linear,
+       .map_voltage    = regulator_map_voltage_linear,
+       .enable         = da903x_enable,
+       .disable        = da903x_disable,
+       .is_enabled     = da903x_is_enabled,
+};
+
+/* NOTE: this is dedicated for the insane LDO12 */
+static const struct regulator_ops da9034_regulator_ldo12_ops = {
+       .set_voltage_sel = da903x_set_voltage_sel,
+       .get_voltage_sel = da903x_get_voltage_sel,
+       .list_voltage   = regulator_list_voltage_linear_range,
+       .map_voltage    = regulator_map_voltage_linear_range,
+       .enable         = da903x_enable,
+       .disable        = da903x_disable,
+       .is_enabled     = da903x_is_enabled,
+};
+
+#define DA903x_LDO(_pmic, _id, min, max, step, vreg, shift, nbits, ereg, ebit) \
+{                                                                      \
+       .desc   = {                                                     \
+               .name   = "LDO" #_id,                                   \
+               .ops    = &da903x_regulator_ldo_ops,                    \
+               .type   = REGULATOR_VOLTAGE,                            \
+               .id     = _pmic##_ID_LDO##_id,                          \
+               .n_voltages = (step) ? ((max - min) / step + 1) : 1,    \
+               .owner  = THIS_MODULE,                                  \
+               .min_uV  = (min) * 1000,                                \
+               .uV_step = (step) * 1000,                               \
+       },                                                              \
+       .max_uV         = (max) * 1000,                                 \
+       .vol_reg        = _pmic##_##vreg,                               \
+       .vol_shift      = (shift),                                      \
+       .vol_nbits      = (nbits),                                      \
+       .enable_reg     = _pmic##_##ereg,                               \
+       .enable_bit     = (ebit),                                       \
+}
+
+#define DA903x_DVC(_pmic, _id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \
+{                                                                      \
+       .desc   = {                                                     \
+               .name   = #_id,                                         \
+               .ops    = &da9034_regulator_dvc_ops,                    \
+               .type   = REGULATOR_VOLTAGE,                            \
+               .id     = _pmic##_ID_##_id,                             \
+               .n_voltages = (step) ? ((max - min) / step + 1) : 1,    \
+               .owner  = THIS_MODULE,                                  \
+               .min_uV = (min) * 1000,                                 \
+               .uV_step = (step) * 1000,                               \
+       },                                                              \
+       .max_uV         = (max) * 1000,                                 \
+       .vol_reg        = _pmic##_##vreg,                               \
+       .vol_shift      = (0),                                          \
+       .vol_nbits      = (nbits),                                      \
+       .update_reg     = _pmic##_##ureg,                               \
+       .update_bit     = (ubit),                                       \
+       .enable_reg     = _pmic##_##ereg,                               \
+       .enable_bit     = (ebit),                                       \
+}
+
+#define DA9034_LDO(_id, min, max, step, vreg, shift, nbits, ereg, ebit)        \
+       DA903x_LDO(DA9034, _id, min, max, step, vreg, shift, nbits, ereg, ebit)
+
+#define DA9030_LDO(_id, min, max, step, vreg, shift, nbits, ereg, ebit)        \
+       DA903x_LDO(DA9030, _id, min, max, step, vreg, shift, nbits, ereg, ebit)
+
+#define DA9030_DVC(_id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \
+       DA903x_DVC(DA9030, _id, min, max, step, vreg, nbits, ureg, ubit, \
+                  ereg, ebit)
+
+#define DA9034_DVC(_id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \
+       DA903x_DVC(DA9034, _id, min, max, step, vreg, nbits, ureg, ubit, \
+                  ereg, ebit)
+
+#define DA9035_DVC(_id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \
+       DA903x_DVC(DA9035, _id, min, max, step, vreg, nbits, ureg, ubit, \
+                  ereg, ebit)
+
+static struct da903x_regulator_info da903x_regulator_info[] = {
+       /* DA9030 */
+       DA9030_DVC(BUCK2, 850, 1625, 25, BUCK2DVM1, 5, BUCK2DVM1, 7, RCTL11, 0),
+
+       DA9030_LDO( 1, 1200, 3200, 100,    LDO1, 0, 5, RCTL12, 1),
+       DA9030_LDO( 2, 1800, 3200, 100,   LDO23, 0, 4, RCTL12, 2),
+       DA9030_LDO( 3, 1800, 3200, 100,   LDO23, 4, 4, RCTL12, 3),
+       DA9030_LDO( 4, 1800, 3200, 100,   LDO45, 0, 4, RCTL12, 4),
+       DA9030_LDO( 5, 1800, 3200, 100,   LDO45, 4, 4, RCTL12, 5),
+       DA9030_LDO( 6, 1800, 3200, 100,    LDO6, 0, 4, RCTL12, 6),
+       DA9030_LDO( 7, 1800, 3200, 100,   LDO78, 0, 4, RCTL12, 7),
+       DA9030_LDO( 8, 1800, 3200, 100,   LDO78, 4, 4, RCTL22, 0),
+       DA9030_LDO( 9, 1800, 3200, 100,  LDO912, 0, 4, RCTL22, 1),
+       DA9030_LDO(10, 1800, 3200, 100, LDO1011, 0, 4, RCTL22, 2),
+       DA9030_LDO(11, 1800, 3200, 100, LDO1011, 4, 4, RCTL22, 3),
+       DA9030_LDO(12, 1800, 3200, 100,  LDO912, 4, 4, RCTL22, 4),
+       DA9030_LDO(14, 2760, 2940,  30, LDO1416, 0, 3, RCTL11, 4),
+       DA9030_LDO(15, 1100, 2650,  50,   LDO15, 0, 5, RCTL11, 5),
+       DA9030_LDO(16, 1100, 2650,  50, LDO1416, 3, 5, RCTL11, 6),
+       DA9030_LDO(17, 1800, 3200, 100,   LDO17, 0, 4, RCTL11, 7),
+       DA9030_LDO(18, 1800, 3200, 100, LDO1819, 0, 4, RCTL21, 2),
+       DA9030_LDO(19, 1800, 3200, 100, LDO1819, 4, 4, RCTL21, 1),
+       DA9030_LDO(13, 2100, 2100, 0, INVAL, 0, 0, RCTL11, 3), /* fixed @2.1V */
+
+       /* DA9034 */
+       DA9034_DVC(BUCK1, 725, 1500, 25, ADTV2, 5, VCC1, 0, OVER1, 0),
+       DA9034_DVC(BUCK2, 725, 1500, 25, CDTV2, 5, VCC1, 2, OVER1, 1),
+       DA9034_DVC(LDO2,  725, 1500, 25, SDTV2, 5, VCC1, 4, OVER1, 2),
+       DA9034_DVC(LDO1, 1700, 2075, 25, MDTV1, 4, VCC1, 6, OVER3, 4),
+
+       DA9034_LDO( 3, 1800, 3300, 100,  LDO643, 0, 4, OVER3, 5),
+       DA9034_LDO( 4, 1800, 2900,1100,  LDO643, 4, 1, OVER3, 6),
+       DA9034_LDO( 6, 2500, 2850,  50,  LDO643, 5, 3, OVER2, 0),
+       DA9034_LDO( 7, 2700, 3050,  50,  LDO987, 0, 3, OVER2, 1),
+       DA9034_LDO( 8, 2700, 2850,  50,  LDO987, 3, 2, OVER2, 2),
+       DA9034_LDO( 9, 2700, 3050,  50,  LDO987, 5, 3, OVER2, 3),
+       DA9034_LDO(10, 2700, 3050,  50, LDO1110, 0, 3, OVER2, 4),
+       DA9034_LDO(11, 1800, 3300, 100, LDO1110, 4, 4, OVER2, 5),
+       DA9034_LDO(12, 1700, 3050,  50, LDO1312, 0, 4, OVER3, 6),
+       DA9034_LDO(13, 1800, 3300, 100, LDO1312, 4, 4, OVER2, 7),
+       DA9034_LDO(14, 1800, 3300, 100, LDO1514, 0, 4, OVER3, 0),
+       DA9034_LDO(15, 1800, 3300, 100, LDO1514, 4, 4, OVER3, 1),
+       DA9034_LDO(5, 3100, 3100, 0, INVAL, 0, 0, OVER3, 7), /* fixed @3.1V */
+
+       /* DA9035 */
+       DA9035_DVC(BUCK3, 1800, 2200, 100, 3DTV1, 3, VCC2, 0, OVER3, 3),
+};
+
+static inline struct da903x_regulator_info *find_regulator_info(int id)
+{
+       struct da903x_regulator_info *ri;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(da903x_regulator_info); i++) {
+               ri = &da903x_regulator_info[i];
+               if (ri->desc.id == id)
+                       return ri;
+       }
+       return NULL;
+}
+
+static int da903x_regulator_probe(struct platform_device *pdev)
+{
+       struct da903x_regulator_info *ri = NULL;
+       struct regulator_dev *rdev;
+       struct regulator_config config = { };
+
+       ri = find_regulator_info(pdev->id);
+       if (ri == NULL) {
+               dev_err(&pdev->dev, "invalid regulator ID specified\n");
+               return -EINVAL;
+       }
+
+       /* Workaround for the weird LDO12 voltage setting */
+       if (ri->desc.id == DA9034_ID_LDO12) {
+               ri->desc.ops = &da9034_regulator_ldo12_ops;
+               ri->desc.n_voltages = 16;
+               ri->desc.linear_ranges = da9034_ldo12_ranges;
+               ri->desc.n_linear_ranges = ARRAY_SIZE(da9034_ldo12_ranges);
+       }
+
+       if (ri->desc.id == DA9030_ID_LDO14)
+               ri->desc.ops = &da9030_regulator_ldo14_ops;
+
+       if (ri->desc.id == DA9030_ID_LDO1 || ri->desc.id == DA9030_ID_LDO15)
+               ri->desc.ops = &da9030_regulator_ldo1_15_ops;
+
+       config.dev = &pdev->dev;
+       config.init_data = dev_get_platdata(&pdev->dev);
+       config.driver_data = ri;
+
+       rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
+       if (IS_ERR(rdev)) {
+               dev_err(&pdev->dev, "failed to register regulator %s\n",
+                               ri->desc.name);
+               return PTR_ERR(rdev);
+       }
+
+       platform_set_drvdata(pdev, rdev);
+       return 0;
+}
+
+static struct platform_driver da903x_regulator_driver = {
+       .driver = {
+               .name   = "da903x-regulator",
+       },
+       .probe          = da903x_regulator_probe,
+};
+
+static int __init da903x_regulator_init(void)
+{
+       return platform_driver_register(&da903x_regulator_driver);
+}
+subsys_initcall(da903x_regulator_init);
+
+static void __exit da903x_regulator_exit(void)
+{
+       platform_driver_unregister(&da903x_regulator_driver);
+}
+module_exit(da903x_regulator_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
+             "Mike Rapoport <mike@compulab.co.il>");
+MODULE_DESCRIPTION("Regulator Driver for Dialog Semiconductor DA903X PMIC");
+MODULE_ALIAS("platform:da903x-regulator");
diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c
deleted file mode 100644 (file)
index 770e694..0000000
+++ /dev/null
@@ -1,494 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Regulators driver for Dialog Semiconductor DA903x
-//
-// Copyright (C) 2006-2008 Marvell International Ltd.
-// Copyright (C) 2008 Compulab Ltd.
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/driver.h>
-#include <linux/regulator/machine.h>
-#include <linux/mfd/da903x.h>
-
-/* DA9030 Registers */
-#define DA9030_INVAL           (-1)
-#define DA9030_LDO1011         (0x10)
-#define DA9030_LDO15           (0x11)
-#define DA9030_LDO1416         (0x12)
-#define DA9030_LDO1819         (0x13)
-#define DA9030_LDO17           (0x14)
-#define DA9030_BUCK2DVM1       (0x15)
-#define DA9030_BUCK2DVM2       (0x16)
-#define DA9030_RCTL11          (0x17)
-#define DA9030_RCTL21          (0x18)
-#define DA9030_LDO1            (0x90)
-#define DA9030_LDO23           (0x91)
-#define DA9030_LDO45           (0x92)
-#define DA9030_LDO6            (0x93)
-#define DA9030_LDO78           (0x94)
-#define DA9030_LDO912          (0x95)
-#define DA9030_BUCK            (0x96)
-#define DA9030_RCTL12          (0x97)
-#define DA9030_RCTL22          (0x98)
-#define DA9030_LDO_UNLOCK      (0xa0)
-#define DA9030_LDO_UNLOCK_MASK (0xe0)
-#define DA9034_OVER1           (0x10)
-
-/* DA9034 Registers */
-#define DA9034_INVAL           (-1)
-#define DA9034_OVER2           (0x11)
-#define DA9034_OVER3           (0x12)
-#define DA9034_LDO643          (0x13)
-#define DA9034_LDO987          (0x14)
-#define DA9034_LDO1110         (0x15)
-#define DA9034_LDO1312         (0x16)
-#define DA9034_LDO1514         (0x17)
-#define DA9034_VCC1            (0x20)
-#define DA9034_ADTV1           (0x23)
-#define DA9034_ADTV2           (0x24)
-#define DA9034_AVRC            (0x25)
-#define DA9034_CDTV1           (0x26)
-#define DA9034_CDTV2           (0x27)
-#define DA9034_CVRC            (0x28)
-#define DA9034_SDTV1           (0x29)
-#define DA9034_SDTV2           (0x2a)
-#define DA9034_SVRC            (0x2b)
-#define DA9034_MDTV1           (0x32)
-#define DA9034_MDTV2           (0x33)
-#define DA9034_MVRC            (0x34)
-
-/* DA9035 Registers. DA9034 Registers are comptabile to DA9035. */
-#define DA9035_OVER3           (0x12)
-#define DA9035_VCC2            (0x1f)
-#define DA9035_3DTV1           (0x2c)
-#define DA9035_3DTV2           (0x2d)
-#define DA9035_3VRC            (0x2e)
-#define DA9035_AUTOSKIP                (0x2f)
-
-struct da903x_regulator_info {
-       struct regulator_desc desc;
-
-       int     max_uV;
-       int     vol_reg;
-       int     vol_shift;
-       int     vol_nbits;
-       int     update_reg;
-       int     update_bit;
-       int     enable_reg;
-       int     enable_bit;
-};
-
-static inline struct device *to_da903x_dev(struct regulator_dev *rdev)
-{
-       return rdev_get_dev(rdev)->parent->parent;
-}
-
-static inline int check_range(struct da903x_regulator_info *info,
-                               int min_uV, int max_uV)
-{
-       if (min_uV < info->desc.min_uV || min_uV > info->max_uV)
-               return -EINVAL;
-
-       return 0;
-}
-
-/* DA9030/DA9034 common operations */
-static int da903x_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
-{
-       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
-       struct device *da9034_dev = to_da903x_dev(rdev);
-       uint8_t val, mask;
-
-       if (rdev->desc->n_voltages == 1)
-               return -EINVAL;
-
-       val = selector << info->vol_shift;
-       mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
-
-       return da903x_update(da9034_dev, info->vol_reg, val, mask);
-}
-
-static int da903x_get_voltage_sel(struct regulator_dev *rdev)
-{
-       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
-       struct device *da9034_dev = to_da903x_dev(rdev);
-       uint8_t val, mask;
-       int ret;
-
-       if (rdev->desc->n_voltages == 1)
-               return 0;
-
-       ret = da903x_read(da9034_dev, info->vol_reg, &val);
-       if (ret)
-               return ret;
-
-       mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
-       val = (val & mask) >> info->vol_shift;
-
-       return val;
-}
-
-static int da903x_enable(struct regulator_dev *rdev)
-{
-       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
-       struct device *da9034_dev = to_da903x_dev(rdev);
-
-       return da903x_set_bits(da9034_dev, info->enable_reg,
-                                       1 << info->enable_bit);
-}
-
-static int da903x_disable(struct regulator_dev *rdev)
-{
-       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
-       struct device *da9034_dev = to_da903x_dev(rdev);
-
-       return da903x_clr_bits(da9034_dev, info->enable_reg,
-                                       1 << info->enable_bit);
-}
-
-static int da903x_is_enabled(struct regulator_dev *rdev)
-{
-       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
-       struct device *da9034_dev = to_da903x_dev(rdev);
-       uint8_t reg_val;
-       int ret;
-
-       ret = da903x_read(da9034_dev, info->enable_reg, &reg_val);
-       if (ret)
-               return ret;
-
-       return !!(reg_val & (1 << info->enable_bit));
-}
-
-/* DA9030 specific operations */
-static int da9030_set_ldo1_15_voltage_sel(struct regulator_dev *rdev,
-                                         unsigned selector)
-{
-       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
-       struct device *da903x_dev = to_da903x_dev(rdev);
-       uint8_t val, mask;
-       int ret;
-
-       val = selector << info->vol_shift;
-       mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
-       val |= DA9030_LDO_UNLOCK; /* have to set UNLOCK bits */
-       mask |= DA9030_LDO_UNLOCK_MASK;
-
-       /* write twice */
-       ret = da903x_update(da903x_dev, info->vol_reg, val, mask);
-       if (ret)
-               return ret;
-
-       return da903x_update(da903x_dev, info->vol_reg, val, mask);
-}
-
-static int da9030_map_ldo14_voltage(struct regulator_dev *rdev,
-                                   int min_uV, int max_uV)
-{
-       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
-       int thresh, sel;
-
-       if (check_range(info, min_uV, max_uV)) {
-               pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV);
-               return -EINVAL;
-       }
-
-       thresh = (info->max_uV + info->desc.min_uV) / 2;
-       if (min_uV < thresh) {
-               sel = DIV_ROUND_UP(thresh - min_uV, info->desc.uV_step);
-               sel |= 0x4;
-       } else {
-               sel = DIV_ROUND_UP(min_uV - thresh, info->desc.uV_step);
-       }
-
-       return sel;
-}
-
-static int da9030_list_ldo14_voltage(struct regulator_dev *rdev,
-                                    unsigned selector)
-{
-       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
-       int volt;
-
-       if (selector & 0x4)
-               volt = rdev->desc->min_uV +
-                      rdev->desc->uV_step * (3 - (selector & ~0x4));
-       else
-               volt = (info->max_uV + rdev->desc->min_uV) / 2 +
-                      rdev->desc->uV_step * (selector & ~0x4);
-
-       if (volt > info->max_uV)
-               return -EINVAL;
-
-       return volt;
-}
-
-/* DA9034 specific operations */
-static int da9034_set_dvc_voltage_sel(struct regulator_dev *rdev,
-                                     unsigned selector)
-{
-       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
-       struct device *da9034_dev = to_da903x_dev(rdev);
-       uint8_t val, mask;
-       int ret;
-
-       val = selector << info->vol_shift;
-       mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
-
-       ret = da903x_update(da9034_dev, info->vol_reg, val, mask);
-       if (ret)
-               return ret;
-
-       ret = da903x_set_bits(da9034_dev, info->update_reg,
-                                       1 << info->update_bit);
-       return ret;
-}
-
-static const struct linear_range da9034_ldo12_ranges[] = {
-       REGULATOR_LINEAR_RANGE(1700000, 0, 7, 50000),
-       REGULATOR_LINEAR_RANGE(2700000, 8, 15, 50000),
-};
-
-static const struct regulator_ops da903x_regulator_ldo_ops = {
-       .set_voltage_sel = da903x_set_voltage_sel,
-       .get_voltage_sel = da903x_get_voltage_sel,
-       .list_voltage   = regulator_list_voltage_linear,
-       .map_voltage    = regulator_map_voltage_linear,
-       .enable         = da903x_enable,
-       .disable        = da903x_disable,
-       .is_enabled     = da903x_is_enabled,
-};
-
-/* NOTE: this is dedicated for the insane DA9030 LDO14 */
-static const struct regulator_ops da9030_regulator_ldo14_ops = {
-       .set_voltage_sel = da903x_set_voltage_sel,
-       .get_voltage_sel = da903x_get_voltage_sel,
-       .list_voltage   = da9030_list_ldo14_voltage,
-       .map_voltage    = da9030_map_ldo14_voltage,
-       .enable         = da903x_enable,
-       .disable        = da903x_disable,
-       .is_enabled     = da903x_is_enabled,
-};
-
-/* NOTE: this is dedicated for the DA9030 LDO1 and LDO15 that have locks  */
-static const struct regulator_ops da9030_regulator_ldo1_15_ops = {
-       .set_voltage_sel = da9030_set_ldo1_15_voltage_sel,
-       .get_voltage_sel = da903x_get_voltage_sel,
-       .list_voltage   = regulator_list_voltage_linear,
-       .map_voltage    = regulator_map_voltage_linear,
-       .enable         = da903x_enable,
-       .disable        = da903x_disable,
-       .is_enabled     = da903x_is_enabled,
-};
-
-static const struct regulator_ops da9034_regulator_dvc_ops = {
-       .set_voltage_sel = da9034_set_dvc_voltage_sel,
-       .get_voltage_sel = da903x_get_voltage_sel,
-       .list_voltage   = regulator_list_voltage_linear,
-       .map_voltage    = regulator_map_voltage_linear,
-       .enable         = da903x_enable,
-       .disable        = da903x_disable,
-       .is_enabled     = da903x_is_enabled,
-};
-
-/* NOTE: this is dedicated for the insane LDO12 */
-static const struct regulator_ops da9034_regulator_ldo12_ops = {
-       .set_voltage_sel = da903x_set_voltage_sel,
-       .get_voltage_sel = da903x_get_voltage_sel,
-       .list_voltage   = regulator_list_voltage_linear_range,
-       .map_voltage    = regulator_map_voltage_linear_range,
-       .enable         = da903x_enable,
-       .disable        = da903x_disable,
-       .is_enabled     = da903x_is_enabled,
-};
-
-#define DA903x_LDO(_pmic, _id, min, max, step, vreg, shift, nbits, ereg, ebit) \
-{                                                                      \
-       .desc   = {                                                     \
-               .name   = "LDO" #_id,                                   \
-               .ops    = &da903x_regulator_ldo_ops,                    \
-               .type   = REGULATOR_VOLTAGE,                            \
-               .id     = _pmic##_ID_LDO##_id,                          \
-               .n_voltages = (step) ? ((max - min) / step + 1) : 1,    \
-               .owner  = THIS_MODULE,                                  \
-               .min_uV  = (min) * 1000,                                \
-               .uV_step = (step) * 1000,                               \
-       },                                                              \
-       .max_uV         = (max) * 1000,                                 \
-       .vol_reg        = _pmic##_##vreg,                               \
-       .vol_shift      = (shift),                                      \
-       .vol_nbits      = (nbits),                                      \
-       .enable_reg     = _pmic##_##ereg,                               \
-       .enable_bit     = (ebit),                                       \
-}
-
-#define DA903x_DVC(_pmic, _id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \
-{                                                                      \
-       .desc   = {                                                     \
-               .name   = #_id,                                         \
-               .ops    = &da9034_regulator_dvc_ops,                    \
-               .type   = REGULATOR_VOLTAGE,                            \
-               .id     = _pmic##_ID_##_id,                             \
-               .n_voltages = (step) ? ((max - min) / step + 1) : 1,    \
-               .owner  = THIS_MODULE,                                  \
-               .min_uV = (min) * 1000,                                 \
-               .uV_step = (step) * 1000,                               \
-       },                                                              \
-       .max_uV         = (max) * 1000,                                 \
-       .vol_reg        = _pmic##_##vreg,                               \
-       .vol_shift      = (0),                                          \
-       .vol_nbits      = (nbits),                                      \
-       .update_reg     = _pmic##_##ureg,                               \
-       .update_bit     = (ubit),                                       \
-       .enable_reg     = _pmic##_##ereg,                               \
-       .enable_bit     = (ebit),                                       \
-}
-
-#define DA9034_LDO(_id, min, max, step, vreg, shift, nbits, ereg, ebit)        \
-       DA903x_LDO(DA9034, _id, min, max, step, vreg, shift, nbits, ereg, ebit)
-
-#define DA9030_LDO(_id, min, max, step, vreg, shift, nbits, ereg, ebit)        \
-       DA903x_LDO(DA9030, _id, min, max, step, vreg, shift, nbits, ereg, ebit)
-
-#define DA9030_DVC(_id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \
-       DA903x_DVC(DA9030, _id, min, max, step, vreg, nbits, ureg, ubit, \
-                  ereg, ebit)
-
-#define DA9034_DVC(_id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \
-       DA903x_DVC(DA9034, _id, min, max, step, vreg, nbits, ureg, ubit, \
-                  ereg, ebit)
-
-#define DA9035_DVC(_id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \
-       DA903x_DVC(DA9035, _id, min, max, step, vreg, nbits, ureg, ubit, \
-                  ereg, ebit)
-
-static struct da903x_regulator_info da903x_regulator_info[] = {
-       /* DA9030 */
-       DA9030_DVC(BUCK2, 850, 1625, 25, BUCK2DVM1, 5, BUCK2DVM1, 7, RCTL11, 0),
-
-       DA9030_LDO( 1, 1200, 3200, 100,    LDO1, 0, 5, RCTL12, 1),
-       DA9030_LDO( 2, 1800, 3200, 100,   LDO23, 0, 4, RCTL12, 2),
-       DA9030_LDO( 3, 1800, 3200, 100,   LDO23, 4, 4, RCTL12, 3),
-       DA9030_LDO( 4, 1800, 3200, 100,   LDO45, 0, 4, RCTL12, 4),
-       DA9030_LDO( 5, 1800, 3200, 100,   LDO45, 4, 4, RCTL12, 5),
-       DA9030_LDO( 6, 1800, 3200, 100,    LDO6, 0, 4, RCTL12, 6),
-       DA9030_LDO( 7, 1800, 3200, 100,   LDO78, 0, 4, RCTL12, 7),
-       DA9030_LDO( 8, 1800, 3200, 100,   LDO78, 4, 4, RCTL22, 0),
-       DA9030_LDO( 9, 1800, 3200, 100,  LDO912, 0, 4, RCTL22, 1),
-       DA9030_LDO(10, 1800, 3200, 100, LDO1011, 0, 4, RCTL22, 2),
-       DA9030_LDO(11, 1800, 3200, 100, LDO1011, 4, 4, RCTL22, 3),
-       DA9030_LDO(12, 1800, 3200, 100,  LDO912, 4, 4, RCTL22, 4),
-       DA9030_LDO(14, 2760, 2940,  30, LDO1416, 0, 3, RCTL11, 4),
-       DA9030_LDO(15, 1100, 2650,  50,   LDO15, 0, 5, RCTL11, 5),
-       DA9030_LDO(16, 1100, 2650,  50, LDO1416, 3, 5, RCTL11, 6),
-       DA9030_LDO(17, 1800, 3200, 100,   LDO17, 0, 4, RCTL11, 7),
-       DA9030_LDO(18, 1800, 3200, 100, LDO1819, 0, 4, RCTL21, 2),
-       DA9030_LDO(19, 1800, 3200, 100, LDO1819, 4, 4, RCTL21, 1),
-       DA9030_LDO(13, 2100, 2100, 0, INVAL, 0, 0, RCTL11, 3), /* fixed @2.1V */
-
-       /* DA9034 */
-       DA9034_DVC(BUCK1, 725, 1500, 25, ADTV2, 5, VCC1, 0, OVER1, 0),
-       DA9034_DVC(BUCK2, 725, 1500, 25, CDTV2, 5, VCC1, 2, OVER1, 1),
-       DA9034_DVC(LDO2,  725, 1500, 25, SDTV2, 5, VCC1, 4, OVER1, 2),
-       DA9034_DVC(LDO1, 1700, 2075, 25, MDTV1, 4, VCC1, 6, OVER3, 4),
-
-       DA9034_LDO( 3, 1800, 3300, 100,  LDO643, 0, 4, OVER3, 5),
-       DA9034_LDO( 4, 1800, 2900,1100,  LDO643, 4, 1, OVER3, 6),
-       DA9034_LDO( 6, 2500, 2850,  50,  LDO643, 5, 3, OVER2, 0),
-       DA9034_LDO( 7, 2700, 3050,  50,  LDO987, 0, 3, OVER2, 1),
-       DA9034_LDO( 8, 2700, 2850,  50,  LDO987, 3, 2, OVER2, 2),
-       DA9034_LDO( 9, 2700, 3050,  50,  LDO987, 5, 3, OVER2, 3),
-       DA9034_LDO(10, 2700, 3050,  50, LDO1110, 0, 3, OVER2, 4),
-       DA9034_LDO(11, 1800, 3300, 100, LDO1110, 4, 4, OVER2, 5),
-       DA9034_LDO(12, 1700, 3050,  50, LDO1312, 0, 4, OVER3, 6),
-       DA9034_LDO(13, 1800, 3300, 100, LDO1312, 4, 4, OVER2, 7),
-       DA9034_LDO(14, 1800, 3300, 100, LDO1514, 0, 4, OVER3, 0),
-       DA9034_LDO(15, 1800, 3300, 100, LDO1514, 4, 4, OVER3, 1),
-       DA9034_LDO(5, 3100, 3100, 0, INVAL, 0, 0, OVER3, 7), /* fixed @3.1V */
-
-       /* DA9035 */
-       DA9035_DVC(BUCK3, 1800, 2200, 100, 3DTV1, 3, VCC2, 0, OVER3, 3),
-};
-
-static inline struct da903x_regulator_info *find_regulator_info(int id)
-{
-       struct da903x_regulator_info *ri;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(da903x_regulator_info); i++) {
-               ri = &da903x_regulator_info[i];
-               if (ri->desc.id == id)
-                       return ri;
-       }
-       return NULL;
-}
-
-static int da903x_regulator_probe(struct platform_device *pdev)
-{
-       struct da903x_regulator_info *ri = NULL;
-       struct regulator_dev *rdev;
-       struct regulator_config config = { };
-
-       ri = find_regulator_info(pdev->id);
-       if (ri == NULL) {
-               dev_err(&pdev->dev, "invalid regulator ID specified\n");
-               return -EINVAL;
-       }
-
-       /* Workaround for the weird LDO12 voltage setting */
-       if (ri->desc.id == DA9034_ID_LDO12) {
-               ri->desc.ops = &da9034_regulator_ldo12_ops;
-               ri->desc.n_voltages = 16;
-               ri->desc.linear_ranges = da9034_ldo12_ranges;
-               ri->desc.n_linear_ranges = ARRAY_SIZE(da9034_ldo12_ranges);
-       }
-
-       if (ri->desc.id == DA9030_ID_LDO14)
-               ri->desc.ops = &da9030_regulator_ldo14_ops;
-
-       if (ri->desc.id == DA9030_ID_LDO1 || ri->desc.id == DA9030_ID_LDO15)
-               ri->desc.ops = &da9030_regulator_ldo1_15_ops;
-
-       config.dev = &pdev->dev;
-       config.init_data = dev_get_platdata(&pdev->dev);
-       config.driver_data = ri;
-
-       rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
-       if (IS_ERR(rdev)) {
-               dev_err(&pdev->dev, "failed to register regulator %s\n",
-                               ri->desc.name);
-               return PTR_ERR(rdev);
-       }
-
-       platform_set_drvdata(pdev, rdev);
-       return 0;
-}
-
-static struct platform_driver da903x_regulator_driver = {
-       .driver = {
-               .name   = "da903x-regulator",
-       },
-       .probe          = da903x_regulator_probe,
-};
-
-static int __init da903x_regulator_init(void)
-{
-       return platform_driver_register(&da903x_regulator_driver);
-}
-subsys_initcall(da903x_regulator_init);
-
-static void __exit da903x_regulator_exit(void)
-{
-       platform_driver_unregister(&da903x_regulator_driver);
-}
-module_exit(da903x_regulator_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
-             "Mike Rapoport <mike@compulab.co.il>");
-MODULE_DESCRIPTION("Regulator Driver for Dialog Semiconductor DA903X PMIC");
-MODULE_ALIAS("platform:da903x-regulator");
index e1d6c8f..fe65b5a 100644 (file)
@@ -512,7 +512,6 @@ static const struct da9063_regulator_info da9063_regulator_info[] = {
        },
        {
                DA9063_LDO(DA9063, LDO9, 950, 50, 3600),
-               .suspend = BFIELD(DA9063_REG_LDO9_CONT, DA9063_VLDO9_SEL),
        },
        {
                DA9063_LDO(DA9063, LDO11, 900, 50, 3600),
index e970e9d..e4bb09b 100644 (file)
@@ -486,7 +486,7 @@ int regulator_map_voltage_pickable_linear_range(struct regulator_dev *rdev,
                        continue;
                }
 
-               ret = selector + sel;
+               ret = selector + sel - range->min_sel;
 
                voltage = rdev->desc->ops->list_voltage(rdev, ret);
 
index 6895379..4c8e8b4 100644 (file)
@@ -209,6 +209,19 @@ static const struct regulator_ops pfuze100_swb_regulator_ops = {
 
 };
 
+static const struct regulator_ops pfuze3000_sw_regulator_ops = {
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+       .list_voltage = regulator_list_voltage_table,
+       .map_voltage = regulator_map_voltage_ascend,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_time_sel = regulator_set_voltage_time_sel,
+       .set_ramp_delay = pfuze100_set_ramp_delay,
+
+};
+
 #define PFUZE100_FIXED_REG(_chip, _name, base, voltage)        \
        [_chip ## _ ## _name] = {       \
                .desc = {       \
@@ -318,23 +331,28 @@ static const struct regulator_ops pfuze100_swb_regulator_ops = {
        .stby_mask = 0x20,      \
 }
 
-
-#define PFUZE3000_SW2_REG(_chip, _name, base, min, max, step)  {       \
-       .desc = {       \
-               .name = #_name,\
-               .n_voltages = ((max) - (min)) / (step) + 1,     \
-               .ops = &pfuze100_sw_regulator_ops,      \
-               .type = REGULATOR_VOLTAGE,      \
-               .id = _chip ## _ ## _name,      \
-               .owner = THIS_MODULE,   \
-               .min_uV = (min),        \
-               .uV_step = (step),      \
-               .vsel_reg = (base) + PFUZE100_VOL_OFFSET,       \
-               .vsel_mask = 0x7,       \
-       },      \
-       .stby_reg = (base) + PFUZE100_STANDBY_OFFSET,   \
-       .stby_mask = 0x7,       \
-}
+/* No linar case for the some switches of PFUZE3000 */
+#define PFUZE3000_SW_REG(_chip, _name, base, mask, voltages)   \
+       [_chip ## _ ##  _name] = {      \
+               .desc = {       \
+                       .name = #_name, \
+                       .n_voltages = ARRAY_SIZE(voltages),     \
+                       .ops = &pfuze3000_sw_regulator_ops,     \
+                       .type = REGULATOR_VOLTAGE,      \
+                       .id = _chip ## _ ## _name,      \
+                       .owner = THIS_MODULE,   \
+                       .volt_table = voltages, \
+                       .vsel_reg = (base) + PFUZE100_VOL_OFFSET,       \
+                       .vsel_mask = (mask),    \
+                       .enable_reg = (base) + PFUZE100_MODE_OFFSET,    \
+                       .enable_mask = 0xf,     \
+                       .enable_val = 0x8,      \
+                       .enable_time = 500,     \
+               },      \
+               .stby_reg = (base) + PFUZE100_STANDBY_OFFSET,   \
+               .stby_mask = (mask),    \
+               .sw_reg = true,         \
+       }
 
 #define PFUZE3000_SW3_REG(_chip, _name, base, min, max, step)  {       \
        .desc = {       \
@@ -391,9 +409,9 @@ static struct pfuze_regulator pfuze200_regulators[] = {
 };
 
 static struct pfuze_regulator pfuze3000_regulators[] = {
-       PFUZE100_SWB_REG(PFUZE3000, SW1A, PFUZE100_SW1ABVOL, 0x1f, pfuze3000_sw1a),
+       PFUZE3000_SW_REG(PFUZE3000, SW1A, PFUZE100_SW1ABVOL, 0x1f, pfuze3000_sw1a),
        PFUZE100_SW_REG(PFUZE3000, SW1B, PFUZE100_SW1CVOL, 700000, 1475000, 25000),
-       PFUZE100_SWB_REG(PFUZE3000, SW2, PFUZE100_SW2VOL, 0x7, pfuze3000_sw2lo),
+       PFUZE3000_SW_REG(PFUZE3000, SW2, PFUZE100_SW2VOL, 0x7, pfuze3000_sw2lo),
        PFUZE3000_SW3_REG(PFUZE3000, SW3, PFUZE100_SW3AVOL, 900000, 1650000, 50000),
        PFUZE100_SWB_REG(PFUZE3000, SWBST, PFUZE100_SWBSTCON1, 0x3, pfuze100_swbst),
        PFUZE100_SWB_REG(PFUZE3000, VSNVS, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
@@ -407,8 +425,8 @@ static struct pfuze_regulator pfuze3000_regulators[] = {
 };
 
 static struct pfuze_regulator pfuze3001_regulators[] = {
-       PFUZE100_SWB_REG(PFUZE3001, SW1, PFUZE100_SW1ABVOL, 0x1f, pfuze3000_sw1a),
-       PFUZE100_SWB_REG(PFUZE3001, SW2, PFUZE100_SW2VOL, 0x7, pfuze3000_sw2lo),
+       PFUZE3000_SW_REG(PFUZE3001, SW1, PFUZE100_SW1ABVOL, 0x1f, pfuze3000_sw1a),
+       PFUZE3000_SW_REG(PFUZE3001, SW2, PFUZE100_SW2VOL, 0x7, pfuze3000_sw2lo),
        PFUZE3000_SW3_REG(PFUZE3001, SW3, PFUZE100_SW3AVOL, 900000, 1650000, 50000),
        PFUZE100_SWB_REG(PFUZE3001, VSNVS, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
        PFUZE100_VGEN_REG(PFUZE3001, VLDO1, PFUZE100_VGEN1VOL, 1800000, 3300000, 100000),
index 53a64d8..7f5c318 100644 (file)
@@ -821,7 +821,7 @@ static const struct rpm_regulator_data rpm_pm8994_regulators[] = {
 static const struct rpm_regulator_data rpm_pmi8994_regulators[] = {
        { "s1", QCOM_SMD_RPM_SMPB, 1, &pmi8994_ftsmps, "vdd_s1" },
        { "s2", QCOM_SMD_RPM_SMPB, 2, &pmi8994_hfsmps, "vdd_s2" },
-       { "s2", QCOM_SMD_RPM_SMPB, 3, &pmi8994_hfsmps, "vdd_s3" },
+       { "s3", QCOM_SMD_RPM_SMPB, 3, &pmi8994_hfsmps, "vdd_s3" },
        { "boost-bypass", QCOM_SMD_RPM_BBYB, 1, &pmi8994_bby, "vdd_bst_byp" },
        {}
 };
index eb13c47..bb1c840 100644 (file)
@@ -182,10 +182,9 @@ enum qdio_irq_poll_states {
 };
 
 struct qdio_input_q {
-       /* first ACK'ed buffer */
-       int ack_start;
-       /* how many SBALs are acknowledged */
-       int ack_count;
+       /* Batch of SBALs that we processed while polling the queue: */
+       unsigned int batch_start;
+       unsigned int batch_count;
        /* last time of noticing incoming data */
        u64 timestamp;
 };
index 286b044..da95c92 100644 (file)
@@ -110,8 +110,8 @@ static int qstat_show(struct seq_file *m, void *v)
        seq_printf(m, "nr_used: %d  ftc: %d\n",
                   atomic_read(&q->nr_buf_used), q->first_to_check);
        if (q->is_input_q) {
-               seq_printf(m, "ack start: %d  ack count: %d\n",
-                          q->u.in.ack_start, q->u.in.ack_count);
+               seq_printf(m, "batch start: %u  batch count: %u\n",
+                          q->u.in.batch_start, q->u.in.batch_count);
                seq_printf(m, "DSCI: %x   IRQs disabled: %u\n",
                           *(u8 *)q->irq_ptr->dsci,
                           test_bit(QDIO_IRQ_DISABLED,
index 610c05f..0c919a1 100644 (file)
@@ -254,10 +254,17 @@ static inline int set_buf_states(struct qdio_q *q, int bufnr,
        if (is_qebsm(q))
                return qdio_do_sqbs(q, state, bufnr, count);
 
+       /* Ensure that all preceding changes to the SBALs are visible: */
+       mb();
+
        for (i = 0; i < count; i++) {
-               xchg(&q->slsb.val[bufnr], state);
+               WRITE_ONCE(q->slsb.val[bufnr], state);
                bufnr = next_buf(bufnr);
        }
+
+       /* Make our SLSB changes visible: */
+       mb();
+
        return count;
 }
 
@@ -393,15 +400,15 @@ int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr,
 
 static inline void qdio_stop_polling(struct qdio_q *q)
 {
-       if (!q->u.in.ack_count)
+       if (!q->u.in.batch_count)
                return;
 
        qperf_inc(q, stop_polling);
 
        /* show the card that we are not polling anymore */
-       set_buf_states(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT,
-                      q->u.in.ack_count);
-       q->u.in.ack_count = 0;
+       set_buf_states(q, q->u.in.batch_start, SLSB_P_INPUT_NOT_INIT,
+                      q->u.in.batch_count);
+       q->u.in.batch_count = 0;
 }
 
 static inline void account_sbals(struct qdio_q *q, unsigned int count)
@@ -441,42 +448,13 @@ static void process_buffer_error(struct qdio_q *q, unsigned int start,
 static inline void inbound_handle_work(struct qdio_q *q, unsigned int start,
                                       int count, bool auto_ack)
 {
-       int new;
-
-       if (auto_ack) {
-               if (!q->u.in.ack_count) {
-                       q->u.in.ack_count = count;
-                       q->u.in.ack_start = start;
-                       return;
-               }
-
-               /* delete the previous ACK's */
-               set_buf_states(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT,
-                              q->u.in.ack_count);
-               q->u.in.ack_count = count;
-               q->u.in.ack_start = start;
-               return;
-       }
-
-       /*
-        * ACK the newest buffer. The ACK will be removed in qdio_stop_polling
-        * or by the next inbound run.
-        */
-       new = add_buf(start, count - 1);
-       set_buf_state(q, new, SLSB_P_INPUT_ACK);
-
-       /* delete the previous ACKs */
-       if (q->u.in.ack_count)
-               set_buf_states(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT,
-                              q->u.in.ack_count);
+       /* ACK the newest SBAL: */
+       if (!auto_ack)
+               set_buf_state(q, add_buf(start, count - 1), SLSB_P_INPUT_ACK);
 
-       q->u.in.ack_count = 1;
-       q->u.in.ack_start = new;
-       count--;
-       if (!count)
-               return;
-       /* need to change ALL buffers to get more interrupts */
-       set_buf_states(q, start, SLSB_P_INPUT_NOT_INIT, count);
+       if (!q->u.in.batch_count)
+               q->u.in.batch_start = start;
+       q->u.in.batch_count += count;
 }
 
 static int get_inbound_buffer_frontier(struct qdio_q *q, unsigned int start)
@@ -525,15 +503,18 @@ static int get_inbound_buffer_frontier(struct qdio_q *q, unsigned int start)
                        account_sbals_error(q, count);
                return count;
        case SLSB_CU_INPUT_EMPTY:
-       case SLSB_P_INPUT_NOT_INIT:
-       case SLSB_P_INPUT_ACK:
                if (q->irq_ptr->perf_stat_enabled)
                        q->q_stats.nr_sbal_nop++;
                DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in nop:%1d %#02x",
                              q->nr, start);
                return 0;
+       case SLSB_P_INPUT_NOT_INIT:
+       case SLSB_P_INPUT_ACK:
+               /* We should never see this state, throw a WARN: */
        default:
-               WARN_ON_ONCE(1);
+               dev_WARN_ONCE(&q->irq_ptr->cdev->dev, 1,
+                             "found state %#x at index %u on queue %u\n",
+                             state, start, q->nr);
                return 0;
        }
 }
@@ -738,11 +719,14 @@ static int get_outbound_buffer_frontier(struct qdio_q *q, unsigned int start)
                DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out primed:%1d",
                              q->nr);
                return 0;
-       case SLSB_P_OUTPUT_NOT_INIT:
        case SLSB_P_OUTPUT_HALTED:
                return 0;
+       case SLSB_P_OUTPUT_NOT_INIT:
+               /* We should never see this state, throw a WARN: */
        default:
-               WARN_ON_ONCE(1);
+               dev_WARN_ONCE(&q->irq_ptr->cdev->dev, 1,
+                             "found state %#x at index %u on queue %u\n",
+                             state, start, q->nr);
                return 0;
        }
 }
@@ -938,10 +922,10 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
        }
 }
 
-static void qdio_handle_activate_check(struct ccw_device *cdev,
-                               unsigned long intparm, int cstat, int dstat)
+static void qdio_handle_activate_check(struct qdio_irq *irq_ptr,
+                                      unsigned long intparm, int cstat,
+                                      int dstat)
 {
-       struct qdio_irq *irq_ptr = cdev->private->qdio_data;
        struct qdio_q *q;
 
        DBF_ERROR("%4x ACT CHECK", irq_ptr->schid.sch_no);
@@ -968,11 +952,9 @@ no_handler:
        lgr_info_log();
 }
 
-static void qdio_establish_handle_irq(struct ccw_device *cdev, int cstat,
+static void qdio_establish_handle_irq(struct qdio_irq *irq_ptr, int cstat,
                                      int dstat)
 {
-       struct qdio_irq *irq_ptr = cdev->private->qdio_data;
-
        DBF_DEV_EVENT(DBF_INFO, irq_ptr, "qest irq");
 
        if (cstat)
@@ -1019,7 +1001,7 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
 
        switch (irq_ptr->state) {
        case QDIO_IRQ_STATE_INACTIVE:
-               qdio_establish_handle_irq(cdev, cstat, dstat);
+               qdio_establish_handle_irq(irq_ptr, cstat, dstat);
                break;
        case QDIO_IRQ_STATE_CLEANUP:
                qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE);
@@ -1031,7 +1013,7 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
                        return;
                }
                if (cstat || dstat)
-                       qdio_handle_activate_check(cdev, intparm, cstat,
+                       qdio_handle_activate_check(irq_ptr, intparm, cstat,
                                                   dstat);
                break;
        case QDIO_IRQ_STATE_STOPPED:
@@ -1446,12 +1428,12 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags,
 
        qperf_inc(q, inbound_call);
 
-       /* If any ACKed SBALs are returned to HW, adjust ACK tracking: */
-       overlap = min(count - sub_buf(q->u.in.ack_start, bufnr),
-                     q->u.in.ack_count);
+       /* If any processed SBALs are returned to HW, adjust our tracking: */
+       overlap = min_t(int, count - sub_buf(q->u.in.batch_start, bufnr),
+                            q->u.in.batch_count);
        if (overlap > 0) {
-               q->u.in.ack_start = add_buf(q->u.in.ack_start, overlap);
-               q->u.in.ack_count -= overlap;
+               q->u.in.batch_start = add_buf(q->u.in.batch_start, overlap);
+               q->u.in.batch_count -= overlap;
        }
 
        count = set_buf_states(q, bufnr, SLSB_CU_INPUT_EMPTY, count);
@@ -1535,12 +1517,11 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
 int do_QDIO(struct ccw_device *cdev, unsigned int callflags,
            int q_nr, unsigned int bufnr, unsigned int count)
 {
-       struct qdio_irq *irq_ptr;
+       struct qdio_irq *irq_ptr = cdev->private->qdio_data;
 
        if (bufnr >= QDIO_MAX_BUFFERS_PER_Q || count > QDIO_MAX_BUFFERS_PER_Q)
                return -EINVAL;
 
-       irq_ptr = cdev->private->qdio_data;
        if (!irq_ptr)
                return -ENODEV;
 
index a646fc8..13b26a1 100644 (file)
@@ -8,6 +8,7 @@
  *            Eric Farman <farman@linux.ibm.com>
  */
 
+#include <linux/slab.h>
 #include <linux/vfio.h>
 #include "vfio_ccw_private.h"
 
index 004ce02..3c3d403 100644 (file)
@@ -195,11 +195,10 @@ static inline struct ep11_cprb *alloc_cprb(size_t payload_len)
        size_t len = sizeof(struct ep11_cprb) + payload_len;
        struct ep11_cprb *cprb;
 
-       cprb = kmalloc(len, GFP_KERNEL);
+       cprb = kzalloc(len, GFP_KERNEL);
        if (!cprb)
                return NULL;
 
-       memset(cprb, 0, len);
        cprb->cprb_len = sizeof(struct ep11_cprb);
        cprb->cprb_ver_id = 0x04;
        memcpy(cprb->func_id, "T4", 2);
index 18a0fb7..88e998d 100644 (file)
@@ -4544,9 +4544,6 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
        int fallback = *(int *)reply->param;
 
        QETH_CARD_TEXT(card, 4, "setaccb");
-       if (cmd->hdr.return_code)
-               return -EIO;
-       qeth_setadpparms_inspect_rc(cmd);
 
        access_ctrl_req = &cmd->data.setadapterparms.data.set_access_ctrl;
        QETH_CARD_TEXT_(card, 2, "rc=%d",
@@ -4556,7 +4553,7 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
                QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_CTRL(%#x) on device %x: %#x\n",
                                 access_ctrl_req->subcmd_code, CARD_DEVID(card),
                                 cmd->data.setadapterparms.hdr.return_code);
-       switch (cmd->data.setadapterparms.hdr.return_code) {
+       switch (qeth_setadpparms_inspect_rc(cmd)) {
        case SET_ACCESS_CTRL_RC_SUCCESS:
                if (card->options.isolation == ISOLATION_MODE_NONE) {
                        dev_info(&card->gdev->dev,
@@ -6840,9 +6837,11 @@ netdev_features_t qeth_features_check(struct sk_buff *skb,
                                      struct net_device *dev,
                                      netdev_features_t features)
 {
+       struct qeth_card *card = dev->ml_priv;
+
        /* Traffic with local next-hop is not eligible for some offloads: */
-       if (skb->ip_summed == CHECKSUM_PARTIAL) {
-               struct qeth_card *card = dev->ml_priv;
+       if (skb->ip_summed == CHECKSUM_PARTIAL &&
+           card->options.isolation != ISOLATION_MODE_FWD) {
                netdev_features_t restricted = 0;
 
                if (skb_is_gso(skb) && !netif_needs_gso(skb, features))
index db320da..79f6e8f 100644 (file)
@@ -577,7 +577,10 @@ static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act)
                                   ZFCP_STATUS_ERP_TIMEDOUT)) {
                        req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
                        zfcp_dbf_rec_run("erscf_1", act);
-                       req->erp_action = NULL;
+                       /* lock-free concurrent access with
+                        * zfcp_erp_timeout_handler()
+                        */
+                       WRITE_ONCE(req->erp_action, NULL);
                }
                if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
                        zfcp_dbf_rec_run("erscf_2", act);
@@ -613,8 +616,14 @@ void zfcp_erp_notify(struct zfcp_erp_action *erp_action, unsigned long set_mask)
 void zfcp_erp_timeout_handler(struct timer_list *t)
 {
        struct zfcp_fsf_req *fsf_req = from_timer(fsf_req, t, timer);
-       struct zfcp_erp_action *act = fsf_req->erp_action;
+       struct zfcp_erp_action *act;
 
+       if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED)
+               return;
+       /* lock-free concurrent access with zfcp_erp_strategy_check_fsfreq() */
+       act = READ_ONCE(fsf_req->erp_action);
+       if (!act)
+               return;
        zfcp_erp_notify(act, ZFCP_STATUS_ERP_TIMEDOUT);
 }
 
index 957889a..5730572 100644 (file)
@@ -1372,27 +1372,6 @@ static struct ccw_device_id virtio_ids[] = {
        {},
 };
 
-#ifdef CONFIG_PM_SLEEP
-static int virtio_ccw_freeze(struct ccw_device *cdev)
-{
-       struct virtio_ccw_device *vcdev = dev_get_drvdata(&cdev->dev);
-
-       return virtio_device_freeze(&vcdev->vdev);
-}
-
-static int virtio_ccw_restore(struct ccw_device *cdev)
-{
-       struct virtio_ccw_device *vcdev = dev_get_drvdata(&cdev->dev);
-       int ret;
-
-       ret = virtio_ccw_set_transport_rev(vcdev);
-       if (ret)
-               return ret;
-
-       return virtio_device_restore(&vcdev->vdev);
-}
-#endif
-
 static struct ccw_driver virtio_ccw_driver = {
        .driver = {
                .owner = THIS_MODULE,
@@ -1405,11 +1384,6 @@ static struct ccw_driver virtio_ccw_driver = {
        .set_online = virtio_ccw_online,
        .notify = virtio_ccw_cio_notify,
        .int_class = IRQIO_VIR,
-#ifdef CONFIG_PM_SLEEP
-       .freeze = virtio_ccw_freeze,
-       .thaw = virtio_ccw_restore,
-       .restore = virtio_ccw_restore,
-#endif
 };
 
 static int __init pure_hex(char **cp, unsigned int *val, int min_digit,
index d022407..bef47f3 100644 (file)
@@ -40,6 +40,7 @@ static struct scsi_host_template aic94xx_sht = {
        /* .name is initialized */
        .name                   = "aic94xx",
        .queuecommand           = sas_queuecommand,
+       .dma_need_drain         = ata_scsi_dma_need_drain,
        .target_alloc           = sas_target_alloc,
        .slave_configure        = sas_slave_configure,
        .scan_finished          = asd_scan_finished,
index 2e1718f..09a7669 100644 (file)
@@ -1756,6 +1756,7 @@ static struct scsi_host_template sht_v1_hw = {
        .proc_name              = DRV_NAME,
        .module                 = THIS_MODULE,
        .queuecommand           = sas_queuecommand,
+       .dma_need_drain         = ata_scsi_dma_need_drain,
        .target_alloc           = sas_target_alloc,
        .slave_configure        = hisi_sas_slave_configure,
        .scan_finished          = hisi_sas_scan_finished,
index e7e7849..968d387 100644 (file)
@@ -3532,6 +3532,7 @@ static struct scsi_host_template sht_v2_hw = {
        .proc_name              = DRV_NAME,
        .module                 = THIS_MODULE,
        .queuecommand           = sas_queuecommand,
+       .dma_need_drain         = ata_scsi_dma_need_drain,
        .target_alloc           = sas_target_alloc,
        .slave_configure        = hisi_sas_slave_configure,
        .scan_finished          = hisi_sas_scan_finished,
index 3e6b78a..55e2321 100644 (file)
@@ -3075,6 +3075,7 @@ static struct scsi_host_template sht_v3_hw = {
        .proc_name              = DRV_NAME,
        .module                 = THIS_MODULE,
        .queuecommand           = sas_queuecommand,
+       .dma_need_drain         = ata_scsi_dma_need_drain,
        .target_alloc           = sas_target_alloc,
        .slave_configure        = hisi_sas_slave_configure,
        .scan_finished          = hisi_sas_scan_finished,
index 7d77997..7d86f4c 100644 (file)
@@ -6731,6 +6731,7 @@ static struct scsi_host_template driver_template = {
        .compat_ioctl = ipr_ioctl,
 #endif
        .queuecommand = ipr_queuecommand,
+       .dma_need_drain = ata_scsi_dma_need_drain,
        .eh_abort_handler = ipr_eh_abort,
        .eh_device_reset_handler = ipr_eh_dev_reset,
        .eh_host_reset_handler = ipr_eh_host_reset,
index 974c3b9..085e285 100644 (file)
@@ -153,6 +153,7 @@ static struct scsi_host_template isci_sht = {
        .name                           = DRV_NAME,
        .proc_name                      = DRV_NAME,
        .queuecommand                   = sas_queuecommand,
+       .dma_need_drain                 = ata_scsi_dma_need_drain,
        .target_alloc                   = sas_target_alloc,
        .slave_configure                = sas_slave_configure,
        .scan_finished                  = isci_host_scan_finished,
index 773c45a..278d15f 100644 (file)
@@ -133,8 +133,10 @@ struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, u32 port_id)
        lockdep_assert_held(&lport->disc.disc_mutex);
 
        rdata = fc_rport_lookup(lport, port_id);
-       if (rdata)
+       if (rdata) {
+               kref_put(&rdata->kref, fc_rport_destroy);
                return rdata;
+       }
 
        if (lport->rport_priv_size > 0)
                rport_priv_size = lport->rport_priv_size;
@@ -481,10 +483,11 @@ static void fc_rport_enter_delete(struct fc_rport_priv *rdata,
 
        fc_rport_state_enter(rdata, RPORT_ST_DELETE);
 
-       kref_get(&rdata->kref);
-       if (rdata->event == RPORT_EV_NONE &&
-           !queue_work(rport_event_queue, &rdata->event_work))
-               kref_put(&rdata->kref, fc_rport_destroy);
+       if (rdata->event == RPORT_EV_NONE) {
+               kref_get(&rdata->kref);
+               if (!queue_work(rport_event_queue, &rdata->event_work))
+                       kref_put(&rdata->kref, fc_rport_destroy);
+       }
 
        rdata->event = event;
 }
index e5a64d4..49c8a18 100644 (file)
@@ -2629,7 +2629,7 @@ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
                        "iscsi_q_%d", shost->host_no);
                ihost->workq = alloc_workqueue("%s",
                        WQ_SYSFS | __WQ_LEGACY | WQ_MEM_RECLAIM | WQ_UNBOUND,
-                       2, ihost->workq_name);
+                       1, ihost->workq_name);
                if (!ihost->workq)
                        goto free_host;
        }
index 69a5249..6637f84 100644 (file)
@@ -11878,7 +11878,8 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba)
        lpfc_sli4_xri_exchange_busy_wait(phba);
 
        /* per-phba callback de-registration for hotplug event */
-       lpfc_cpuhp_remove(phba);
+       if (phba->pport)
+               lpfc_cpuhp_remove(phba);
 
        /* Disable PCI subsystem interrupt */
        lpfc_sli4_disable_intr(phba);
index 319f241..fcf03f7 100644 (file)
@@ -3739,10 +3739,8 @@ static irqreturn_t megasas_isr_fusion(int irq, void *devp)
        if (instance->mask_interrupts)
                return IRQ_NONE;
 
-#if defined(ENABLE_IRQ_POLL)
        if (irq_context->irq_poll_scheduled)
                return IRQ_HANDLED;
-#endif
 
        if (!instance->msix_vectors) {
                mfiStatus = instance->instancet->clear_intr(instance);
index 62e5528..983e568 100644 (file)
@@ -3145,19 +3145,18 @@ BRM_status_show(struct device *cdev, struct device_attribute *attr,
        if (!ioc->is_warpdrive) {
                ioc_err(ioc, "%s: BRM attribute is only for warpdrive\n",
                        __func__);
-               goto out;
+               return 0;
        }
        /* pci_access_mutex lock acquired by sysfs show path */
        mutex_lock(&ioc->pci_access_mutex);
-       if (ioc->pci_error_recovery || ioc->remove_host) {
-               mutex_unlock(&ioc->pci_access_mutex);
-               return 0;
-       }
+       if (ioc->pci_error_recovery || ioc->remove_host)
+               goto out;
 
        /* allocate upto GPIOVal 36 entries */
        sz = offsetof(Mpi2IOUnitPage3_t, GPIOVal) + (sizeof(u16) * 36);
        io_unit_pg3 = kzalloc(sz, GFP_KERNEL);
        if (!io_unit_pg3) {
+               rc = -ENOMEM;
                ioc_err(ioc, "%s: failed allocating memory for iounit_pg3: (%d) bytes\n",
                        __func__, sz);
                goto out;
@@ -3167,6 +3166,7 @@ BRM_status_show(struct device *cdev, struct device_attribute *attr,
            0) {
                ioc_err(ioc, "%s: failed reading iounit_pg3\n",
                        __func__);
+               rc = -EINVAL;
                goto out;
        }
 
@@ -3174,12 +3174,14 @@ BRM_status_show(struct device *cdev, struct device_attribute *attr,
        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
                ioc_err(ioc, "%s: iounit_pg3 failed with ioc_status(0x%04x)\n",
                        __func__, ioc_status);
+               rc = -EINVAL;
                goto out;
        }
 
        if (io_unit_pg3->GPIOCount < 25) {
                ioc_err(ioc, "%s: iounit_pg3->GPIOCount less than 25 entries, detected (%d) entries\n",
                        __func__, io_unit_pg3->GPIOCount);
+               rc = -EINVAL;
                goto out;
        }
 
index 5973eed..b0de3bd 100644 (file)
@@ -33,6 +33,7 @@ static struct scsi_host_template mvs_sht = {
        .module                 = THIS_MODULE,
        .name                   = DRV_NAME,
        .queuecommand           = sas_queuecommand,
+       .dma_need_drain         = ata_scsi_dma_need_drain,
        .target_alloc           = sas_target_alloc,
        .slave_configure        = sas_slave_configure,
        .scan_finished          = mvs_scan_finished,
index a8f5344..9e99262 100644 (file)
@@ -87,6 +87,7 @@ static struct scsi_host_template pm8001_sht = {
        .module                 = THIS_MODULE,
        .name                   = DRV_NAME,
        .queuecommand           = sas_queuecommand,
+       .dma_need_drain         = ata_scsi_dma_need_drain,
        .target_alloc           = sas_target_alloc,
        .slave_configure        = sas_slave_configure,
        .scan_finished          = pm8001_scan_finished,
index 42c3ad2..df670fb 100644 (file)
@@ -3496,7 +3496,9 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
                                qla2x00_clear_loop_id(fcport);
                                fcport->flags |= FCF_FABRIC_DEVICE;
                        } else if (fcport->d_id.b24 != rp->id.b24 ||
-                               fcport->scan_needed) {
+                                  (fcport->scan_needed &&
+                                   fcport->port_type != FCT_INITIATOR &&
+                                   fcport->port_type != FCT_NVME_INITIATOR)) {
                                qlt_schedule_sess_for_deletion(fcport);
                        }
                        fcport->d_id.b24 = rp->id.b24;
index 4576d3a..2436a17 100644 (file)
@@ -5944,7 +5944,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)
                        break;
                }
 
-               if (NVME_TARGET(vha->hw, fcport)) {
+               if (found && NVME_TARGET(vha->hw, fcport)) {
                        if (fcport->disc_state == DSC_DELETE_PEND) {
                                qla2x00_set_fcport_disc_state(fcport, DSC_GNL);
                                vha->fcport_count--;
index d66d47a..fa695a4 100644 (file)
@@ -139,11 +139,12 @@ static void qla_nvme_release_fcp_cmd_kref(struct kref *kref)
        sp->priv = NULL;
        if (priv->comp_status == QLA_SUCCESS) {
                fd->rcv_rsplen = le16_to_cpu(nvme->u.nvme.rsp_pyld_len);
+               fd->status = NVME_SC_SUCCESS;
        } else {
                fd->rcv_rsplen = 0;
                fd->transferred_length = 0;
+               fd->status = NVME_SC_INTERNAL;
        }
-       fd->status = 0;
        spin_unlock_irqrestore(&priv->cmd_lock, flags);
 
        fd->done(fd);
index eed3102..ba84244 100644 (file)
@@ -239,6 +239,7 @@ static struct {
        {"LSI", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
        {"ENGENIO", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
        {"LENOVO", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
+       {"FUJITSU", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
        {"SanDisk", "Cruzer Blade", NULL, BLIST_TRY_VPD_PAGES |
                BLIST_INQUIRY_36},
        {"SMSC", "USB 2 HS-CF", NULL, BLIST_SPARSELUN | BLIST_INQUIRY_36},
index 42f0550..6f41e4b 100644 (file)
@@ -63,6 +63,7 @@ static const struct scsi_dh_blist scsi_dh_blist[] = {
        {"LSI", "INF-01-00",            "rdac", },
        {"ENGENIO", "INF-01-00",        "rdac", },
        {"LENOVO", "DE_Series",         "rdac", },
+       {"FUJITSU", "ETERNUS_AHB",      "rdac", },
        {NULL, NULL,                    NULL },
 };
 
index 0ba7a65..06056e9 100644 (file)
@@ -547,6 +547,15 @@ static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd)
        scsi_uninit_cmd(cmd);
 }
 
+static void scsi_run_queue_async(struct scsi_device *sdev)
+{
+       if (scsi_target(sdev)->single_lun ||
+           !list_empty(&sdev->host->starved_list))
+               kblockd_schedule_work(&sdev->requeue_work);
+       else
+               blk_mq_run_hw_queues(sdev->request_queue, true);
+}
+
 /* Returns false when no more bytes to process, true if there are more */
 static bool scsi_end_request(struct request *req, blk_status_t error,
                unsigned int bytes)
@@ -591,11 +600,7 @@ static bool scsi_end_request(struct request *req, blk_status_t error,
 
        __blk_mq_end_request(req, error);
 
-       if (scsi_target(sdev)->single_lun ||
-           !list_empty(&sdev->host->starved_list))
-               kblockd_schedule_work(&sdev->requeue_work);
-       else
-               blk_mq_run_hw_queues(q, true);
+       scsi_run_queue_async(sdev);
 
        percpu_ref_put(&q->q_usage_counter);
        return false;
@@ -1702,6 +1707,7 @@ out_put_budget:
                 */
                if (req->rq_flags & RQF_DONTPREP)
                        scsi_mq_uninit_cmd(cmd);
+               scsi_run_queue_async(sdev);
                break;
        }
        return ret;
index f4cc08e..7ae5024 100644 (file)
@@ -4760,7 +4760,7 @@ static __init int iscsi_transport_init(void)
 
        iscsi_eh_timer_workq = alloc_workqueue("%s",
                        WQ_SYSFS | __WQ_LEGACY | WQ_MEM_RECLAIM | WQ_UNBOUND,
-                       2, "iscsi_eh");
+                       1, "iscsi_eh");
        if (!iscsi_eh_timer_workq) {
                err = -ENOMEM;
                goto release_nls;
index f866106..f3d5b1b 100644 (file)
@@ -339,7 +339,7 @@ store_spi_transport_##field(struct device *dev,                     \
        struct spi_transport_attrs *tp                                  \
                = (struct spi_transport_attrs *)&starget->starget_data; \
                                                                        \
-       if (i->f->set_##field)                                          \
+       if (!i->f->set_##field)                                         \
                return -EINVAL;                                         \
        val = simple_strtoul(buf, NULL, 0);                             \
        if (val > tp->max_##field)                                      \
index 53dd876..516a7f5 100644 (file)
@@ -106,8 +106,10 @@ static int ufs_bsg_request(struct bsg_job *job)
                desc_op = bsg_request->upiu_req.qr.opcode;
                ret = ufs_bsg_alloc_desc_buffer(hba, job, &desc_buff,
                                                &desc_len, desc_op);
-               if (ret)
+               if (ret) {
+                       pm_runtime_put_sync(hba->dev);
                        goto out;
+               }
 
                /* fall through */
        case UPIU_TRANSACTION_NOP_OUT:
index 01fc0d2..6f54bd8 100644 (file)
@@ -66,10 +66,12 @@ static const struct meson_gx_package_id {
        { "A113D", 0x25, 0x22, 0xff },
        { "S905D2", 0x28, 0x10, 0xf0 },
        { "S905X2", 0x28, 0x40, 0xf0 },
-       { "S922X", 0x29, 0x40, 0xf0 },
        { "A311D", 0x29, 0x10, 0xf0 },
-       { "S905X3", 0x2b, 0x5, 0xf },
-       { "S905D3", 0x2b, 0xb0, 0xf0 },
+       { "S922X", 0x29, 0x40, 0xf0 },
+       { "S905D3", 0x2b, 0x4, 0xf5 },
+       { "S905X3", 0x2b, 0x5, 0xf5 },
+       { "S905X3", 0x2b, 0x10, 0x3f },
+       { "S905D3", 0x2b, 0x30, 0x3f },
        { "A113L", 0x2c, 0x0, 0xf8 },
 };
 
index fec3d67..01bfea1 100644 (file)
@@ -33,6 +33,9 @@ static int __init imx_soc_device_init(void)
        u32 val;
        int ret;
 
+       if (of_machine_is_compatible("fsl,ls1021a"))
+               return 0;
+
        soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
        if (!soc_dev_attr)
                return -ENOMEM;
index 7b0759a..cc57a38 100644 (file)
@@ -22,6 +22,8 @@
 #define OCOTP_UID_LOW                  0x410
 #define OCOTP_UID_HIGH                 0x420
 
+#define IMX8MP_OCOTP_UID_OFFSET                0x10
+
 /* Same as ANADIG_DIGPROG_IMX7D */
 #define ANADIG_DIGPROG_IMX8MM  0x800
 
@@ -87,6 +89,8 @@ static void __init imx8mm_soc_uid(void)
 {
        void __iomem *ocotp_base;
        struct device_node *np;
+       u32 offset = of_machine_is_compatible("fsl,imx8mp") ?
+                    IMX8MP_OCOTP_UID_OFFSET : 0;
 
        np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-ocotp");
        if (!np)
@@ -95,9 +99,9 @@ static void __init imx8mm_soc_uid(void)
        ocotp_base = of_iomap(np, 0);
        WARN_ON(!ocotp_base);
 
-       soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH);
+       soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH + offset);
        soc_uid <<= 32;
-       soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW);
+       soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW + offset);
 
        iounmap(ocotp_base);
        of_node_put(np);
@@ -146,7 +150,7 @@ static const struct imx8_soc_data imx8mp_soc_data = {
        .soc_revision = imx8mm_soc_revision,
 };
 
-static const struct of_device_id imx8_soc_match[] = {
+static __maybe_unused const struct of_device_id imx8_soc_match[] = {
        { .compatible = "fsl,imx8mq", .data = &imx8mq_soc_data, },
        { .compatible = "fsl,imx8mm", .data = &imx8mm_soc_data, },
        { .compatible = "fsl,imx8mn", .data = &imx8mn_soc_data, },
index 038aec3..a01eda7 100644 (file)
@@ -67,7 +67,7 @@ struct knav_reg_config {
        u32             link_ram_size0;
        u32             link_ram_base1;
        u32             __pad2[2];
-       u32             starvation[0];
+       u32             starvation[];
 };
 
 struct knav_reg_region {
index 96c6f77..c9b3f9e 100644 (file)
@@ -256,10 +256,10 @@ static int omap_reset_deassert(struct reset_controller_dev *rcdev,
                goto exit;
 
        /* wait for the status to be set */
-       ret = readl_relaxed_poll_timeout(reset->prm->base +
-                                        reset->prm->data->rstst,
-                                        v, v & BIT(st_bit), 1,
-                                        OMAP_RESET_MAX_WAIT);
+       ret = readl_relaxed_poll_timeout_atomic(reset->prm->base +
+                                                reset->prm->data->rstst,
+                                                v, v & BIT(st_bit), 1,
+                                                OMAP_RESET_MAX_WAIT);
        if (ret)
                pr_err("%s: timedout waiting for %s:%lu\n", __func__,
                       reset->prm->data->name, id);
index 4cfdd07..c742274 100644 (file)
@@ -930,8 +930,9 @@ static int intel_create_dai(struct sdw_cdns *cdns,
 
         /* TODO: Read supported rates/formats from hardware */
        for (i = off; i < (off + num); i++) {
-               dais[i].name = kasprintf(GFP_KERNEL, "SDW%d Pin%d",
-                                        cdns->instance, i);
+               dais[i].name = devm_kasprintf(cdns->dev, GFP_KERNEL,
+                                             "SDW%d Pin%d",
+                                             cdns->instance, i);
                if (!dais[i].name)
                        return -ENOMEM;
 
index a35face..91c6aff 100644 (file)
@@ -588,14 +588,14 @@ static void dspi_release_dma(struct fsl_dspi *dspi)
                return;
 
        if (dma->chan_tx) {
-               dma_unmap_single(dma->chan_tx->device->dev, dma->tx_dma_phys,
-                                dma_bufsize, DMA_TO_DEVICE);
+               dma_free_coherent(dma->chan_tx->device->dev, dma_bufsize,
+                                 dma->tx_dma_buf, dma->tx_dma_phys);
                dma_release_channel(dma->chan_tx);
        }
 
        if (dma->chan_rx) {
-               dma_unmap_single(dma->chan_rx->device->dev, dma->rx_dma_phys,
-                                dma_bufsize, DMA_FROM_DEVICE);
+               dma_free_coherent(dma->chan_rx->device->dev, dma_bufsize,
+                                 dma->rx_dma_buf, dma->rx_dma_phys);
                dma_release_channel(dma->chan_rx);
        }
 }
@@ -1109,6 +1109,8 @@ static int dspi_suspend(struct device *dev)
        struct spi_controller *ctlr = dev_get_drvdata(dev);
        struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr);
 
+       if (dspi->irq)
+               disable_irq(dspi->irq);
        spi_controller_suspend(ctlr);
        clk_disable_unprepare(dspi->clk);
 
@@ -1129,6 +1131,8 @@ static int dspi_resume(struct device *dev)
        if (ret)
                return ret;
        spi_controller_resume(ctlr);
+       if (dspi->irq)
+               enable_irq(dspi->irq);
 
        return 0;
 }
@@ -1385,22 +1389,22 @@ static int dspi_probe(struct platform_device *pdev)
                goto poll_mode;
        }
 
-       ret = devm_request_irq(&pdev->dev, dspi->irq, dspi_interrupt,
-                              IRQF_SHARED, pdev->name, dspi);
+       init_completion(&dspi->xfer_done);
+
+       ret = request_threaded_irq(dspi->irq, dspi_interrupt, NULL,
+                                  IRQF_SHARED, pdev->name, dspi);
        if (ret < 0) {
                dev_err(&pdev->dev, "Unable to attach DSPI interrupt\n");
                goto out_clk_put;
        }
 
-       init_completion(&dspi->xfer_done);
-
 poll_mode:
 
        if (dspi->devtype_data->trans_mode == DSPI_DMA_MODE) {
                ret = dspi_request_dma(dspi, res->start);
                if (ret < 0) {
                        dev_err(&pdev->dev, "can't get dma channels\n");
-                       goto out_clk_put;
+                       goto out_free_irq;
                }
        }
 
@@ -1415,11 +1419,14 @@ poll_mode:
        ret = spi_register_controller(ctlr);
        if (ret != 0) {
                dev_err(&pdev->dev, "Problem registering DSPI ctlr\n");
-               goto out_clk_put;
+               goto out_free_irq;
        }
 
        return ret;
 
+out_free_irq:
+       if (dspi->irq)
+               free_irq(dspi->irq, dspi);
 out_clk_put:
        clk_disable_unprepare(dspi->clk);
 out_ctlr_put:
@@ -1434,18 +1441,8 @@ static int dspi_remove(struct platform_device *pdev)
        struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr);
 
        /* Disconnect from the SPI framework */
-       dspi_release_dma(dspi);
-       clk_disable_unprepare(dspi->clk);
        spi_unregister_controller(dspi->ctlr);
 
-       return 0;
-}
-
-static void dspi_shutdown(struct platform_device *pdev)
-{
-       struct spi_controller *ctlr = platform_get_drvdata(pdev);
-       struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr);
-
        /* Disable RX and TX */
        regmap_update_bits(dspi->regmap, SPI_MCR,
                           SPI_MCR_DIS_TXF | SPI_MCR_DIS_RXF,
@@ -1455,8 +1452,16 @@ static void dspi_shutdown(struct platform_device *pdev)
        regmap_update_bits(dspi->regmap, SPI_MCR, SPI_MCR_HALT, SPI_MCR_HALT);
 
        dspi_release_dma(dspi);
+       if (dspi->irq)
+               free_irq(dspi->irq, dspi);
        clk_disable_unprepare(dspi->clk);
-       spi_unregister_controller(dspi->ctlr);
+
+       return 0;
+}
+
+static void dspi_shutdown(struct platform_device *pdev)
+{
+       dspi_remove(pdev);
 }
 
 static struct platform_driver fsl_dspi_driver = {
index 6783e12..a556795 100644 (file)
@@ -36,7 +36,6 @@
 #define SPI_CFG0_SCK_LOW_OFFSET           8
 #define SPI_CFG0_CS_HOLD_OFFSET           16
 #define SPI_CFG0_CS_SETUP_OFFSET          24
-#define SPI_ADJUST_CFG0_SCK_LOW_OFFSET    16
 #define SPI_ADJUST_CFG0_CS_HOLD_OFFSET    0
 #define SPI_ADJUST_CFG0_CS_SETUP_OFFSET   16
 
@@ -48,6 +47,8 @@
 #define SPI_CFG1_CS_IDLE_MASK             0xff
 #define SPI_CFG1_PACKET_LOOP_MASK         0xff00
 #define SPI_CFG1_PACKET_LENGTH_MASK       0x3ff0000
+#define SPI_CFG2_SCK_HIGH_OFFSET          0
+#define SPI_CFG2_SCK_LOW_OFFSET           16
 
 #define SPI_CMD_ACT                  BIT(0)
 #define SPI_CMD_RESUME               BIT(1)
@@ -283,7 +284,7 @@ static void mtk_spi_set_cs(struct spi_device *spi, bool enable)
 static void mtk_spi_prepare_transfer(struct spi_master *master,
                                     struct spi_transfer *xfer)
 {
-       u32 spi_clk_hz, div, sck_time, cs_time, reg_val = 0;
+       u32 spi_clk_hz, div, sck_time, cs_time, reg_val;
        struct mtk_spi *mdata = spi_master_get_devdata(master);
 
        spi_clk_hz = clk_get_rate(mdata->spi_clk);
@@ -296,18 +297,18 @@ static void mtk_spi_prepare_transfer(struct spi_master *master,
        cs_time = sck_time * 2;
 
        if (mdata->dev_comp->enhance_timing) {
+               reg_val = (((sck_time - 1) & 0xffff)
+                          << SPI_CFG2_SCK_HIGH_OFFSET);
                reg_val |= (((sck_time - 1) & 0xffff)
-                          << SPI_CFG0_SCK_HIGH_OFFSET);
-               reg_val |= (((sck_time - 1) & 0xffff)
-                          << SPI_ADJUST_CFG0_SCK_LOW_OFFSET);
+                          << SPI_CFG2_SCK_LOW_OFFSET);
                writel(reg_val, mdata->base + SPI_CFG2_REG);
-               reg_val |= (((cs_time - 1) & 0xffff)
+               reg_val = (((cs_time - 1) & 0xffff)
                           << SPI_ADJUST_CFG0_CS_HOLD_OFFSET);
                reg_val |= (((cs_time - 1) & 0xffff)
                           << SPI_ADJUST_CFG0_CS_SETUP_OFFSET);
                writel(reg_val, mdata->base + SPI_CFG0_REG);
        } else {
-               reg_val |= (((sck_time - 1) & 0xff)
+               reg_val = (((sck_time - 1) & 0xff)
                           << SPI_CFG0_SCK_HIGH_OFFSET);
                reg_val |= (((sck_time - 1) & 0xff) << SPI_CFG0_SCK_LOW_OFFSET);
                reg_val |= (((cs_time - 1) & 0xff) << SPI_CFG0_CS_HOLD_OFFSET);
index 6721910..0040362 100644 (file)
@@ -1485,6 +1485,11 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
        { PCI_VDEVICE(INTEL, 0x4daa), LPSS_CNL_SSP },
        { PCI_VDEVICE(INTEL, 0x4dab), LPSS_CNL_SSP },
        { PCI_VDEVICE(INTEL, 0x4dfb), LPSS_CNL_SSP },
+       /* TGL-H */
+       { PCI_VDEVICE(INTEL, 0x43aa), LPSS_CNL_SSP },
+       { PCI_VDEVICE(INTEL, 0x43ab), LPSS_CNL_SSP },
+       { PCI_VDEVICE(INTEL, 0x43fb), LPSS_CNL_SSP },
+       { PCI_VDEVICE(INTEL, 0x43fd), LPSS_CNL_SSP },
        /* APL */
        { PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP },
        { PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP },
index 06192c9..cbc2387 100644 (file)
 
 struct rspi_data {
        void __iomem *addr;
-       u32 max_speed_hz;
+       u32 speed_hz;
        struct spi_controller *ctlr;
        struct platform_device *pdev;
        wait_queue_head_t wait;
@@ -258,8 +258,7 @@ static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
        rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
 
        /* Sets transfer bit rate */
-       spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk),
-                           2 * rspi->max_speed_hz) - 1;
+       spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk), 2 * rspi->speed_hz) - 1;
        rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
 
        /* Disable dummy transmission, set 16-bit word access, 1 frame */
@@ -299,14 +298,14 @@ static int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size)
 
        clksrc = clk_get_rate(rspi->clk);
        while (div < 3) {
-               if (rspi->max_speed_hz >= clksrc/4) /* 4=(CLK/2)/2 */
+               if (rspi->speed_hz >= clksrc/4) /* 4=(CLK/2)/2 */
                        break;
                div++;
                clksrc /= 2;
        }
 
        /* Sets transfer bit rate */
-       spbr = DIV_ROUND_UP(clksrc, 2 * rspi->max_speed_hz) - 1;
+       spbr = DIV_ROUND_UP(clksrc, 2 * rspi->speed_hz) - 1;
        rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
        rspi->spcmd |= div << 2;
 
@@ -341,7 +340,7 @@ static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
        rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
 
        /* Sets transfer bit rate */
-       spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk), 2 * rspi->max_speed_hz);
+       spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk), 2 * rspi->speed_hz);
        rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
 
        /* Disable dummy transmission, set byte access */
@@ -949,9 +948,24 @@ static int rspi_prepare_message(struct spi_controller *ctlr,
 {
        struct rspi_data *rspi = spi_controller_get_devdata(ctlr);
        struct spi_device *spi = msg->spi;
+       const struct spi_transfer *xfer;
        int ret;
 
-       rspi->max_speed_hz = spi->max_speed_hz;
+       /*
+        * As the Bit Rate Register must not be changed while the device is
+        * active, all transfers in a message must use the same bit rate.
+        * In theory, the sequencer could be enabled, and each Command Register
+        * could divide the base bit rate by a different value.
+        * However, most RSPI variants do not have Transfer Data Length
+        * Multiplier Setting Registers, so each sequence step would be limited
+        * to a single word, making this feature unsuitable for large
+        * transfers, which would gain most from it.
+        */
+       rspi->speed_hz = spi->max_speed_hz;
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+               if (xfer->speed_hz < rspi->speed_hz)
+                       rspi->speed_hz = xfer->speed_hz;
+       }
 
        rspi->spcmd = SPCMD_SSLKP;
        if (spi->mode & SPI_CPOL)
index 88e6543..bd23c46 100644 (file)
@@ -389,9 +389,9 @@ static int sprd_adi_restart_handler(struct notifier_block *this,
        sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_CTRL, val);
 
        /* Load the watchdog timeout value, 50ms is always enough. */
+       sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOAD_HIGH, 0);
        sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOAD_LOW,
                       WDG_LOAD_VAL & WDG_LOAD_MASK);
-       sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOAD_HIGH, 0);
 
        /* Start the watchdog to reset system */
        sprd_adi_read(sadi, sadi->slave_pbase + REG_WDG_CTRL, &val);
index 3c44bb2..a900962 100644 (file)
@@ -553,20 +553,6 @@ static const struct spi_controller_mem_ops stm32_qspi_mem_ops = {
        .exec_op = stm32_qspi_exec_op,
 };
 
-static void stm32_qspi_release(struct stm32_qspi *qspi)
-{
-       pm_runtime_get_sync(qspi->dev);
-       /* disable qspi */
-       writel_relaxed(0, qspi->io_base + QSPI_CR);
-       stm32_qspi_dma_free(qspi);
-       mutex_destroy(&qspi->lock);
-       pm_runtime_put_noidle(qspi->dev);
-       pm_runtime_disable(qspi->dev);
-       pm_runtime_set_suspended(qspi->dev);
-       pm_runtime_dont_use_autosuspend(qspi->dev);
-       clk_disable_unprepare(qspi->clk);
-}
-
 static int stm32_qspi_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -642,7 +628,7 @@ static int stm32_qspi_probe(struct platform_device *pdev)
        if (IS_ERR(rstc)) {
                ret = PTR_ERR(rstc);
                if (ret == -EPROBE_DEFER)
-                       goto err_qspi_release;
+                       goto err_clk_disable;
        } else {
                reset_control_assert(rstc);
                udelay(2);
@@ -653,7 +639,7 @@ static int stm32_qspi_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, qspi);
        ret = stm32_qspi_dma_setup(qspi);
        if (ret)
-               goto err_qspi_release;
+               goto err_dma_free;
 
        mutex_init(&qspi->lock);
 
@@ -673,15 +659,26 @@ static int stm32_qspi_probe(struct platform_device *pdev)
 
        ret = devm_spi_register_master(dev, ctrl);
        if (ret)
-               goto err_qspi_release;
+               goto err_pm_runtime_free;
 
        pm_runtime_mark_last_busy(dev);
        pm_runtime_put_autosuspend(dev);
 
        return 0;
 
-err_qspi_release:
-       stm32_qspi_release(qspi);
+err_pm_runtime_free:
+       pm_runtime_get_sync(qspi->dev);
+       /* disable qspi */
+       writel_relaxed(0, qspi->io_base + QSPI_CR);
+       mutex_destroy(&qspi->lock);
+       pm_runtime_put_noidle(qspi->dev);
+       pm_runtime_disable(qspi->dev);
+       pm_runtime_set_suspended(qspi->dev);
+       pm_runtime_dont_use_autosuspend(qspi->dev);
+err_dma_free:
+       stm32_qspi_dma_free(qspi);
+err_clk_disable:
+       clk_disable_unprepare(qspi->clk);
 err_master_put:
        spi_master_put(qspi->ctrl);
 
@@ -692,7 +689,16 @@ static int stm32_qspi_remove(struct platform_device *pdev)
 {
        struct stm32_qspi *qspi = platform_get_drvdata(pdev);
 
-       stm32_qspi_release(qspi);
+       pm_runtime_get_sync(qspi->dev);
+       /* disable qspi */
+       writel_relaxed(0, qspi->io_base + QSPI_CR);
+       stm32_qspi_dma_free(qspi);
+       mutex_destroy(&qspi->lock);
+       pm_runtime_put_noidle(qspi->dev);
+       pm_runtime_disable(qspi->dev);
+       pm_runtime_set_suspended(qspi->dev);
+       pm_runtime_dont_use_autosuspend(qspi->dev);
+       clk_disable_unprepare(qspi->clk);
 
        return 0;
 }
index ecea155..fa11cc0 100644 (file)
@@ -198,7 +198,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
                                  struct spi_transfer *tfr)
 {
        struct sun6i_spi *sspi = spi_master_get_devdata(master);
-       unsigned int mclk_rate, div, timeout;
+       unsigned int mclk_rate, div, div_cdr1, div_cdr2, timeout;
        unsigned int start, end, tx_time;
        unsigned int trig_level;
        unsigned int tx_len = 0;
@@ -287,14 +287,12 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
         * First try CDR2, and if we can't reach the expected
         * frequency, fall back to CDR1.
         */
-       div = mclk_rate / (2 * tfr->speed_hz);
-       if (div <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) {
-               if (div > 0)
-                       div--;
-
-               reg = SUN6I_CLK_CTL_CDR2(div) | SUN6I_CLK_CTL_DRS;
+       div_cdr1 = DIV_ROUND_UP(mclk_rate, tfr->speed_hz);
+       div_cdr2 = DIV_ROUND_UP(div_cdr1, 2);
+       if (div_cdr2 <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) {
+               reg = SUN6I_CLK_CTL_CDR2(div_cdr2 - 1) | SUN6I_CLK_CTL_DRS;
        } else {
-               div = ilog2(mclk_rate) - ilog2(tfr->speed_hz);
+               div = min(SUN6I_CLK_CTL_CDR1_MASK, order_base_2(div_cdr1));
                reg = SUN6I_CLK_CTL_CDR1(div);
        }
 
index d753df7..59e0767 100644 (file)
@@ -609,15 +609,20 @@ err_find_dev:
 static int spidev_release(struct inode *inode, struct file *filp)
 {
        struct spidev_data      *spidev;
+       int                     dofree;
 
        mutex_lock(&device_list_lock);
        spidev = filp->private_data;
        filp->private_data = NULL;
 
+       spin_lock_irq(&spidev->spi_lock);
+       /* ... after we unbound from the underlying device? */
+       dofree = (spidev->spi == NULL);
+       spin_unlock_irq(&spidev->spi_lock);
+
        /* last close? */
        spidev->users--;
        if (!spidev->users) {
-               int             dofree;
 
                kfree(spidev->tx_buffer);
                spidev->tx_buffer = NULL;
@@ -625,19 +630,14 @@ static int spidev_release(struct inode *inode, struct file *filp)
                kfree(spidev->rx_buffer);
                spidev->rx_buffer = NULL;
 
-               spin_lock_irq(&spidev->spi_lock);
-               if (spidev->spi)
-                       spidev->speed_hz = spidev->spi->max_speed_hz;
-
-               /* ... after we unbound from the underlying device? */
-               dofree = (spidev->spi == NULL);
-               spin_unlock_irq(&spidev->spi_lock);
-
                if (dofree)
                        kfree(spidev);
+               else
+                       spidev->speed_hz = spidev->spi->max_speed_hz;
        }
 #ifdef CONFIG_SPI_SLAVE
-       spi_slave_abort(spidev->spi);
+       if (!dofree)
+               spi_slave_abort(spidev->spi);
 #endif
        mutex_unlock(&device_list_lock);
 
@@ -787,13 +787,13 @@ static int spidev_remove(struct spi_device *spi)
 {
        struct spidev_data      *spidev = spi_get_drvdata(spi);
 
+       /* prevent new opens */
+       mutex_lock(&device_list_lock);
        /* make sure ops on existing fds can abort cleanly */
        spin_lock_irq(&spidev->spi_lock);
        spidev->spi = NULL;
        spin_unlock_irq(&spidev->spi_lock);
 
-       /* prevent new opens */
-       mutex_lock(&device_list_lock);
        list_del(&spidev->device_entry);
        device_destroy(spidev_class, spidev->devt);
        clear_bit(MINOR(spidev->devt), minors);
index 560649b..e035c9f 100644 (file)
@@ -106,14 +106,22 @@ static int apci1032_cos_insn_config(struct comedi_device *dev,
                                    unsigned int *data)
 {
        struct apci1032_private *devpriv = dev->private;
-       unsigned int shift, oldmask;
+       unsigned int shift, oldmask, himask, lomask;
 
        switch (data[0]) {
        case INSN_CONFIG_DIGITAL_TRIG:
                if (data[1] != 0)
                        return -EINVAL;
                shift = data[3];
-               oldmask = (1U << shift) - 1;
+               if (shift < 32) {
+                       oldmask = (1U << shift) - 1;
+                       himask = data[4] << shift;
+                       lomask = data[5] << shift;
+               } else {
+                       oldmask = 0xffffffffu;
+                       himask = 0;
+                       lomask = 0;
+               }
                switch (data[2]) {
                case COMEDI_DIGITAL_TRIG_DISABLE:
                        devpriv->ctrl = 0;
@@ -136,8 +144,8 @@ static int apci1032_cos_insn_config(struct comedi_device *dev,
                                devpriv->mode2 &= oldmask;
                        }
                        /* configure specified channels */
-                       devpriv->mode1 |= data[4] << shift;
-                       devpriv->mode2 |= data[5] << shift;
+                       devpriv->mode1 |= himask;
+                       devpriv->mode2 |= lomask;
                        break;
                case COMEDI_DIGITAL_TRIG_ENABLE_LEVELS:
                        if (devpriv->ctrl != (APCI1032_CTRL_INT_ENA |
@@ -154,8 +162,8 @@ static int apci1032_cos_insn_config(struct comedi_device *dev,
                                devpriv->mode2 &= oldmask;
                        }
                        /* configure specified channels */
-                       devpriv->mode1 |= data[4] << shift;
-                       devpriv->mode2 |= data[5] << shift;
+                       devpriv->mode1 |= himask;
+                       devpriv->mode2 |= lomask;
                        break;
                default:
                        return -EINVAL;
index 45ad4ba..816dd25 100644 (file)
@@ -452,13 +452,14 @@ static int apci1500_di_cfg_trig(struct comedi_device *dev,
        struct apci1500_private *devpriv = dev->private;
        unsigned int trig = data[1];
        unsigned int shift = data[3];
-       unsigned int hi_mask = data[4] << shift;
-       unsigned int lo_mask = data[5] << shift;
-       unsigned int chan_mask = hi_mask | lo_mask;
-       unsigned int old_mask = (1 << shift) - 1;
-       unsigned int pm = devpriv->pm[trig] & old_mask;
-       unsigned int pt = devpriv->pt[trig] & old_mask;
-       unsigned int pp = devpriv->pp[trig] & old_mask;
+       unsigned int hi_mask;
+       unsigned int lo_mask;
+       unsigned int chan_mask;
+       unsigned int old_mask;
+       unsigned int pm;
+       unsigned int pt;
+       unsigned int pp;
+       unsigned int invalid_chan;
 
        if (trig > 1) {
                dev_dbg(dev->class_dev,
@@ -466,11 +467,28 @@ static int apci1500_di_cfg_trig(struct comedi_device *dev,
                return -EINVAL;
        }
 
-       if (chan_mask > 0xffff) {
+       if (shift <= 16) {
+               hi_mask = data[4] << shift;
+               lo_mask = data[5] << shift;
+               old_mask = (1U << shift) - 1;
+               invalid_chan = (data[4] | data[5]) >> (16 - shift);
+       } else {
+               hi_mask = 0;
+               lo_mask = 0;
+               old_mask = 0xffff;
+               invalid_chan = data[4] | data[5];
+       }
+       chan_mask = hi_mask | lo_mask;
+
+       if (invalid_chan) {
                dev_dbg(dev->class_dev, "invalid digital trigger channel\n");
                return -EINVAL;
        }
 
+       pm = devpriv->pm[trig] & old_mask;
+       pt = devpriv->pt[trig] & old_mask;
+       pp = devpriv->pp[trig] & old_mask;
+
        switch (data[2]) {
        case COMEDI_DIGITAL_TRIG_DISABLE:
                /* clear trigger configuration */
index 10501fe..1268ba3 100644 (file)
@@ -331,14 +331,22 @@ static int apci1564_cos_insn_config(struct comedi_device *dev,
                                    unsigned int *data)
 {
        struct apci1564_private *devpriv = dev->private;
-       unsigned int shift, oldmask;
+       unsigned int shift, oldmask, himask, lomask;
 
        switch (data[0]) {
        case INSN_CONFIG_DIGITAL_TRIG:
                if (data[1] != 0)
                        return -EINVAL;
                shift = data[3];
-               oldmask = (1U << shift) - 1;
+               if (shift < 32) {
+                       oldmask = (1U << shift) - 1;
+                       himask = data[4] << shift;
+                       lomask = data[5] << shift;
+               } else {
+                       oldmask = 0xffffffffu;
+                       himask = 0;
+                       lomask = 0;
+               }
                switch (data[2]) {
                case COMEDI_DIGITAL_TRIG_DISABLE:
                        devpriv->ctrl = 0;
@@ -362,8 +370,8 @@ static int apci1564_cos_insn_config(struct comedi_device *dev,
                                devpriv->mode2 &= oldmask;
                        }
                        /* configure specified channels */
-                       devpriv->mode1 |= data[4] << shift;
-                       devpriv->mode2 |= data[5] << shift;
+                       devpriv->mode1 |= himask;
+                       devpriv->mode2 |= lomask;
                        break;
                case COMEDI_DIGITAL_TRIG_ENABLE_LEVELS:
                        if (devpriv->ctrl != (APCI1564_DI_IRQ_ENA |
@@ -380,8 +388,8 @@ static int apci1564_cos_insn_config(struct comedi_device *dev,
                                devpriv->mode2 &= oldmask;
                        }
                        /* configure specified channels */
-                       devpriv->mode1 |= data[4] << shift;
-                       devpriv->mode2 |= data[5] << shift;
+                       devpriv->mode1 |= himask;
+                       devpriv->mode2 |= lomask;
                        break;
                default:
                        return -EINVAL;
index 4d1eccb..4518c26 100644 (file)
@@ -332,7 +332,7 @@ static int ni6527_intr_insn_config(struct comedi_device *dev,
                case COMEDI_DIGITAL_TRIG_ENABLE_EDGES:
                        /* check shift amount */
                        shift = data[3];
-                       if (shift >= s->n_chan) {
+                       if (shift >= 32) {
                                mask = 0;
                                rising = 0;
                                falling = 0;
index fea06cb..37577bb 100644 (file)
@@ -22,7 +22,7 @@ config VIDEO_ATOMISP
          module will be called atomisp
 
 config VIDEO_ATOMISP_ISP2401
-       bool "VIDEO_ATOMISP_ISP2401"
+       bool "Use Intel Atom ISP on Cherrytail/Anniedale (ISP2401)"
        depends on VIDEO_ATOMISP
        help
          Enable support for Atom ISP2401-based boards.
index 9dc8072..205d0f8 100644 (file)
@@ -156,6 +156,7 @@ atomisp-objs += \
        pci/hive_isp_css_common/host/timed_ctrl.o \
        pci/hive_isp_css_common/host/vmem.o \
        pci/hive_isp_css_shared/host/tag.o \
+       pci/system_local.o \
 
 obj-byt = \
        pci/css_2400_system/hive/ia_css_isp_configs.o \
@@ -182,7 +183,6 @@ INCLUDES += \
        -I$(atomisp)/include/hmm/ \
        -I$(atomisp)/include/mmu/ \
        -I$(atomisp)/pci/ \
-       -I$(atomisp)/pci/hrt/ \
        -I$(atomisp)/pci/base/circbuf/interface/ \
        -I$(atomisp)/pci/base/refcount/interface/ \
        -I$(atomisp)/pci/camera/pipe/interface/ \
@@ -192,7 +192,6 @@ INCLUDES += \
        -I$(atomisp)/pci/hive_isp_css_include/ \
        -I$(atomisp)/pci/hive_isp_css_include/device_access/ \
        -I$(atomisp)/pci/hive_isp_css_include/host/ \
-       -I$(atomisp)/pci/hive_isp_css_include/memory_access/ \
        -I$(atomisp)/pci/hive_isp_css_shared/ \
        -I$(atomisp)/pci/hive_isp_css_shared/host/ \
        -I$(atomisp)/pci/isp/kernels/ \
@@ -311,9 +310,7 @@ INCLUDES += \
        -I$(atomisp)/pci/runtime/tagger/interface/
 
 INCLUDES_byt += \
-       -I$(atomisp)/pci/css_2400_system/ \
        -I$(atomisp)/pci/css_2400_system/hive/ \
-       -I$(atomisp)/pci/css_2400_system/hrt/ \
 
 INCLUDES_cht += \
        -I$(atomisp)/pci/css_2401_system/ \
@@ -321,7 +318,6 @@ INCLUDES_cht += \
        -I$(atomisp)/pci/css_2401_system/hive/ \
        -I$(atomisp)/pci/css_2401_system/hrt/ \
 
-#      -I$(atomisp)/pci/css_2401_system/hrt/ \
 #      -I$(atomisp)/pci/css_2401_system/hive_isp_css_2401_system_generated/ \
 
 DEFINES := -DHRT_HW -DHRT_ISP_CSS_CUSTOM_HOST -DHRT_USE_VIR_ADDRS -D__HOST__
index 90d125b..c907305 100644 (file)
@@ -495,11 +495,11 @@ static int ov2680_h_flip(struct v4l2_subdev *sd, s32 value)
        ret = ov2680_read_reg(client, 1, OV2680_MIRROR_REG, &val);
        if (ret)
                return ret;
-       if (value) {
+       if (value)
                val |= OV2680_FLIP_MIRROR_BIT_ENABLE;
-       } else {
+       else
                val &= ~OV2680_FLIP_MIRROR_BIT_ENABLE;
-       }
+
        ret = ov2680_write_reg(client, 1,
                               OV2680_MIRROR_REG, val);
        if (ret)
index 97ab10b..e698b63 100644 (file)
@@ -1899,7 +1899,7 @@ static int ov5693_probe(struct i2c_client *client)
 {
        struct ov5693_device *dev;
        int i2c;
-       int ret = 0;
+       int ret;
        void *pdata;
        unsigned int i;
 
@@ -1929,8 +1929,10 @@ static int ov5693_probe(struct i2c_client *client)
        pdata = gmin_camera_platform_data(&dev->sd,
                                          ATOMISP_INPUT_FORMAT_RAW_10,
                                          atomisp_bayer_order_bggr);
-       if (!pdata)
+       if (!pdata) {
+               ret = -EINVAL;
                goto out_free;
+       }
 
        ret = ov5693_s_config(&dev->sd, client->irq, pdata);
        if (ret)
index 873344a..5a5121d 100644 (file)
@@ -250,6 +250,7 @@ const struct atomisp_camera_caps *atomisp_get_default_camera_caps(void);
 #define IS_MFLD        __IS_SOC(INTEL_FAM6_ATOM_SALTWELL_MID)
 #define IS_BYT __IS_SOC(INTEL_FAM6_ATOM_SILVERMONT)
 #define IS_CHT __IS_SOC(INTEL_FAM6_ATOM_AIRMONT)
+#define IS_MRFD        __IS_SOC(INTEL_FAM6_ATOM_SILVERMONT_MID)
 #define IS_MOFD        __IS_SOC(INTEL_FAM6_ATOM_AIRMONT_MID)
 
 /* Both CHT and MOFD come with ISP2401 */
index de34ee2..022997f 100644 (file)
@@ -20,9 +20,6 @@
 #define ATOMISP_REGS_H
 
 /* common register definitions */
-#define PUNIT_PORT             0x04
-#define CCK_PORT               0x14
-
 #define PCICMDSTS              0x01
 #define INTR                   0x0f
 #define MSI_CAPID              0x24
index 7686139..f638d0b 100644 (file)
@@ -355,11 +355,11 @@ int atomisp_acc_map(struct atomisp_sub_device *asd, struct atomisp_acc_map *map)
 
                pgnr = DIV_ROUND_UP(map->length, PAGE_SIZE);
                if (pgnr < ((PAGE_ALIGN(map->length)) >> PAGE_SHIFT)) {
-                       dev_err(atomisp_dev,
+                       dev_err(asd->isp->dev,
                                "user space memory size is less than the expected size..\n");
                        return -ENOMEM;
                } else if (pgnr > ((PAGE_ALIGN(map->length)) >> PAGE_SHIFT)) {
-                       dev_err(atomisp_dev,
+                       dev_err(asd->isp->dev,
                                "user space memory size is large than the expected size..\n");
                        return -ENOMEM;
                }
index 7b936e5..8ea65be 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/firmware.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/kfifo.h>
 #include <linux/pm_runtime.h>
@@ -109,7 +110,7 @@ struct atomisp_acc_pipe *atomisp_to_acc_pipe(struct video_device *dev)
 
 static unsigned short atomisp_get_sensor_fps(struct atomisp_sub_device *asd)
 {
-       struct v4l2_subdev_frame_interval fi;
+       struct v4l2_subdev_frame_interval fi = { 0 };
        struct atomisp_device *isp = asd->isp;
 
        unsigned short fps = 0;
@@ -206,6 +207,7 @@ int atomisp_freq_scaling(struct atomisp_device *isp,
                         enum atomisp_dfs_mode mode,
                         bool force)
 {
+       struct pci_dev *pdev = to_pci_dev(isp->dev);
        /* FIXME! Only use subdev[0] status yet */
        struct atomisp_sub_device *asd = &isp->asd[0];
        const struct atomisp_dfs_config *dfs;
@@ -219,7 +221,7 @@ int atomisp_freq_scaling(struct atomisp_device *isp,
                return -EINVAL;
        }
 
-       if ((isp->pdev->device & ATOMISP_PCI_DEVICE_SOC_MASK) ==
+       if ((pdev->device & ATOMISP_PCI_DEVICE_SOC_MASK) ==
            ATOMISP_PCI_DEVICE_SOC_CHT && ATOMISP_USE_YUVPP(asd))
                isp->dfs = &dfs_config_cht_soc;
 
@@ -357,39 +359,41 @@ static void clear_isp_irq(enum hrt_isp_css_irq irq)
        irq_clear_all(IRQ0_ID);
 }
 
-void atomisp_msi_irq_init(struct atomisp_device *isp, struct pci_dev *dev)
+void atomisp_msi_irq_init(struct atomisp_device *isp)
 {
+       struct pci_dev *pdev = to_pci_dev(isp->dev);
        u32 msg32;
        u16 msg16;
 
-       pci_read_config_dword(dev, PCI_MSI_CAPID, &msg32);
+       pci_read_config_dword(pdev, PCI_MSI_CAPID, &msg32);
        msg32 |= 1 << MSI_ENABLE_BIT;
-       pci_write_config_dword(dev, PCI_MSI_CAPID, msg32);
+       pci_write_config_dword(pdev, PCI_MSI_CAPID, msg32);
 
        msg32 = (1 << INTR_IER) | (1 << INTR_IIR);
-       pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, msg32);
+       pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, msg32);
 
-       pci_read_config_word(dev, PCI_COMMAND, &msg16);
+       pci_read_config_word(pdev, PCI_COMMAND, &msg16);
        msg16 |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
                  PCI_COMMAND_INTX_DISABLE);
-       pci_write_config_word(dev, PCI_COMMAND, msg16);
+       pci_write_config_word(pdev, PCI_COMMAND, msg16);
 }
 
-void atomisp_msi_irq_uninit(struct atomisp_device *isp, struct pci_dev *dev)
+void atomisp_msi_irq_uninit(struct atomisp_device *isp)
 {
+       struct pci_dev *pdev = to_pci_dev(isp->dev);
        u32 msg32;
        u16 msg16;
 
-       pci_read_config_dword(dev, PCI_MSI_CAPID, &msg32);
+       pci_read_config_dword(pdev, PCI_MSI_CAPID, &msg32);
        msg32 &=  ~(1 << MSI_ENABLE_BIT);
-       pci_write_config_dword(dev, PCI_MSI_CAPID, msg32);
+       pci_write_config_dword(pdev, PCI_MSI_CAPID, msg32);
 
        msg32 = 0x0;
-       pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, msg32);
+       pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, msg32);
 
-       pci_read_config_word(dev, PCI_COMMAND, &msg16);
+       pci_read_config_word(pdev, PCI_COMMAND, &msg16);
        msg16 &= ~(PCI_COMMAND_MASTER);
-       pci_write_config_word(dev, PCI_COMMAND, msg16);
+       pci_write_config_word(pdev, PCI_COMMAND, msg16);
 }
 
 static void atomisp_sof_event(struct atomisp_sub_device *asd)
@@ -480,11 +484,12 @@ static void print_csi_rx_errors(enum mipi_port_id port,
 /* Clear irq reg */
 static void clear_irq_reg(struct atomisp_device *isp)
 {
+       struct pci_dev *pdev = to_pci_dev(isp->dev);
        u32 msg_ret;
 
-       pci_read_config_dword(isp->pdev, PCI_INTERRUPT_CTRL, &msg_ret);
+       pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &msg_ret);
        msg_ret |= 1 << INTR_IIR;
-       pci_write_config_dword(isp->pdev, PCI_INTERRUPT_CTRL, msg_ret);
+       pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, msg_ret);
 }
 
 static struct atomisp_sub_device *
@@ -665,11 +670,10 @@ bool atomisp_buffers_queued_pipe(struct atomisp_video_pipe *pipe)
 void dump_sp_dmem(struct atomisp_device *isp, unsigned int addr,
                  unsigned int size)
 {
-       u32 __iomem *io_virt_addr;
        unsigned int data = 0;
        unsigned int size32 = DIV_ROUND_UP(size, sizeof(u32));
 
-       dev_dbg(isp->dev, "atomisp_io_base:%p\n", atomisp_io_base);
+       dev_dbg(isp->dev, "atomisp mmio base: %p\n", isp->base);
        dev_dbg(isp->dev, "%s, addr:0x%x, size: %d, size32: %d\n", __func__,
                addr, size, size32);
        if (size32 * 4 + addr > 0x4000) {
@@ -678,13 +682,12 @@ void dump_sp_dmem(struct atomisp_device *isp, unsigned int addr,
                return;
        }
        addr += SP_DMEM_BASE;
-       io_virt_addr = atomisp_io_base + (addr & 0x003FFFFF);
+       addr &= 0x003FFFFF;
        do {
-               data = *io_virt_addr;
+               data = readl(isp->base + addr);
                dev_dbg(isp->dev, "%s, \t [0x%x]:0x%x\n", __func__, addr, data);
-               io_virt_addr += sizeof(u32);
-               size32 -= 1;
-       } while (size32 > 0);
+               addr += sizeof(u32);
+       } while (--size32);
 }
 
 static struct videobuf_buffer *atomisp_css_frame_to_vbuf(
@@ -1289,6 +1292,7 @@ void atomisp_delayed_init_work(struct work_struct *work)
 
 static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout)
 {
+       struct pci_dev *pdev = to_pci_dev(isp->dev);
        enum ia_css_pipe_id css_pipe_id;
        bool stream_restart[MAX_STREAM_NUM] = {0};
        bool depth_mode = false;
@@ -1372,8 +1376,8 @@ static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout)
        clear_isp_irq(hrt_isp_css_irq_sp);
 
        /* Set the SRSE to 3 before resetting */
-       pci_write_config_dword(isp->pdev, PCI_I_CONTROL, isp->saved_regs.i_control |
-                              MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK);
+       pci_write_config_dword(pdev, PCI_I_CONTROL,
+                              isp->saved_regs.i_control | MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK);
 
        /* reset ISP and restore its state */
        isp->isp_timeout = true;
@@ -6158,6 +6162,7 @@ out:
 /*Turn off ISP dphy */
 int atomisp_ospm_dphy_down(struct atomisp_device *isp)
 {
+       struct pci_dev *pdev = to_pci_dev(isp->dev);
        unsigned long flags;
        u32 reg;
 
@@ -6179,9 +6184,9 @@ done:
         * MRFLD HW design need all CSI ports are disabled before
         * powering down the IUNIT.
         */
-       pci_read_config_dword(isp->pdev, MRFLD_PCI_CSI_CONTROL, &reg);
+       pci_read_config_dword(pdev, MRFLD_PCI_CSI_CONTROL, &reg);
        reg |= MRFLD_ALL_CSI_PORTS_OFF_MASK;
-       pci_write_config_dword(isp->pdev, MRFLD_PCI_CSI_CONTROL, reg);
+       pci_write_config_dword(pdev, MRFLD_PCI_CSI_CONTROL, reg);
        return 0;
 }
 
index 0bde995..1c0d464 100644 (file)
@@ -68,8 +68,8 @@ bool atomisp_buffers_queued_pipe(struct atomisp_video_pipe *pipe);
 /*
  * Interrupt functions
  */
-void atomisp_msi_irq_init(struct atomisp_device *isp, struct pci_dev *dev);
-void atomisp_msi_irq_uninit(struct atomisp_device *isp, struct pci_dev *dev);
+void atomisp_msi_irq_init(struct atomisp_device *isp);
+void atomisp_msi_irq_uninit(struct atomisp_device *isp);
 void atomisp_wdt_work(struct work_struct *work);
 void atomisp_wdt(struct timer_list *t);
 void atomisp_setup_flash(struct atomisp_sub_device *asd);
index b2ed83c..6a2a81a 100644 (file)
@@ -29,8 +29,6 @@ struct atomisp_sub_device;
 struct video_device;
 enum atomisp_input_stream_id;
 
-extern void __iomem *atomisp_io_base;
-
 struct atomisp_metadata_buf {
        struct ia_css_metadata *metadata;
        void *md_vptr;
index c1e282a..cccc5bf 100644 (file)
 #include "atomisp_ioctl.h"
 #include "atomisp_acc.h"
 
-#include <asm/intel-mid.h>
-
 #include "ia_css_debug.h"
 #include "ia_css_isp_param.h"
 #include "sh_css_hrt.h"
 #include "ia_css_isys.h"
 
+#include <linux/io.h>
 #include <linux/pm_runtime.h>
 
 /* Assume max number of ACC stages */
@@ -69,92 +68,94 @@ struct bayer_ds_factor {
 
 static void atomisp_css2_hw_store_8(hrt_address addr, uint8_t data)
 {
-       s8 __iomem *io_virt_addr = atomisp_io_base + (addr & 0x003FFFFF);
+       struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
        unsigned long flags;
 
        spin_lock_irqsave(&mmio_lock, flags);
-       *io_virt_addr = data;
+       writeb(data, isp->base + (addr & 0x003FFFFF));
        spin_unlock_irqrestore(&mmio_lock, flags);
 }
 
 static void atomisp_css2_hw_store_16(hrt_address addr, uint16_t data)
 {
-       s16 __iomem *io_virt_addr = atomisp_io_base + (addr & 0x003FFFFF);
+       struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
        unsigned long flags;
 
        spin_lock_irqsave(&mmio_lock, flags);
-       *io_virt_addr = data;
+       writew(data, isp->base + (addr & 0x003FFFFF));
        spin_unlock_irqrestore(&mmio_lock, flags);
 }
 
 void atomisp_css2_hw_store_32(hrt_address addr, uint32_t data)
 {
-       s32 __iomem *io_virt_addr = atomisp_io_base + (addr & 0x003FFFFF);
+       struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
        unsigned long flags;
 
        spin_lock_irqsave(&mmio_lock, flags);
-       *io_virt_addr = data;
+       writel(data, isp->base + (addr & 0x003FFFFF));
        spin_unlock_irqrestore(&mmio_lock, flags);
 }
 
 static uint8_t atomisp_css2_hw_load_8(hrt_address addr)
 {
-       s8 __iomem *io_virt_addr = atomisp_io_base + (addr & 0x003FFFFF);
+       struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
        unsigned long flags;
        u8 ret;
 
        spin_lock_irqsave(&mmio_lock, flags);
-       ret = *io_virt_addr;
+       ret = readb(isp->base + (addr & 0x003FFFFF));
        spin_unlock_irqrestore(&mmio_lock, flags);
        return ret;
 }
 
 static uint16_t atomisp_css2_hw_load_16(hrt_address addr)
 {
-       s16 __iomem *io_virt_addr = atomisp_io_base + (addr & 0x003FFFFF);
+       struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
        unsigned long flags;
        u16 ret;
 
        spin_lock_irqsave(&mmio_lock, flags);
-       ret = *io_virt_addr;
+       ret = readw(isp->base + (addr & 0x003FFFFF));
        spin_unlock_irqrestore(&mmio_lock, flags);
        return ret;
 }
 
 static uint32_t atomisp_css2_hw_load_32(hrt_address addr)
 {
-       s32 __iomem *io_virt_addr = atomisp_io_base + (addr & 0x003FFFFF);
+       struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
        unsigned long flags;
        u32 ret;
 
        spin_lock_irqsave(&mmio_lock, flags);
-       ret = *io_virt_addr;
+       ret = readl(isp->base + (addr & 0x003FFFFF));
        spin_unlock_irqrestore(&mmio_lock, flags);
        return ret;
 }
 
-static void atomisp_css2_hw_store(hrt_address addr,
-                                 const void *from, uint32_t n)
+static void atomisp_css2_hw_store(hrt_address addr, const void *from, uint32_t n)
 {
-       s8 __iomem *io_virt_addr = atomisp_io_base + (addr & 0x003FFFFF);
+       struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
        unsigned long flags;
        unsigned int i;
 
+       addr &= 0x003FFFFF;
        spin_lock_irqsave(&mmio_lock, flags);
-       for (i = 0; i < n; i++, io_virt_addr++, from++)
-               *io_virt_addr = *(s8 *)from;
+       for (i = 0; i < n; i++, from++)
+               writeb(*(s8 *)from, isp->base + addr + i);
+
        spin_unlock_irqrestore(&mmio_lock, flags);
 }
 
 static void atomisp_css2_hw_load(hrt_address addr, void *to, uint32_t n)
 {
-       s8 __iomem *io_virt_addr = atomisp_io_base + (addr & 0x003FFFFF);
+       struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
        unsigned long flags;
        unsigned int i;
 
+       addr &= 0x003FFFFF;
        spin_lock_irqsave(&mmio_lock, flags);
-       for (i = 0; i < n; i++, to++, io_virt_addr++)
-               *(s8 *)to = *io_virt_addr;
+       for (i = 0; i < n; i++, to++)
+               *(s8 *)to = readb(isp->base + addr + i);
        spin_unlock_irqrestore(&mmio_lock, flags);
 }
 
@@ -181,10 +182,10 @@ void atomisp_load_uint32(hrt_address addr, uint32_t *data)
        *data = atomisp_css2_hw_load_32(addr);
 }
 
-static int hmm_get_mmu_base_addr(unsigned int *mmu_base_addr)
+static int hmm_get_mmu_base_addr(struct device *dev, unsigned int *mmu_base_addr)
 {
        if (!sh_mmu_mrfld.get_pd_base) {
-               dev_err(atomisp_dev, "get mmu base address failed.\n");
+               dev_err(dev, "get mmu base address failed.\n");
                return -EINVAL;
        }
 
@@ -839,7 +840,7 @@ int atomisp_css_init(struct atomisp_device *isp)
        int ret;
        int err;
 
-       ret = hmm_get_mmu_base_addr(&mmu_base_addr);
+       ret = hmm_get_mmu_base_addr(isp->dev, &mmu_base_addr);
        if (ret)
                return ret;
 
@@ -941,7 +942,7 @@ int atomisp_css_resume(struct atomisp_device *isp)
        unsigned int mmu_base_addr;
        int ret;
 
-       ret = hmm_get_mmu_base_addr(&mmu_base_addr);
+       ret = hmm_get_mmu_base_addr(isp->dev, &mmu_base_addr);
        if (ret) {
                dev_err(isp->dev, "get base address error.\n");
                return -EINVAL;
@@ -1966,8 +1967,7 @@ void atomisp_css_input_set_mode(struct atomisp_sub_device *asd,
                        true,
                        0x13000,
                        &size_mem_words) != 0) {
-                       if (intel_mid_identify_cpu() ==
-                           INTEL_MID_CPU_CHIP_TANGIER)
+                       if (IS_MRFD)
                                size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_2;
                        else
                                size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_1;
@@ -2414,13 +2414,13 @@ static void __configure_preview_pp_input(struct atomisp_sub_device *asd,
        struct ia_css_resolution  *effective_res =
                    &stream_config->input_config.effective_res;
 
-       const struct bayer_ds_factor bds_fct[] = {{2, 1}, {3, 2}, {5, 4} };
+       static const struct bayer_ds_factor bds_fct[] = {{2, 1}, {3, 2}, {5, 4} };
        /*
         * BZ201033: YUV decimation factor of 4 causes couple of rightmost
         * columns to be shaded. Remove this factor to work around the CSS bug.
         * const unsigned int yuv_dec_fct[] = {4, 2};
         */
-       const unsigned int yuv_dec_fct[] = { 2 };
+       static const unsigned int yuv_dec_fct[] = { 2 };
        unsigned int i;
 
        if (width == 0 && height == 0)
@@ -2540,7 +2540,7 @@ static void __configure_video_pp_input(struct atomisp_sub_device *asd,
        struct ia_css_resolution  *effective_res =
                    &stream_config->input_config.effective_res;
 
-       const struct bayer_ds_factor bds_factors[] = {
+       static const struct bayer_ds_factor bds_factors[] = {
                {8, 1}, {6, 1}, {4, 1}, {3, 1}, {2, 1}, {3, 2}
        };
        unsigned int i;
@@ -4337,7 +4337,7 @@ static const char * const fw_acc_type_name[] = {
        [IA_CSS_ACC_STANDALONE] =       "Stand-alone acceleration",
 };
 
-int atomisp_css_dump_blob_infor(void)
+int atomisp_css_dump_blob_infor(struct atomisp_device *isp)
 {
        struct ia_css_blob_descr *bd = sh_css_blob_info;
        unsigned int i, nm = sh_css_num_binaries;
@@ -4354,8 +4354,7 @@ int atomisp_css_dump_blob_infor(void)
        for (i = 0; i < sh_css_num_binaries - NUM_OF_SPS; i++) {
                switch (bd[i].header.type) {
                case ia_css_isp_firmware:
-                       dev_dbg(atomisp_dev,
-                               "Num%2d type %s (%s), binary id is %2d, name is %s\n",
+                       dev_dbg(isp->dev, "Num%2d type %s (%s), binary id is %2d, name is %s\n",
                                i + NUM_OF_SPS,
                                fw_type_name[bd[i].header.type],
                                fw_acc_type_name[bd[i].header.info.isp.type],
@@ -4363,8 +4362,7 @@ int atomisp_css_dump_blob_infor(void)
                                bd[i].name);
                        break;
                default:
-                       dev_dbg(atomisp_dev,
-                               "Num%2d type %s, name is %s\n",
+                       dev_dbg(isp->dev, "Num%2d type %s, name is %s\n",
                                i + NUM_OF_SPS, fw_type_name[bd[i].header.type],
                                bd[i].name);
                }
index 8376aec..e060153 100644 (file)
@@ -153,7 +153,7 @@ int atomisp_css_debug_dump_isp_binary(void);
 
 int atomisp_css_dump_sp_raw_copy_linecount(bool reduced);
 
-int atomisp_css_dump_blob_infor(void);
+int atomisp_css_dump_blob_infor(struct atomisp_device *isp);
 
 void atomisp_css_set_isp_config_id(struct atomisp_sub_device *asd,
                                   uint32_t isp_config_id);
index fe0e2bf..f670faf 100644 (file)
@@ -62,9 +62,9 @@ static inline int iunit_dump_dbgopt(struct atomisp_device *isp,
 
        if (opt & OPTION_VALID) {
                if (opt & OPTION_BIN_LIST) {
-                       ret = atomisp_css_dump_blob_infor();
+                       ret = atomisp_css_dump_blob_infor(isp);
                        if (ret) {
-                               dev_err(atomisp_dev, "%s dump blob infor err[ret:%d]\n",
+                               dev_err(isp->dev, "%s dump blob infor err[ret:%d]\n",
                                        __func__, ret);
                                goto opt_err;
                        }
@@ -76,7 +76,7 @@ static inline int iunit_dump_dbgopt(struct atomisp_device *isp,
                                atomisp_css_debug_dump_isp_binary();
                        } else {
                                ret = -EPERM;
-                               dev_err(atomisp_dev, "%s dump running bin err[ret:%d]\n",
+                               dev_err(isp->dev, "%s dump running bin err[ret:%d]\n",
                                        __func__, ret);
                                goto opt_err;
                        }
@@ -86,8 +86,7 @@ static inline int iunit_dump_dbgopt(struct atomisp_device *isp,
                        hmm_show_mem_stat(__func__, __LINE__);
        } else {
                ret = -EINVAL;
-               dev_err(atomisp_dev, "%s dump nothing[ret=%d]\n", __func__,
-                       ret);
+               dev_err(isp->dev, "%s dump nothing[ret=%d]\n", __func__, ret);
        }
 
 opt_err:
@@ -185,8 +184,9 @@ static void iunit_drvfs_remove_files(struct device_driver *drv)
                driver_remove_file(drv, &iunit_drvfs_attrs[i]);
 }
 
-int atomisp_drvfs_init(struct device_driver *drv, struct atomisp_device *isp)
+int atomisp_drvfs_init(struct atomisp_device *isp)
 {
+       struct device_driver *drv = isp->dev->driver;
        int ret;
 
        iunit_debug.isp = isp;
@@ -194,7 +194,7 @@ int atomisp_drvfs_init(struct device_driver *drv, struct atomisp_device *isp)
 
        ret = iunit_drvfs_create_files(iunit_debug.drv);
        if (ret) {
-               dev_err(atomisp_dev, "drvfs_create_files error: %d\n", ret);
+               dev_err(isp->dev, "drvfs_create_files error: %d\n", ret);
                iunit_drvfs_remove_files(iunit_debug.drv);
        }
 
index 4911037..8f4cc72 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef        __ATOMISP_DRVFS_H__
 #define        __ATOMISP_DRVFS_H__
 
-int atomisp_drvfs_init(struct device_driver *drv, struct atomisp_device *isp);
+int atomisp_drvfs_init(struct atomisp_device *isp);
 void atomisp_drvfs_exit(void);
 
 #endif /* __ATOMISP_DRVFS_H__ */
index 1af9da8..0df46a1 100644 (file)
@@ -26,6 +26,9 @@ enum clock_rate {
 #define CLK_RATE_19_2MHZ       19200000
 #define CLK_RATE_25_0MHZ       25000000
 
+/* Valid clock number range from 0 to 5 */
+#define MAX_CLK_COUNT                   5
+
 /* X-Powers AXP288 register set */
 #define ALDO1_SEL_REG  0x28
 #define ALDO1_CTRL3_REG        0x13
@@ -61,9 +64,7 @@ enum clock_rate {
 
 struct gmin_subdev {
        struct v4l2_subdev *subdev;
-       int clock_num;
        enum clock_rate clock_src;
-       bool clock_on;
        struct clk *pmc_clk;
        struct gpio_desc *gpio0;
        struct gpio_desc *gpio1;
@@ -75,11 +76,16 @@ struct gmin_subdev {
        unsigned int csi_lanes;
        enum atomisp_input_format csi_fmt;
        enum atomisp_bayer_order csi_bayer;
+
+       bool clock_on;
        bool v1p8_on;
        bool v2p8_on;
        bool v1p2_on;
        bool v2p8_vcm_on;
 
+       int v1p8_gpio;
+       int v2p8_gpio;
+
        u8 pwm_i2c_addr;
 
        /* For PMIC AXP */
@@ -90,9 +96,9 @@ struct gmin_subdev {
 static struct gmin_subdev gmin_subdevs[MAX_SUBDEVS];
 
 /* ACPI HIDs for the PMICs that could be used by this driver */
-#define PMIC_ACPI_AXP          "INT33F4:00"    /* XPower AXP288 PMIC */
-#define PMIC_ACPI_TI           "INT33F5:00"    /* Dollar Cove TI PMIC */
-#define PMIC_ACPI_CRYSTALCOVE  "INT33FD:00"    /* Crystal Cove PMIC */
+#define PMIC_ACPI_AXP          "INT33F4"       /* XPower AXP288 PMIC */
+#define PMIC_ACPI_TI           "INT33F5"       /* Dollar Cove TI PMIC */
+#define PMIC_ACPI_CRYSTALCOVE  "INT33FD"       /* Crystal Cove PMIC */
 
 #define PMIC_PLATFORM_TI       "intel_soc_pmic_chtdc_ti"
 
@@ -105,7 +111,7 @@ static enum {
 } pmic_id;
 
 static const char *pmic_name[] = {
-       [PMIC_UNSET]            = "unset",
+       [PMIC_UNSET]            = "ACPI device PM",
        [PMIC_REGULATOR]        = "regulator driver",
        [PMIC_AXP]              = "XPower AXP288 PMIC",
        [PMIC_TI]               = "Dollar Cove TI PMIC",
@@ -119,24 +125,6 @@ static const struct atomisp_platform_data pdata = {
        .subdevs = pdata_subdevs,
 };
 
-/*
- * Something of a hack.  The ECS E7 board drives camera 2.8v from an
- * external regulator instead of the PMIC.  There's a gmin_CamV2P8
- * config variable that specifies the GPIO to handle this particular
- * case, but this needs a broader architecture for handling camera
- * power.
- */
-enum { V2P8_GPIO_UNSET = -2, V2P8_GPIO_NONE = -1 };
-static int v2p8_gpio = V2P8_GPIO_UNSET;
-
-/*
- * Something of a hack. The CHT RVP board drives camera 1.8v from an
- * external regulator instead of the PMIC just like ECS E7 board, see the
- * comments above.
- */
-enum { V1P8_GPIO_UNSET = -2, V1P8_GPIO_NONE = -1 };
-static int v1p8_gpio = V1P8_GPIO_UNSET;
-
 static LIST_HEAD(vcm_devices);
 static DEFINE_MUTEX(vcm_lock);
 
@@ -199,6 +187,8 @@ int atomisp_register_i2c_module(struct v4l2_subdev *subdev,
         * gmin_subdev struct is already initialized for us.
         */
        gs = find_gmin_subdev(subdev);
+       if (!gs)
+               return -ENODEV;
 
        pdata.subdevs[i].type = type;
        pdata.subdevs[i].port = gs->csi_port;
@@ -294,6 +284,7 @@ static struct gmin_cfg_var mrd7_vars[] = {
        {"INT33F8:00_CsiFmt", "13"},
        {"INT33F8:00_CsiBayer", "0"},
        {"INT33F8:00_CamClk", "0"},
+
        {"INT33F9:00_CamType", "1"},
        {"INT33F9:00_CsiPort", "0"},
        {"INT33F9:00_CsiLanes", "1"},
@@ -309,6 +300,7 @@ static struct gmin_cfg_var ecs7_vars[] = {
        {"INT33BE:00_CsiFmt", "13"},
        {"INT33BE:00_CsiBayer", "2"},
        {"INT33BE:00_CamClk", "0"},
+
        {"INT33F0:00_CsiPort", "0"},
        {"INT33F0:00_CsiLanes", "1"},
        {"INT33F0:00_CsiFmt", "13"},
@@ -322,6 +314,7 @@ static struct gmin_cfg_var i8880_vars[] = {
        {"XXOV2680:00_CsiPort", "1"},
        {"XXOV2680:00_CsiLanes", "1"},
        {"XXOV2680:00_CamClk", "0"},
+
        {"XXGC0310:00_CsiPort", "0"},
        {"XXGC0310:00_CsiLanes", "1"},
        {"XXGC0310:00_CamClk", "1"},
@@ -381,34 +374,27 @@ static const guid_t atomisp_dsm_guid = GUID_INIT(0xdc2f6c4f, 0x045b, 0x4f1d,
 #define GMIN_PMC_CLK_NAME 14 /* "pmc_plt_clk_[0..5]" */
 static char gmin_pmc_clk_name[GMIN_PMC_CLK_NAME];
 
-static int gmin_i2c_match_one(struct device *dev, const void *data)
-{
-       const char *name = data;
-       struct i2c_client *client;
-
-       if (dev->type != &i2c_client_type)
-               return 0;
-
-       client = to_i2c_client(dev);
-
-       return (!strcmp(name, client->name));
-}
-
 static struct i2c_client *gmin_i2c_dev_exists(struct device *dev, char *name,
                                              struct i2c_client **client)
 {
+       struct acpi_device *adev;
        struct device *d;
 
-       while ((d = bus_find_device(&i2c_bus_type, NULL, name,
-                                   gmin_i2c_match_one))) {
-               *client = to_i2c_client(d);
-               dev_dbg(dev, "found '%s' at address 0x%02x, adapter %d\n",
-                       (*client)->name, (*client)->addr,
-                       (*client)->adapter->nr);
-               return *client;
-       }
+       adev = acpi_dev_get_first_match_dev(name, NULL, -1);
+       if (!adev)
+               return NULL;
 
-       return NULL;
+       d = bus_find_device_by_acpi_dev(&i2c_bus_type, adev);
+       acpi_dev_put(adev);
+       if (!d)
+               return NULL;
+
+       *client = i2c_verify_client(d);
+       put_device(d);
+
+       dev_dbg(dev, "found '%s' at address 0x%02x, adapter %d\n",
+               (*client)->name, (*client)->addr, (*client)->adapter->nr);
+       return *client;
 }
 
 static int gmin_i2c_write(struct device *dev, u16 i2c_addr, u8 reg,
@@ -427,94 +413,222 @@ static int gmin_i2c_write(struct device *dev, u16 i2c_addr, u8 reg,
                "I2C write, addr: 0x%02x, reg: 0x%02x, value: 0x%02x, mask: 0x%02x\n",
                i2c_addr, reg, value, mask);
 
-       ret = intel_soc_pmic_exec_mipi_pmic_seq_element(i2c_addr, reg,
-                                                       value, mask);
-
-       if (ret == -EOPNOTSUPP) {
+       ret = intel_soc_pmic_exec_mipi_pmic_seq_element(i2c_addr, reg, value, mask);
+       if (ret == -EOPNOTSUPP)
                dev_err(dev,
                        "ACPI didn't mapped the OpRegion needed to access I2C address 0x%02x.\n"
-                       "Need to compile the Kernel using CONFIG_*_PMIC_OPREGION settings\n",
+                       "Need to compile the kernel using CONFIG_*_PMIC_OPREGION settings\n",
                        i2c_addr);
-               return ret;
-       }
 
        return ret;
 }
 
-static struct gmin_subdev *gmin_subdev_add(struct v4l2_subdev *subdev)
+static int atomisp_get_acpi_power(struct device *dev)
 {
-       struct i2c_client *power = NULL, *client = v4l2_get_subdevdata(subdev);
-       struct acpi_device *adev;
-       acpi_handle handle;
-       struct device *dev;
-       int i, ret;
+       char name[5];
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       struct acpi_buffer b_name = { sizeof(name), name };
+       union acpi_object *package, *element;
+       acpi_handle handle = ACPI_HANDLE(dev);
+       acpi_handle rhandle;
+       acpi_status status;
+       int clock_num = -1;
+       int i;
 
-       if (!client)
-               return NULL;
+       status = acpi_evaluate_object(handle, "_PR0", NULL, &buffer);
+       if (!ACPI_SUCCESS(status))
+               return -1;
 
-       dev = &client->dev;
+       package = buffer.pointer;
 
-       handle = ACPI_HANDLE(dev);
+       if (!buffer.length || !package
+           || package->type != ACPI_TYPE_PACKAGE
+           || !package->package.count)
+               goto fail;
 
-       // FIXME: may need to release resources allocated by acpi_bus_get_device()
-       if (!handle || acpi_bus_get_device(handle, &adev)) {
-               dev_err(dev, "Error could not get ACPI device\n");
-               return NULL;
-       }
+       for (i = 0; i < package->package.count; i++) {
+               element = &package->package.elements[i];
 
-       dev_info(&client->dev, "%s: ACPI detected it on bus ID=%s, HID=%s\n",
-               __func__, acpi_device_bid(adev), acpi_device_hid(adev));
+               if (element->type != ACPI_TYPE_LOCAL_REFERENCE)
+                       continue;
 
-       if (!pmic_id) {
-               if (gmin_i2c_dev_exists(dev, PMIC_ACPI_TI, &power))
-                       pmic_id = PMIC_TI;
-               else if (gmin_i2c_dev_exists(dev, PMIC_ACPI_AXP, &power))
-                       pmic_id = PMIC_AXP;
-               else if (gmin_i2c_dev_exists(dev, PMIC_ACPI_CRYSTALCOVE, &power))
-                       pmic_id = PMIC_CRYSTALCOVE;
-               else
-                       pmic_id = PMIC_REGULATOR;
+               rhandle = element->reference.handle;
+               if (!rhandle)
+                       goto fail;
+
+               acpi_get_name(rhandle, ACPI_SINGLE_NAME, &b_name);
+
+               dev_dbg(dev, "Found PM resource '%s'\n", name);
+               if (strlen(name) == 4 && !strncmp(name, "CLK", 3)) {
+                       if (name[3] >= '0' && name[3] <= '4')
+                               clock_num = name[3] - '0';
+#if 0
+                       /*
+                        * We could abort here, but let's parse all resources,
+                        * as this is helpful for debugging purposes
+                        */
+                       if (clock_num >= 0)
+                               break;
+#endif
+               }
        }
 
-       for (i = 0; i < MAX_SUBDEVS && gmin_subdevs[i].subdev; i++)
-               ;
-       if (i >= MAX_SUBDEVS)
-               return NULL;
+fail:
+       ACPI_FREE(buffer.pointer);
+
+       return clock_num;
+}
+
+static u8 gmin_get_pmic_id_and_addr(struct device *dev)
+{
+       struct i2c_client *power;
+       static u8 pmic_i2c_addr;
+
+       if (pmic_id)
+               return pmic_i2c_addr;
+
+       if (gmin_i2c_dev_exists(dev, PMIC_ACPI_TI, &power))
+               pmic_id = PMIC_TI;
+       else if (gmin_i2c_dev_exists(dev, PMIC_ACPI_AXP, &power))
+               pmic_id = PMIC_AXP;
+       else if (gmin_i2c_dev_exists(dev, PMIC_ACPI_CRYSTALCOVE, &power))
+               pmic_id = PMIC_CRYSTALCOVE;
+       else
+               pmic_id = PMIC_REGULATOR;
+
+       pmic_i2c_addr = power ? power->addr : 0;
+       return pmic_i2c_addr;
+}
+
+static int gmin_detect_pmic(struct v4l2_subdev *subdev)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(subdev);
+       struct device *dev = &client->dev;
+       u8 pmic_i2c_addr;
+
+       pmic_i2c_addr = gmin_get_pmic_id_and_addr(dev);
+       dev_info(dev, "gmin: power management provided via %s (i2c addr 0x%02x)\n",
+                pmic_name[pmic_id], pmic_i2c_addr);
+       return pmic_i2c_addr;
+}
+
+static int gmin_subdev_add(struct gmin_subdev *gs)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(gs->subdev);
+       struct device *dev = &client->dev;
+       struct acpi_device *adev = ACPI_COMPANION(dev);
+       int ret, clock_num = -1;
+
+       dev_info(dev, "%s: ACPI path is %pfw\n", __func__, dev_fwnode(dev));
+
+       /*WA:CHT requires XTAL clock as PLL is not stable.*/
+       gs->clock_src = gmin_get_var_int(dev, false, "ClkSrc",
+                                        VLV2_CLK_PLL_19P2MHZ);
+
+       gs->csi_port = gmin_get_var_int(dev, false, "CsiPort", 0);
+       gs->csi_lanes = gmin_get_var_int(dev, false, "CsiLanes", 1);
+
+       gs->gpio0 = gpiod_get_index(dev, NULL, 0, GPIOD_OUT_LOW);
+       if (IS_ERR(gs->gpio0))
+               gs->gpio0 = NULL;
+       else
+               dev_info(dev, "will handle gpio0 via ACPI\n");
+
+       gs->gpio1 = gpiod_get_index(dev, NULL, 1, GPIOD_OUT_LOW);
+       if (IS_ERR(gs->gpio1))
+               gs->gpio1 = NULL;
+       else
+               dev_info(dev, "will handle gpio1 via ACPI\n");
+
+       /*
+        * Those are used only when there is an external regulator apart
+        * from the PMIC that would be providing power supply, like on the
+        * two cases below:
+        *
+        * The ECS E7 board drives camera 2.8v from an external regulator
+        * instead of the PMIC.  There's a gmin_CamV2P8 config variable
+        * that specifies the GPIO to handle this particular case,
+        * but this needs a broader architecture for handling camera power.
+        *
+        * The CHT RVP board drives camera 1.8v from an* external regulator
+        * instead of the PMIC just like ECS E7 board.
+        */
 
-       if (power) {
-               gmin_subdevs[i].pwm_i2c_addr = power->addr;
+       gs->v1p8_gpio = gmin_get_var_int(dev, true, "V1P8GPIO", -1);
+       gs->v2p8_gpio = gmin_get_var_int(dev, true, "V2P8GPIO", -1);
+
+       /*
+        * FIXME:
+        *
+        * The ACPI handling code checks for the _PR? tables in order to
+        * know what is required to switch the device from power state
+        * D0 (_PR0) up to D3COLD (_PR3).
+        *
+        * The adev->flags.power_manageable is set to true if the device
+        * has a _PR0 table, which can be checked by calling
+        * acpi_device_power_manageable(adev).
+        *
+        * However, this only says that the device can be set to power off
+        * mode.
+        *
+        * At least on the DSDT tables we've seen so far, there's no _PR3,
+        * nor _PS3 (which would have a somewhat similar effect).
+        * So, using ACPI for power management won't work, except if adding
+        * an ACPI override logic somewhere.
+        *
+        * So, at least for the existing devices we know, the check below
+        * will always be false.
+        */
+       if (acpi_device_can_wakeup(adev) &&
+           acpi_device_can_poweroff(adev)) {
                dev_info(dev,
-                        "gmin: power management provided via %s (i2c addr 0x%02x)\n",
-                        pmic_name[pmic_id], power->addr);
-       } else {
-               dev_info(dev, "gmin: power management provided via %s\n",
-                        pmic_name[pmic_id]);
+                        "gmin: power management provided via device PM\n");
+               return 0;
        }
 
-       gmin_subdevs[i].subdev = subdev;
-       gmin_subdevs[i].clock_num = gmin_get_var_int(dev, false, "CamClk", 0);
-       /*WA:CHT requires XTAL clock as PLL is not stable.*/
-       gmin_subdevs[i].clock_src = gmin_get_var_int(dev, false, "ClkSrc",
-                                   VLV2_CLK_PLL_19P2MHZ);
-       gmin_subdevs[i].csi_port = gmin_get_var_int(dev, false, "CsiPort", 0);
-       gmin_subdevs[i].csi_lanes = gmin_get_var_int(dev, false, "CsiLanes", 1);
+       /*
+        * The code below is here due to backward compatibility with devices
+        * whose ACPI BIOS may not contain everything that would be needed
+        * in order to set clocks and do power management.
+        */
+
+       /*
+        * According with :
+        *   https://github.com/projectceladon/hardware-intel-kernelflinger/blob/master/doc/fastboot.md
+        *
+        * The "CamClk" EFI var is set via fastboot on some Android devices,
+        * and seems to contain the number of the clock used to feed the
+        * sensor.
+        *
+        * On systems with a proper ACPI table, this is given via the _PR0
+        * power resource table. The logic below should first check if there
+        * is a power resource already, falling back to the EFI vars detection
+        * otherwise.
+        */
 
-       /* get PMC clock with clock framework */
-       snprintf(gmin_pmc_clk_name,
-                sizeof(gmin_pmc_clk_name),
-                "%s_%d", "pmc_plt_clk", gmin_subdevs[i].clock_num);
+       /* Try first to use ACPI to get the clock resource */
+       if (acpi_device_power_manageable(adev))
+               clock_num = atomisp_get_acpi_power(dev);
 
-       gmin_subdevs[i].pmc_clk = devm_clk_get(dev, gmin_pmc_clk_name);
-       if (IS_ERR(gmin_subdevs[i].pmc_clk)) {
-               ret = PTR_ERR(gmin_subdevs[i].pmc_clk);
+       /* Fall-back use EFI and/or DMI match */
+       if (clock_num < 0)
+               clock_num = gmin_get_var_int(dev, false, "CamClk", 0);
 
-               dev_err(dev,
-                       "Failed to get clk from %s : %d\n",
-                       gmin_pmc_clk_name,
-                       ret);
+       if (clock_num < 0 || clock_num > MAX_CLK_COUNT) {
+               dev_err(dev, "Invalid clock number\n");
+               return -EINVAL;
+       }
 
-               return NULL;
+       snprintf(gmin_pmc_clk_name, sizeof(gmin_pmc_clk_name),
+                "%s_%d", "pmc_plt_clk", clock_num);
+
+       gs->pmc_clk = devm_clk_get(dev, gmin_pmc_clk_name);
+       if (IS_ERR(gs->pmc_clk)) {
+               ret = PTR_ERR(gs->pmc_clk);
+               dev_err(dev, "Failed to get clk from %s: %d\n", gmin_pmc_clk_name, ret);
+               return ret;
        }
+       dev_info(dev, "Will use CLK%d (%s)\n", clock_num, gmin_pmc_clk_name);
 
        /*
         * The firmware might enable the clock at
@@ -526,25 +640,17 @@ static struct gmin_subdev *gmin_subdev_add(struct v4l2_subdev *subdev)
         * to disable a clock that has not been enabled,
         * we need to enable the clock first.
         */
-       ret = clk_prepare_enable(gmin_subdevs[i].pmc_clk);
+       ret = clk_prepare_enable(gs->pmc_clk);
        if (!ret)
-               clk_disable_unprepare(gmin_subdevs[i].pmc_clk);
-
-       gmin_subdevs[i].gpio0 = gpiod_get_index(dev, NULL, 0, GPIOD_OUT_LOW);
-       if (IS_ERR(gmin_subdevs[i].gpio0))
-               gmin_subdevs[i].gpio0 = NULL;
-
-       gmin_subdevs[i].gpio1 = gpiod_get_index(dev, NULL, 1, GPIOD_OUT_LOW);
-       if (IS_ERR(gmin_subdevs[i].gpio1))
-               gmin_subdevs[i].gpio1 = NULL;
+               clk_disable_unprepare(gs->pmc_clk);
 
        switch (pmic_id) {
        case PMIC_REGULATOR:
-               gmin_subdevs[i].v1p8_reg = regulator_get(dev, "V1P8SX");
-               gmin_subdevs[i].v2p8_reg = regulator_get(dev, "V2P8SX");
+               gs->v1p8_reg = regulator_get(dev, "V1P8SX");
+               gs->v2p8_reg = regulator_get(dev, "V2P8SX");
 
-               gmin_subdevs[i].v1p2_reg = regulator_get(dev, "V1P2A");
-               gmin_subdevs[i].v2p8_vcm_reg = regulator_get(dev, "VPROG4B");
+               gs->v1p2_reg = regulator_get(dev, "V1P2A");
+               gs->v2p8_vcm_reg = regulator_get(dev, "VPROG4B");
 
                /* Note: ideally we would initialize v[12]p8_on to the
                 * output of regulator_is_enabled(), but sadly that
@@ -556,32 +662,31 @@ static struct gmin_subdev *gmin_subdev_add(struct v4l2_subdev *subdev)
                break;
 
        case PMIC_AXP:
-               gmin_subdevs[i].eldo1_1p8v = gmin_get_var_int(dev, false,
-                                                             "eldo1_1p8v",
-                                                             ELDO1_1P8V);
-               gmin_subdevs[i].eldo1_sel_reg = gmin_get_var_int(dev, false,
-                                                                "eldo1_sel_reg",
-                                                                ELDO1_SEL_REG);
-               gmin_subdevs[i].eldo1_ctrl_shift = gmin_get_var_int(dev, false,
-                                                                   "eldo1_ctrl_shift",
-                                                                   ELDO1_CTRL_SHIFT);
-               gmin_subdevs[i].eldo2_1p8v = gmin_get_var_int(dev, false,
-                                                             "eldo2_1p8v",
-                                                             ELDO2_1P8V);
-               gmin_subdevs[i].eldo2_sel_reg = gmin_get_var_int(dev, false,
-                                                                "eldo2_sel_reg",
-                                                                ELDO2_SEL_REG);
-               gmin_subdevs[i].eldo2_ctrl_shift = gmin_get_var_int(dev, false,
-                                                                   "eldo2_ctrl_shift",
-                                                                   ELDO2_CTRL_SHIFT);
-               gmin_subdevs[i].pwm_i2c_addr = power->addr;
+               gs->eldo1_1p8v = gmin_get_var_int(dev, false,
+                                                 "eldo1_1p8v",
+                                                 ELDO1_1P8V);
+               gs->eldo1_sel_reg = gmin_get_var_int(dev, false,
+                                                    "eldo1_sel_reg",
+                                                    ELDO1_SEL_REG);
+               gs->eldo1_ctrl_shift = gmin_get_var_int(dev, false,
+                                                       "eldo1_ctrl_shift",
+                                                       ELDO1_CTRL_SHIFT);
+               gs->eldo2_1p8v = gmin_get_var_int(dev, false,
+                                                 "eldo2_1p8v",
+                                                 ELDO2_1P8V);
+               gs->eldo2_sel_reg = gmin_get_var_int(dev, false,
+                                                    "eldo2_sel_reg",
+                                                    ELDO2_SEL_REG);
+               gs->eldo2_ctrl_shift = gmin_get_var_int(dev, false,
+                                                       "eldo2_ctrl_shift",
+                                                       ELDO2_CTRL_SHIFT);
                break;
 
        default:
                break;
        }
 
-       return &gmin_subdevs[i];
+       return 0;
 }
 
 static struct gmin_subdev *find_gmin_subdev(struct v4l2_subdev *subdev)
@@ -591,7 +696,17 @@ static struct gmin_subdev *find_gmin_subdev(struct v4l2_subdev *subdev)
        for (i = 0; i < MAX_SUBDEVS; i++)
                if (gmin_subdevs[i].subdev == subdev)
                        return &gmin_subdevs[i];
-       return gmin_subdev_add(subdev);
+       return NULL;
+}
+
+static struct gmin_subdev *find_free_gmin_subdev_slot(void)
+{
+       unsigned int i;
+
+       for (i = 0; i < MAX_SUBDEVS; i++)
+               if (gmin_subdevs[i].subdev == NULL)
+                       return &gmin_subdevs[i];
+       return NULL;
 }
 
 static int axp_regulator_set(struct device *dev, struct gmin_subdev *gs,
@@ -700,32 +815,24 @@ static int gmin_v1p8_ctrl(struct v4l2_subdev *subdev, int on)
 {
        struct gmin_subdev *gs = find_gmin_subdev(subdev);
        int ret;
-       struct device *dev;
-       struct i2c_client *client = v4l2_get_subdevdata(subdev);
        int value;
 
-       dev = &client->dev;
-
-       if (v1p8_gpio == V1P8_GPIO_UNSET) {
-               v1p8_gpio = gmin_get_var_int(dev, true,
-                                            "V1P8GPIO", V1P8_GPIO_NONE);
-               if (v1p8_gpio != V1P8_GPIO_NONE) {
-                       pr_info("atomisp_gmin_platform: 1.8v power on GPIO %d\n",
-                               v1p8_gpio);
-                       ret = gpio_request(v1p8_gpio, "camera_v1p8_en");
-                       if (!ret)
-                               ret = gpio_direction_output(v1p8_gpio, 0);
-                       if (ret)
-                               pr_err("V1P8 GPIO initialization failed\n");
-               }
+       if (gs->v1p8_gpio >= 0) {
+               pr_info("atomisp_gmin_platform: 1.8v power on GPIO %d\n",
+                       gs->v1p8_gpio);
+               ret = gpio_request(gs->v1p8_gpio, "camera_v1p8_en");
+               if (!ret)
+                       ret = gpio_direction_output(gs->v1p8_gpio, 0);
+               if (ret)
+                       pr_err("V1P8 GPIO initialization failed\n");
        }
 
        if (!gs || gs->v1p8_on == on)
                return 0;
        gs->v1p8_on = on;
 
-       if (v1p8_gpio >= 0)
-               gpio_set_value(v1p8_gpio, on);
+       if (gs->v1p8_gpio >= 0)
+               gpio_set_value(gs->v1p8_gpio, on);
 
        if (gs->v1p8_reg) {
                regulator_set_voltage(gs->v1p8_reg, 1800000, 1800000);
@@ -762,32 +869,24 @@ static int gmin_v2p8_ctrl(struct v4l2_subdev *subdev, int on)
 {
        struct gmin_subdev *gs = find_gmin_subdev(subdev);
        int ret;
-       struct device *dev;
-       struct i2c_client *client = v4l2_get_subdevdata(subdev);
        int value;
 
-       dev = &client->dev;
-
-       if (v2p8_gpio == V2P8_GPIO_UNSET) {
-               v2p8_gpio = gmin_get_var_int(dev, true,
-                                            "V2P8GPIO", V2P8_GPIO_NONE);
-               if (v2p8_gpio != V2P8_GPIO_NONE) {
-                       pr_info("atomisp_gmin_platform: 2.8v power on GPIO %d\n",
-                               v2p8_gpio);
-                       ret = gpio_request(v2p8_gpio, "camera_v2p8");
-                       if (!ret)
-                               ret = gpio_direction_output(v2p8_gpio, 0);
-                       if (ret)
-                               pr_err("V2P8 GPIO initialization failed\n");
-               }
+       if (gs->v2p8_gpio >= 0) {
+               pr_info("atomisp_gmin_platform: 2.8v power on GPIO %d\n",
+                       gs->v2p8_gpio);
+               ret = gpio_request(gs->v2p8_gpio, "camera_v2p8");
+               if (!ret)
+                       ret = gpio_direction_output(gs->v2p8_gpio, 0);
+               if (ret)
+                       pr_err("V2P8 GPIO initialization failed\n");
        }
 
        if (!gs || gs->v2p8_on == on)
                return 0;
        gs->v2p8_on = on;
 
-       if (v2p8_gpio >= 0)
-               gpio_set_value(v2p8_gpio, on);
+       if (gs->v2p8_gpio >= 0)
+               gpio_set_value(gs->v2p8_gpio, on);
 
        if (gs->v2p8_reg) {
                regulator_set_voltage(gs->v2p8_reg, 2900000, 2900000);
@@ -819,6 +918,37 @@ static int gmin_v2p8_ctrl(struct v4l2_subdev *subdev, int on)
        return -EINVAL;
 }
 
+static int gmin_acpi_pm_ctrl(struct v4l2_subdev *subdev, int on)
+{
+       int ret = 0;
+       struct gmin_subdev *gs = find_gmin_subdev(subdev);
+       struct i2c_client *client = v4l2_get_subdevdata(subdev);
+       struct acpi_device *adev = ACPI_COMPANION(&client->dev);
+
+       /* Use the ACPI power management to control it */
+       on = !!on;
+       if (gs->clock_on == on)
+               return 0;
+
+       dev_dbg(subdev->dev, "Setting power state to %s\n",
+               on ? "on" : "off");
+
+       if (on)
+               ret = acpi_device_set_power(adev,
+                                           ACPI_STATE_D0);
+       else
+               ret = acpi_device_set_power(adev,
+                                           ACPI_STATE_D3_COLD);
+
+       if (!ret)
+               gs->clock_on = on;
+       else
+               dev_err(subdev->dev, "Couldn't set power state to %s\n",
+                       on ? "on" : "off");
+
+       return ret;
+}
+
 static int gmin_flisclk_ctrl(struct v4l2_subdev *subdev, int on)
 {
        int ret = 0;
@@ -884,7 +1014,7 @@ static struct camera_vcm_control *gmin_get_vcm_ctrl(struct v4l2_subdev *subdev,
        return NULL;
 }
 
-static struct camera_sensor_platform_data gmin_plat = {
+static struct camera_sensor_platform_data pmic_gmin_plat = {
        .gpio0_ctrl = gmin_gpio0_ctrl,
        .gpio1_ctrl = gmin_gpio1_ctrl,
        .v1p8_ctrl = gmin_v1p8_ctrl,
@@ -895,17 +1025,36 @@ static struct camera_sensor_platform_data gmin_plat = {
        .get_vcm_ctrl = gmin_get_vcm_ctrl,
 };
 
+static struct camera_sensor_platform_data acpi_gmin_plat = {
+       .gpio0_ctrl = gmin_gpio0_ctrl,
+       .gpio1_ctrl = gmin_gpio1_ctrl,
+       .v1p8_ctrl = gmin_acpi_pm_ctrl,
+       .v2p8_ctrl = gmin_acpi_pm_ctrl,
+       .v1p2_ctrl = gmin_acpi_pm_ctrl,
+       .flisclk_ctrl = gmin_acpi_pm_ctrl,
+       .csi_cfg = gmin_csi_cfg,
+       .get_vcm_ctrl = gmin_get_vcm_ctrl,
+};
+
 struct camera_sensor_platform_data *gmin_camera_platform_data(
     struct v4l2_subdev *subdev,
     enum atomisp_input_format csi_format,
     enum atomisp_bayer_order csi_bayer)
 {
-       struct gmin_subdev *gs = find_gmin_subdev(subdev);
+       u8 pmic_i2c_addr = gmin_detect_pmic(subdev);
+       struct gmin_subdev *gs;
 
+       gs = find_free_gmin_subdev_slot();
+       gs->subdev = subdev;
        gs->csi_fmt = csi_format;
        gs->csi_bayer = csi_bayer;
+       gs->pwm_i2c_addr = pmic_i2c_addr;
 
-       return &gmin_plat;
+       gmin_subdev_add(gs);
+       if (gs->pmc_clk)
+               return &pmic_gmin_plat;
+       else
+               return &acpi_gmin_plat;
 }
 EXPORT_SYMBOL_GPL(gmin_camera_platform_data);
 
@@ -957,12 +1106,28 @@ static int gmin_get_config_dsm_var(struct device *dev,
        union acpi_object *obj, *cur = NULL;
        int i;
 
+       /*
+        * The data reported by "CamClk" seems to be either 0 or 1 at the
+        * _DSM table.
+        *
+        * At the ACPI tables we looked so far, this is not related to the
+        * actual clock source for the sensor, which is given by the
+        * _PR0 ACPI table. So, ignore it, as otherwise this will be
+        * set to a wrong value.
+        */
+       if (!strcmp(var, "CamClk"))
+               return -EINVAL;
+
        obj = acpi_evaluate_dsm(handle, &atomisp_dsm_guid, 0, 0, NULL);
        if (!obj) {
                dev_info_once(dev, "Didn't find ACPI _DSM table.\n");
                return -EINVAL;
        }
 
+       /* Return on unexpected object type */
+       if (obj->type != ACPI_TYPE_PACKAGE)
+               return -EINVAL;
+
 #if 0 /* Just for debugging purposes */
        for (i = 0; i < obj->package.count; i++) {
                union acpi_object *cur = &obj->package.elements[i];
@@ -1155,10 +1320,10 @@ EXPORT_SYMBOL_GPL(camera_sensor_csi);
  * trying.  The driver itself does direct calls to the PUNIT to manage
  * ISP power.
  */
-static void isp_pm_cap_fixup(struct pci_dev *dev)
+static void isp_pm_cap_fixup(struct pci_dev *pdev)
 {
-       dev_info(&dev->dev, "Disabling PCI power management on camera ISP\n");
-       dev->pm_cap = 0;
+       dev_info(&pdev->dev, "Disabling PCI power management on camera ISP\n");
+       pdev->pm_cap = 0;
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0f38, isp_pm_cap_fixup);
 
index ff3becd..c01db10 100644 (file)
@@ -216,12 +216,12 @@ struct atomisp_sw_contex {
  * ci device struct
  */
 struct atomisp_device {
-       struct pci_dev *pdev;
        struct device *dev;
        struct v4l2_device v4l2_dev;
        struct media_device media_dev;
        struct atomisp_platform_data *pdata;
        void *mmu_l1_base;
+       void __iomem *base;
        const struct firmware *firmware;
 
        struct pm_qos_request pm_qos;
index 9404a67..f8d616f 100644 (file)
@@ -549,8 +549,7 @@ static int atomisp_querycap(struct file *file, void *fh,
 
        strscpy(cap->driver, DRIVER, sizeof(cap->driver));
        strscpy(cap->card, CARD, sizeof(cap->card));
-       snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
-                pci_name(isp->pdev));
+       snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", dev_name(isp->dev));
 
        return 0;
 }
@@ -1635,6 +1634,7 @@ static int atomisp_streamon(struct file *file, void *fh,
        struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
        struct atomisp_sub_device *asd = pipe->asd;
        struct atomisp_device *isp = video_get_drvdata(vdev);
+       struct pci_dev *pdev = to_pci_dev(isp->dev);
        enum ia_css_pipe_id css_pipe_id;
        unsigned int sensor_start_stream;
        unsigned int wdt_duration = ATOMISP_ISP_TIMEOUT_DURATION;
@@ -1844,9 +1844,8 @@ start_sensor:
        /* Enable the CSI interface on ANN B0/K0 */
        if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 <<
                                            ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0)) {
-               pci_write_config_word(isp->pdev, MRFLD_PCI_CSI_CONTROL,
-                                     isp->saved_regs.csi_control |
-                                     MRFLD_PCI_CSI_CONTROL_CSI_READY);
+               pci_write_config_word(pdev, MRFLD_PCI_CSI_CONTROL,
+                                     isp->saved_regs.csi_control | MRFLD_PCI_CSI_CONTROL_CSI_READY);
        }
 
        /* stream on the sensor */
@@ -1891,6 +1890,7 @@ int __atomisp_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
 {
        struct video_device *vdev = video_devdata(file);
        struct atomisp_device *isp = video_get_drvdata(vdev);
+       struct pci_dev *pdev = to_pci_dev(isp->dev);
        struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
        struct atomisp_sub_device *asd = pipe->asd;
        struct atomisp_video_pipe *capture_pipe = NULL;
@@ -2076,9 +2076,8 @@ stopsensor:
        /* Disable the CSI interface on ANN B0/K0 */
        if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 <<
                                            ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0)) {
-               pci_write_config_word(isp->pdev, MRFLD_PCI_CSI_CONTROL,
-                                     isp->saved_regs.csi_control &
-                                     ~MRFLD_PCI_CSI_CONTROL_CSI_READY);
+               pci_write_config_word(pdev, MRFLD_PCI_CSI_CONTROL,
+                                     isp->saved_regs.csi_control & ~MRFLD_PCI_CSI_CONTROL_CSI_READY);
        }
 
        if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_LOW, false))
@@ -2111,8 +2110,8 @@ stopsensor:
                }
 
                /* disable  PUNIT/ISP acknowlede/handshake - SRSE=3 */
-               pci_write_config_dword(isp->pdev, PCI_I_CONTROL, isp->saved_regs.i_control |
-                                      MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK);
+               pci_write_config_dword(pdev, PCI_I_CONTROL,
+                                      isp->saved_regs.i_control | MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK);
                dev_err(isp->dev, "atomisp_reset");
                atomisp_reset(isp);
                for (i = 0; i < isp->num_of_streams; i++) {
index d36809a..a000a1e 100644 (file)
@@ -127,8 +127,6 @@ MODULE_PARM_DESC(pad_h, "extra data for ISP processing");
 
 struct device *atomisp_dev;
 
-void __iomem *atomisp_io_base;
-
 static const struct atomisp_freq_scaling_rule dfs_rules_merr[] = {
        {
                .width = ISP_FREQ_RULE_ANY,
@@ -512,30 +510,27 @@ void atomisp_acc_unregister(struct atomisp_acc_pipe *video)
 
 static int atomisp_save_iunit_reg(struct atomisp_device *isp)
 {
-       struct pci_dev *dev = isp->pdev;
+       struct pci_dev *pdev = to_pci_dev(isp->dev);
 
        dev_dbg(isp->dev, "%s\n", __func__);
 
-       pci_read_config_word(dev, PCI_COMMAND, &isp->saved_regs.pcicmdsts);
+       pci_read_config_word(pdev, PCI_COMMAND, &isp->saved_regs.pcicmdsts);
        /* isp->saved_regs.ispmmadr is set from the atomisp_pci_probe() */
-       pci_read_config_dword(dev, PCI_MSI_CAPID, &isp->saved_regs.msicap);
-       pci_read_config_dword(dev, PCI_MSI_ADDR, &isp->saved_regs.msi_addr);
-       pci_read_config_word(dev, PCI_MSI_DATA,  &isp->saved_regs.msi_data);
-       pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &isp->saved_regs.intr);
-       pci_read_config_dword(dev, PCI_INTERRUPT_CTRL,
-                             &isp->saved_regs.interrupt_control);
-
-       pci_read_config_dword(dev, MRFLD_PCI_PMCS,
-                             &isp->saved_regs.pmcs);
+       pci_read_config_dword(pdev, PCI_MSI_CAPID, &isp->saved_regs.msicap);
+       pci_read_config_dword(pdev, PCI_MSI_ADDR, &isp->saved_regs.msi_addr);
+       pci_read_config_word(pdev, PCI_MSI_DATA,  &isp->saved_regs.msi_data);
+       pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &isp->saved_regs.intr);
+       pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &isp->saved_regs.interrupt_control);
+
+       pci_read_config_dword(pdev, MRFLD_PCI_PMCS, &isp->saved_regs.pmcs);
        /* Ensure read/write combining is enabled. */
-       pci_read_config_dword(dev, PCI_I_CONTROL,
-                             &isp->saved_regs.i_control);
+       pci_read_config_dword(pdev, PCI_I_CONTROL, &isp->saved_regs.i_control);
        isp->saved_regs.i_control |=
            MRFLD_PCI_I_CONTROL_ENABLE_READ_COMBINING |
            MRFLD_PCI_I_CONTROL_ENABLE_WRITE_COMBINING;
-       pci_read_config_dword(dev, MRFLD_PCI_CSI_ACCESS_CTRL_VIOL,
+       pci_read_config_dword(pdev, MRFLD_PCI_CSI_ACCESS_CTRL_VIOL,
                              &isp->saved_regs.csi_access_viol);
-       pci_read_config_dword(dev, MRFLD_PCI_CSI_RCOMP_CONTROL,
+       pci_read_config_dword(pdev, MRFLD_PCI_CSI_RCOMP_CONTROL,
                              &isp->saved_regs.csi_rcomp_config);
        /*
         * Hardware bugs require setting CSI_HS_OVR_CLK_GATE_ON_UPDATE.
@@ -545,65 +540,58 @@ static int atomisp_save_iunit_reg(struct atomisp_device *isp)
         * is missed, and IUNIT can hang.
         * For both issues, setting this bit is a workaround.
         */
-       isp->saved_regs.csi_rcomp_config |=
-           MRFLD_PCI_CSI_HS_OVR_CLK_GATE_ON_UPDATE;
-       pci_read_config_dword(dev, MRFLD_PCI_CSI_AFE_TRIM_CONTROL,
+       isp->saved_regs.csi_rcomp_config |= MRFLD_PCI_CSI_HS_OVR_CLK_GATE_ON_UPDATE;
+       pci_read_config_dword(pdev, MRFLD_PCI_CSI_AFE_TRIM_CONTROL,
                              &isp->saved_regs.csi_afe_dly);
-       pci_read_config_dword(dev, MRFLD_PCI_CSI_CONTROL,
+       pci_read_config_dword(pdev, MRFLD_PCI_CSI_CONTROL,
                              &isp->saved_regs.csi_control);
        if (isp->media_dev.hw_revision >=
            (ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT))
-               isp->saved_regs.csi_control |=
-                   MRFLD_PCI_CSI_CONTROL_PARPATHEN;
+               isp->saved_regs.csi_control |= MRFLD_PCI_CSI_CONTROL_PARPATHEN;
        /*
         * On CHT CSI_READY bit should be enabled before stream on
         */
        if (IS_CHT && (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 <<
                       ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0)))
-               isp->saved_regs.csi_control |=
-                   MRFLD_PCI_CSI_CONTROL_CSI_READY;
-       pci_read_config_dword(dev, MRFLD_PCI_CSI_AFE_RCOMP_CONTROL,
+               isp->saved_regs.csi_control |= MRFLD_PCI_CSI_CONTROL_CSI_READY;
+       pci_read_config_dword(pdev, MRFLD_PCI_CSI_AFE_RCOMP_CONTROL,
                              &isp->saved_regs.csi_afe_rcomp_config);
-       pci_read_config_dword(dev, MRFLD_PCI_CSI_AFE_HS_CONTROL,
+       pci_read_config_dword(pdev, MRFLD_PCI_CSI_AFE_HS_CONTROL,
                              &isp->saved_regs.csi_afe_hs_control);
-       pci_read_config_dword(dev, MRFLD_PCI_CSI_DEADLINE_CONTROL,
+       pci_read_config_dword(pdev, MRFLD_PCI_CSI_DEADLINE_CONTROL,
                              &isp->saved_regs.csi_deadline_control);
        return 0;
 }
 
 static int __maybe_unused atomisp_restore_iunit_reg(struct atomisp_device *isp)
 {
-       struct pci_dev *dev = isp->pdev;
+       struct pci_dev *pdev = to_pci_dev(isp->dev);
 
        dev_dbg(isp->dev, "%s\n", __func__);
 
-       pci_write_config_word(dev, PCI_COMMAND, isp->saved_regs.pcicmdsts);
-       pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
-                              isp->saved_regs.ispmmadr);
-       pci_write_config_dword(dev, PCI_MSI_CAPID, isp->saved_regs.msicap);
-       pci_write_config_dword(dev, PCI_MSI_ADDR, isp->saved_regs.msi_addr);
-       pci_write_config_word(dev, PCI_MSI_DATA, isp->saved_regs.msi_data);
-       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, isp->saved_regs.intr);
-       pci_write_config_dword(dev, PCI_INTERRUPT_CTRL,
-                              isp->saved_regs.interrupt_control);
-       pci_write_config_dword(dev, PCI_I_CONTROL,
-                              isp->saved_regs.i_control);
-
-       pci_write_config_dword(dev, MRFLD_PCI_PMCS,
-                              isp->saved_regs.pmcs);
-       pci_write_config_dword(dev, MRFLD_PCI_CSI_ACCESS_CTRL_VIOL,
+       pci_write_config_word(pdev, PCI_COMMAND, isp->saved_regs.pcicmdsts);
+       pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, isp->saved_regs.ispmmadr);
+       pci_write_config_dword(pdev, PCI_MSI_CAPID, isp->saved_regs.msicap);
+       pci_write_config_dword(pdev, PCI_MSI_ADDR, isp->saved_regs.msi_addr);
+       pci_write_config_word(pdev, PCI_MSI_DATA, isp->saved_regs.msi_data);
+       pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, isp->saved_regs.intr);
+       pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, isp->saved_regs.interrupt_control);
+       pci_write_config_dword(pdev, PCI_I_CONTROL, isp->saved_regs.i_control);
+
+       pci_write_config_dword(pdev, MRFLD_PCI_PMCS, isp->saved_regs.pmcs);
+       pci_write_config_dword(pdev, MRFLD_PCI_CSI_ACCESS_CTRL_VIOL,
                               isp->saved_regs.csi_access_viol);
-       pci_write_config_dword(dev, MRFLD_PCI_CSI_RCOMP_CONTROL,
+       pci_write_config_dword(pdev, MRFLD_PCI_CSI_RCOMP_CONTROL,
                               isp->saved_regs.csi_rcomp_config);
-       pci_write_config_dword(dev, MRFLD_PCI_CSI_AFE_TRIM_CONTROL,
+       pci_write_config_dword(pdev, MRFLD_PCI_CSI_AFE_TRIM_CONTROL,
                               isp->saved_regs.csi_afe_dly);
-       pci_write_config_dword(dev, MRFLD_PCI_CSI_CONTROL,
+       pci_write_config_dword(pdev, MRFLD_PCI_CSI_CONTROL,
                               isp->saved_regs.csi_control);
-       pci_write_config_dword(dev, MRFLD_PCI_CSI_AFE_RCOMP_CONTROL,
+       pci_write_config_dword(pdev, MRFLD_PCI_CSI_AFE_RCOMP_CONTROL,
                               isp->saved_regs.csi_afe_rcomp_config);
-       pci_write_config_dword(dev, MRFLD_PCI_CSI_AFE_HS_CONTROL,
+       pci_write_config_dword(pdev, MRFLD_PCI_CSI_AFE_HS_CONTROL,
                               isp->saved_regs.csi_afe_hs_control);
-       pci_write_config_dword(dev, MRFLD_PCI_CSI_DEADLINE_CONTROL,
+       pci_write_config_dword(pdev, MRFLD_PCI_CSI_DEADLINE_CONTROL,
                               isp->saved_regs.csi_deadline_control);
 
        /*
@@ -619,7 +607,7 @@ static int __maybe_unused atomisp_restore_iunit_reg(struct atomisp_device *isp)
 
 static int atomisp_mrfld_pre_power_down(struct atomisp_device *isp)
 {
-       struct pci_dev *dev = isp->pdev;
+       struct pci_dev *pdev = to_pci_dev(isp->dev);
        u32 irq;
        unsigned long flags;
 
@@ -635,11 +623,11 @@ static int atomisp_mrfld_pre_power_down(struct atomisp_device *isp)
         * So, here we need to check if there is any pending
         * IRQ, if so, waiting for it to be served
         */
-       pci_read_config_dword(dev, PCI_INTERRUPT_CTRL, &irq);
+       pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq);
        irq = irq & 1 << INTR_IIR;
-       pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, irq);
+       pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, irq);
 
-       pci_read_config_dword(dev, PCI_INTERRUPT_CTRL, &irq);
+       pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq);
        if (!(irq & (1 << INTR_IIR)))
                goto done;
 
@@ -652,11 +640,11 @@ static int atomisp_mrfld_pre_power_down(struct atomisp_device *isp)
                spin_unlock_irqrestore(&isp->lock, flags);
                return -EAGAIN;
        } else {
-               pci_read_config_dword(dev, PCI_INTERRUPT_CTRL, &irq);
+               pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq);
                irq = irq & 1 << INTR_IIR;
-               pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, irq);
+               pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, irq);
 
-               pci_read_config_dword(dev, PCI_INTERRUPT_CTRL, &irq);
+               pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq);
                if (!(irq & (1 << INTR_IIR))) {
                        atomisp_css2_hw_store_32(MRFLD_INTR_ENABLE_REG, 0x0);
                        goto done;
@@ -675,11 +663,11 @@ done:
        * to IIR. It could block subsequent interrupt messages.
        * HW sighting:4568410.
        */
-       pci_read_config_dword(dev, PCI_INTERRUPT_CTRL, &irq);
+       pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq);
        irq &= ~(1 << INTR_IER);
-       pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, irq);
+       pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, irq);
 
-       atomisp_msi_irq_uninit(isp, dev);
+       atomisp_msi_irq_uninit(isp);
        atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_LOW, true);
        spin_unlock_irqrestore(&isp->lock, flags);
 
@@ -755,7 +743,7 @@ static int atomisp_mrfld_power(struct atomisp_device *isp, bool enable)
 
                /* Wait until ISPSSPM0 bit[25:24] shows the right value */
                iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, MRFLD_ISPSSPM0, &tmp);
-               tmp = (tmp & MRFLD_ISPSSPM0_ISPSSC_MASK) >> MRFLD_ISPSSPM0_ISPSSS_OFFSET;
+               tmp = (tmp >> MRFLD_ISPSSPM0_ISPSSS_OFFSET) & MRFLD_ISPSSPM0_ISPSSC_MASK;
                if (tmp == val) {
                        trace_ipu_cstate(enable);
                        return 0;
@@ -778,15 +766,13 @@ static int atomisp_mrfld_power(struct atomisp_device *isp, bool enable)
 /* Workaround for pmu_nc_set_power_state not ready in MRFLD */
 int atomisp_mrfld_power_down(struct atomisp_device *isp)
 {
-// FIXME: at least with ISP2401, enabling this code causes the driver to break
-       return 0 && atomisp_mrfld_power(isp, false);
+       return atomisp_mrfld_power(isp, false);
 }
 
 /* Workaround for pmu_nc_set_power_state not ready in MRFLD */
 int atomisp_mrfld_power_up(struct atomisp_device *isp)
 {
-// FIXME: at least with ISP2401, enabling this code causes the driver to break
-       return 0 && atomisp_mrfld_power(isp, true);
+       return atomisp_mrfld_power(isp, true);
 }
 
 int atomisp_runtime_suspend(struct device *dev)
@@ -902,6 +888,7 @@ static int __maybe_unused atomisp_resume(struct device *dev)
 
 int atomisp_csi_lane_config(struct atomisp_device *isp)
 {
+       struct pci_dev *pdev = to_pci_dev(isp->dev);
        static const struct {
                u8 code;
                u8 lanes[MRFLD_PORT_NUM];
@@ -1003,7 +990,7 @@ int atomisp_csi_lane_config(struct atomisp_device *isp)
                return -EINVAL;
        }
 
-       pci_read_config_dword(isp->pdev, MRFLD_PCI_CSI_CONTROL, &csi_control);
+       pci_read_config_dword(pdev, MRFLD_PCI_CSI_CONTROL, &csi_control);
        csi_control &= ~port_config_mask;
        csi_control |= (portconfigs[i].code << MRFLD_PORT_CONFIGCODE_SHIFT)
                       | (portconfigs[i].lanes[0] ? 0 : (1 << MRFLD_PORT1_ENABLE_SHIFT))
@@ -1013,7 +1000,7 @@ int atomisp_csi_lane_config(struct atomisp_device *isp)
                       | (((1 << portconfigs[i].lanes[1]) - 1) << MRFLD_PORT2_LANES_SHIFT)
                       | (((1 << portconfigs[i].lanes[2]) - 1) << port3_lanes_shift);
 
-       pci_write_config_dword(isp->pdev, MRFLD_PCI_CSI_CONTROL, csi_control);
+       pci_write_config_dword(pdev, MRFLD_PCI_CSI_CONTROL, csi_control);
 
        dev_dbg(isp->dev,
                "%s: the portconfig is %d-%d-%d, CSI_CONTROL is 0x%08X\n",
@@ -1440,8 +1427,7 @@ atomisp_load_firmware(struct atomisp_device *isp)
  * Check for flags the driver was compiled with against the PCI
  * device. Always returns true on other than ISP 2400.
  */
-static bool is_valid_device(struct pci_dev *dev,
-                           const struct pci_device_id *id)
+static bool is_valid_device(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        unsigned int a0_max_id = 0;
        const char *name;
@@ -1465,14 +1451,14 @@ static bool is_valid_device(struct pci_dev *dev,
                name = "Cherrytrail";
                break;
        default:
-               dev_err(&dev->dev, "%s: unknown device ID %x04:%x04\n",
+               dev_err(&pdev->dev, "%s: unknown device ID %x04:%x04\n",
                        product, id->vendor, id->device);
                return false;
        }
 
-       if (dev->revision <= ATOMISP_PCI_REV_BYT_A0_MAX) {
-               dev_err(&dev->dev, "%s revision %d is not unsupported\n",
-                       name, dev->revision);
+       if (pdev->revision <= ATOMISP_PCI_REV_BYT_A0_MAX) {
+               dev_err(&pdev->dev, "%s revision %d is not unsupported\n",
+                       name, pdev->revision);
                return false;
        }
 
@@ -1483,22 +1469,20 @@ static bool is_valid_device(struct pci_dev *dev,
 
 #if defined(ISP2400)
        if (IS_ISP2401) {
-               dev_err(&dev->dev, "Support for %s (ISP2401) was disabled at compile time\n",
+               dev_err(&pdev->dev, "Support for %s (ISP2401) was disabled at compile time\n",
                        name);
                return false;
        }
 #else
        if (!IS_ISP2401) {
-               dev_err(&dev->dev, "Support for %s (ISP2400) was disabled at compile time\n",
+               dev_err(&pdev->dev, "Support for %s (ISP2400) was disabled at compile time\n",
                        name);
                return false;
        }
 #endif
 
-       dev_info(&dev->dev, "Detected %s version %d (ISP240%c) on %s\n",
-               name, dev->revision,
-               IS_ISP2401 ? '1' : '0',
-               product);
+       dev_info(&pdev->dev, "Detected %s version %d (ISP240%c) on %s\n",
+                name, pdev->revision, IS_ISP2401 ? '1' : '0', product);
 
        return true;
 }
@@ -1538,66 +1522,60 @@ alloc_fail:
 
 #define ATOM_ISP_PCI_BAR       0
 
-static int atomisp_pci_probe(struct pci_dev *dev,
-                            const struct pci_device_id *id)
+static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        const struct atomisp_platform_data *pdata;
        struct atomisp_device *isp;
        unsigned int start;
-       void __iomem *base;
        int err, val;
        u32 irq;
 
-       if (!is_valid_device(dev, id))
+       if (!is_valid_device(pdev, id))
                return -ENODEV;
 
        /* Pointer to struct device. */
-       atomisp_dev = &dev->dev;
+       atomisp_dev = &pdev->dev;
 
        pdata = atomisp_get_platform_data();
        if (!pdata)
-               dev_warn(&dev->dev, "no platform data available\n");
+               dev_warn(&pdev->dev, "no platform data available\n");
 
-       err = pcim_enable_device(dev);
+       err = pcim_enable_device(pdev);
        if (err) {
-               dev_err(&dev->dev, "Failed to enable CI ISP device (%d)\n",
-                       err);
+               dev_err(&pdev->dev, "Failed to enable CI ISP device (%d)\n", err);
                return err;
        }
 
-       start = pci_resource_start(dev, ATOM_ISP_PCI_BAR);
-       dev_dbg(&dev->dev, "start: 0x%x\n", start);
+       start = pci_resource_start(pdev, ATOM_ISP_PCI_BAR);
+       dev_dbg(&pdev->dev, "start: 0x%x\n", start);
 
-       err = pcim_iomap_regions(dev, 1 << ATOM_ISP_PCI_BAR, pci_name(dev));
+       err = pcim_iomap_regions(pdev, 1 << ATOM_ISP_PCI_BAR, pci_name(pdev));
        if (err) {
-               dev_err(&dev->dev, "Failed to I/O memory remapping (%d)\n",
-                       err);
+               dev_err(&pdev->dev, "Failed to I/O memory remapping (%d)\n", err);
                goto ioremap_fail;
        }
 
-       base = pcim_iomap_table(dev)[ATOM_ISP_PCI_BAR];
-       dev_dbg(&dev->dev, "base: %p\n", base);
-
-       atomisp_io_base = base;
-
-       dev_dbg(&dev->dev, "atomisp_io_base: %p\n", atomisp_io_base);
-
-       isp = devm_kzalloc(&dev->dev, sizeof(struct atomisp_device), GFP_KERNEL);
+       isp = devm_kzalloc(&pdev->dev, sizeof(*isp), GFP_KERNEL);
        if (!isp) {
                err = -ENOMEM;
                goto atomisp_dev_alloc_fail;
        }
-       isp->pdev = dev;
-       isp->dev = &dev->dev;
+
+       isp->dev = &pdev->dev;
+       isp->base = pcim_iomap_table(pdev)[ATOM_ISP_PCI_BAR];
        isp->sw_contex.power_state = ATOM_ISP_POWER_UP;
        isp->saved_regs.ispmmadr = start;
 
+       dev_dbg(&pdev->dev, "atomisp mmio base: %p\n", isp->base);
+
        rt_mutex_init(&isp->mutex);
        mutex_init(&isp->streamoff_mutex);
        spin_lock_init(&isp->lock);
 
        /* This is not a true PCI device on SoC, so the delay is not needed. */
-       isp->pdev->d3_delay = 0;
+       pdev->d3_delay = 0;
+
+       pci_set_drvdata(pdev, isp);
 
        switch (id->device & ATOMISP_PCI_DEVICE_SOC_MASK) {
        case ATOMISP_PCI_DEVICE_SOC_MRFLD:
@@ -1648,15 +1626,14 @@ static int atomisp_pci_probe(struct pci_dev *dev,
                 * have specs yet for exactly how it varies.  Default to
                 * BYT-CR but let provisioning set it via EFI variable
                 */
-               isp->hpll_freq = gmin_get_var_int(&dev->dev, false, "HpllFreq",
-                                                 HPLL_FREQ_2000MHZ);
+               isp->hpll_freq = gmin_get_var_int(&pdev->dev, false, "HpllFreq", HPLL_FREQ_2000MHZ);
 
                /*
                 * for BYT/CHT we are put isp into D3cold to avoid pci registers access
                 * in power off. Set d3cold_delay to 0 since default 100ms is not
                 * necessary.
                 */
-               isp->pdev->d3cold_delay = 0;
+               pdev->d3cold_delay = 0;
                break;
        case ATOMISP_PCI_DEVICE_SOC_ANN:
                isp->media_dev.hw_revision = (
@@ -1666,7 +1643,7 @@ static int atomisp_pci_probe(struct pci_dev *dev,
                                                 ATOMISP_HW_REVISION_ISP2401_LEGACY
 #endif
                                                 << ATOMISP_HW_REVISION_SHIFT);
-               isp->media_dev.hw_revision |= isp->pdev->revision < 2 ?
+               isp->media_dev.hw_revision |= pdev->revision < 2 ?
                                              ATOMISP_HW_STEPPING_A0 : ATOMISP_HW_STEPPING_B0;
                isp->dfs = &dfs_config_merr;
                isp->hpll_freq = HPLL_FREQ_1600MHZ;
@@ -1679,13 +1656,13 @@ static int atomisp_pci_probe(struct pci_dev *dev,
                                                 ATOMISP_HW_REVISION_ISP2401_LEGACY
 #endif
                                                 << ATOMISP_HW_REVISION_SHIFT);
-               isp->media_dev.hw_revision |= isp->pdev->revision < 2 ?
+               isp->media_dev.hw_revision |= pdev->revision < 2 ?
                                              ATOMISP_HW_STEPPING_A0 : ATOMISP_HW_STEPPING_B0;
 
                isp->dfs = &dfs_config_cht;
-               isp->pdev->d3cold_delay = 0;
+               pdev->d3cold_delay = 0;
 
-               iosf_mbi_read(CCK_PORT, MBI_REG_READ, CCK_FUSE_REG_0, &val);
+               iosf_mbi_read(BT_MBI_UNIT_CCK, MBI_REG_READ, CCK_FUSE_REG_0, &val);
                switch (val & CCK_FUSE_HPLL_FREQ_MASK) {
                case 0x00:
                        isp->hpll_freq = HPLL_FREQ_800MHZ;
@@ -1698,18 +1675,16 @@ static int atomisp_pci_probe(struct pci_dev *dev,
                        break;
                default:
                        isp->hpll_freq = HPLL_FREQ_1600MHZ;
-                       dev_warn(isp->dev,
-                                "read HPLL from cck failed. Default to 1600 MHz.\n");
+                       dev_warn(&pdev->dev, "read HPLL from cck failed. Default to 1600 MHz.\n");
                }
                break;
        default:
-               dev_err(&dev->dev, "un-supported IUNIT device\n");
+               dev_err(&pdev->dev, "un-supported IUNIT device\n");
                err = -ENODEV;
                goto atomisp_dev_alloc_fail;
        }
 
-       dev_info(&dev->dev, "ISP HPLL frequency base = %d MHz\n",
-                isp->hpll_freq);
+       dev_info(&pdev->dev, "ISP HPLL frequency base = %d MHz\n", isp->hpll_freq);
 
        isp->max_isr_latency = ATOMISP_MAX_ISR_LATENCY;
 
@@ -1718,30 +1693,28 @@ static int atomisp_pci_probe(struct pci_dev *dev,
                isp->firmware = atomisp_load_firmware(isp);
                if (!isp->firmware) {
                        err = -ENOENT;
-                       dev_dbg(&dev->dev, "Firmware load failed\n");
+                       dev_dbg(&pdev->dev, "Firmware load failed\n");
                        goto load_fw_fail;
                }
 
-               err = sh_css_check_firmware_version(isp->dev,
-                                                   isp->firmware->data);
+               err = sh_css_check_firmware_version(isp->dev, isp->firmware->data);
                if (err) {
-                       dev_dbg(&dev->dev, "Firmware version check failed\n");
+                       dev_dbg(&pdev->dev, "Firmware version check failed\n");
                        goto fw_validation_fail;
                }
        } else {
-               dev_info(&dev->dev, "Firmware load will be deferred\n");
+               dev_info(&pdev->dev, "Firmware load will be deferred\n");
        }
 
-       pci_set_master(dev);
-       pci_set_drvdata(dev, isp);
+       pci_set_master(pdev);
 
-       err = pci_enable_msi(dev);
+       err = pci_enable_msi(pdev);
        if (err) {
-               dev_err(&dev->dev, "Failed to enable msi (%d)\n", err);
+               dev_err(&pdev->dev, "Failed to enable msi (%d)\n", err);
                goto enable_msi_fail;
        }
 
-       atomisp_msi_irq_init(isp, dev);
+       atomisp_msi_irq_init(isp);
 
        cpu_latency_qos_add_request(&isp->pm_qos, PM_QOS_DEFAULT_VALUE);
 
@@ -1762,8 +1735,7 @@ static int atomisp_pci_probe(struct pci_dev *dev,
                 * Workaround for imbalance data eye issue which is observed
                 * on TNG B0.
                 */
-               pci_read_config_dword(dev, MRFLD_PCI_CSI_AFE_TRIM_CONTROL,
-                                     &csi_afe_trim);
+               pci_read_config_dword(pdev, MRFLD_PCI_CSI_AFE_TRIM_CONTROL, &csi_afe_trim);
                csi_afe_trim &= ~((MRFLD_PCI_CSI_HSRXCLKTRIM_MASK <<
                                   MRFLD_PCI_CSI1_HSRXCLKTRIM_SHIFT) |
                                  (MRFLD_PCI_CSI_HSRXCLKTRIM_MASK <<
@@ -1776,20 +1748,18 @@ static int atomisp_pci_probe(struct pci_dev *dev,
                                 MRFLD_PCI_CSI2_HSRXCLKTRIM_SHIFT) |
                                (MRFLD_PCI_CSI3_HSRXCLKTRIM <<
                                 MRFLD_PCI_CSI3_HSRXCLKTRIM_SHIFT);
-               pci_write_config_dword(dev, MRFLD_PCI_CSI_AFE_TRIM_CONTROL,
-                                      csi_afe_trim);
+               pci_write_config_dword(pdev, MRFLD_PCI_CSI_AFE_TRIM_CONTROL, csi_afe_trim);
        }
 
        err = atomisp_initialize_modules(isp);
        if (err < 0) {
-               dev_err(&dev->dev, "atomisp_initialize_modules (%d)\n", err);
+               dev_err(&pdev->dev, "atomisp_initialize_modules (%d)\n", err);
                goto initialize_modules_fail;
        }
 
        err = atomisp_register_entities(isp);
        if (err < 0) {
-               dev_err(&dev->dev, "atomisp_register_entities failed (%d)\n",
-                       err);
+               dev_err(&pdev->dev, "atomisp_register_entities failed (%d)\n", err);
                goto register_entities_fail;
        }
        err = atomisp_create_pads_links(isp);
@@ -1802,24 +1772,24 @@ static int atomisp_pci_probe(struct pci_dev *dev,
        /* save the iunit context only once after all the values are init'ed. */
        atomisp_save_iunit_reg(isp);
 
-       pm_runtime_put_noidle(&dev->dev);
-       pm_runtime_allow(&dev->dev);
+       pm_runtime_put_noidle(&pdev->dev);
+       pm_runtime_allow(&pdev->dev);
 
        hmm_init_mem_stat(repool_pgnr, dypool_enable, dypool_pgnr);
        err = hmm_pool_register(repool_pgnr, HMM_POOL_TYPE_RESERVED);
        if (err) {
-               dev_err(&dev->dev, "Failed to register reserved memory pool.\n");
+               dev_err(&pdev->dev, "Failed to register reserved memory pool.\n");
                goto hmm_pool_fail;
        }
 
        /* Init ISP memory management */
        hmm_init();
 
-       err = devm_request_threaded_irq(&dev->dev, dev->irq,
+       err = devm_request_threaded_irq(&pdev->dev, pdev->irq,
                                        atomisp_isr, atomisp_isr_thread,
                                        IRQF_SHARED, "isp_irq", isp);
        if (err) {
-               dev_err(&dev->dev, "Failed to request irq (%d)\n", err);
+               dev_err(&pdev->dev, "Failed to request irq (%d)\n", err);
                goto request_irq_fail;
        }
 
@@ -1827,23 +1797,23 @@ static int atomisp_pci_probe(struct pci_dev *dev,
        if (!defer_fw_load) {
                err = atomisp_css_load_firmware(isp);
                if (err) {
-                       dev_err(&dev->dev, "Failed to init css.\n");
+                       dev_err(&pdev->dev, "Failed to init css.\n");
                        goto css_init_fail;
                }
        } else {
-               dev_dbg(&dev->dev, "Skip css init.\n");
+               dev_dbg(&pdev->dev, "Skip css init.\n");
        }
        /* Clear FW image from memory */
        release_firmware(isp->firmware);
        isp->firmware = NULL;
        isp->css_env.isp_css_fw.data = NULL;
 
-       atomisp_drvfs_init(&dev->driver->driver, isp);
+       atomisp_drvfs_init(isp);
 
        return 0;
 
 css_init_fail:
-       devm_free_irq(&dev->dev, dev->irq, isp);
+       devm_free_irq(&pdev->dev, pdev->irq, isp);
 request_irq_fail:
        hmm_cleanup();
        hmm_pool_unregister(HMM_POOL_TYPE_RESERVED);
@@ -1856,8 +1826,8 @@ register_entities_fail:
        atomisp_uninitialize_modules(isp);
 initialize_modules_fail:
        cpu_latency_qos_remove_request(&isp->pm_qos);
-       atomisp_msi_irq_uninit(isp, dev);
-       pci_disable_msi(dev);
+       atomisp_msi_irq_uninit(isp);
+       pci_disable_msi(pdev);
 enable_msi_fail:
 fw_validation_fail:
        release_firmware(isp->firmware);
@@ -1869,35 +1839,34 @@ load_fw_fail:
         * The following lines have been copied from atomisp suspend path
         */
 
-       pci_read_config_dword(dev, PCI_INTERRUPT_CTRL, &irq);
+       pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq);
        irq = irq & 1 << INTR_IIR;
-       pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, irq);
+       pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, irq);
 
-       pci_read_config_dword(dev, PCI_INTERRUPT_CTRL, &irq);
+       pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq);
        irq &= ~(1 << INTR_IER);
-       pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, irq);
+       pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, irq);
 
-       atomisp_msi_irq_uninit(isp, dev);
+       atomisp_msi_irq_uninit(isp);
 
        atomisp_ospm_dphy_down(isp);
 
        /* Address later when we worry about the ...field chips */
        if (IS_ENABLED(CONFIG_PM) && atomisp_mrfld_power_down(isp))
-               dev_err(&dev->dev, "Failed to switch off ISP\n");
+               dev_err(&pdev->dev, "Failed to switch off ISP\n");
 
 atomisp_dev_alloc_fail:
-       pcim_iounmap_regions(dev, 1 << ATOM_ISP_PCI_BAR);
+       pcim_iounmap_regions(pdev, 1 << ATOM_ISP_PCI_BAR);
 
 ioremap_fail:
        return err;
 }
 
-static void atomisp_pci_remove(struct pci_dev *dev)
+static void atomisp_pci_remove(struct pci_dev *pdev)
 {
-       struct atomisp_device *isp = (struct atomisp_device *)
-                                    pci_get_drvdata(dev);
+       struct atomisp_device *isp = pci_get_drvdata(pdev);
 
-       dev_info(&dev->dev, "Removing atomisp driver\n");
+       dev_info(&pdev->dev, "Removing atomisp driver\n");
 
        atomisp_drvfs_exit();
 
@@ -1906,11 +1875,11 @@ static void atomisp_pci_remove(struct pci_dev *dev)
        ia_css_unload_firmware();
        hmm_cleanup();
 
-       pm_runtime_forbid(&dev->dev);
-       pm_runtime_get_noresume(&dev->dev);
+       pm_runtime_forbid(&pdev->dev);
+       pm_runtime_get_noresume(&pdev->dev);
        cpu_latency_qos_remove_request(&isp->pm_qos);
 
-       atomisp_msi_irq_uninit(isp, dev);
+       atomisp_msi_irq_uninit(isp);
        atomisp_unregister_entities(isp);
 
        destroy_workqueue(isp->wdt_work_queue);
index cf02737..a9c8816 100644 (file)
@@ -48,7 +48,7 @@ static struct ia_css_refcount_entry *refcount_find_entry(ia_css_ptr ptr,
                return NULL;
        if (!myrefcount.items) {
                ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
-                                   "refcount_find_entry(): Ref count not initialized!\n");
+                                   "%s(): Ref count not initialized!\n", __func__);
                return NULL;
        }
 
@@ -73,12 +73,12 @@ int ia_css_refcount_init(uint32_t size)
 
        if (size == 0) {
                ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
-                                   "ia_css_refcount_init(): Size of 0 for Ref count init!\n");
+                                   "%s(): Size of 0 for Ref count init!\n", __func__);
                return -EINVAL;
        }
        if (myrefcount.items) {
                ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
-                                   "ia_css_refcount_init(): Ref count is already initialized\n");
+                                   "%s(): Ref count is already initialized\n", __func__);
                return -EINVAL;
        }
        myrefcount.items =
@@ -99,7 +99,7 @@ void ia_css_refcount_uninit(void)
        u32 i;
 
        ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
-                           "ia_css_refcount_uninit() entry\n");
+                           "%s() entry\n", __func__);
        for (i = 0; i < myrefcount.size; i++) {
                /* driver verifier tool has issues with &arr[i]
                   and prefers arr + i; as these are actually equivalent
@@ -120,7 +120,7 @@ void ia_css_refcount_uninit(void)
        myrefcount.items = NULL;
        myrefcount.size = 0;
        ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
-                           "ia_css_refcount_uninit() leave\n");
+                           "%s() leave\n", __func__);
 }
 
 ia_css_ptr ia_css_refcount_increment(s32 id, ia_css_ptr ptr)
@@ -133,7 +133,7 @@ ia_css_ptr ia_css_refcount_increment(s32 id, ia_css_ptr ptr)
        entry = refcount_find_entry(ptr, false);
 
        ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
-                           "ia_css_refcount_increment(%x) 0x%x\n", id, ptr);
+                           "%s(%x) 0x%x\n", __func__, id, ptr);
 
        if (!entry) {
                entry = refcount_find_entry(ptr, true);
@@ -145,7 +145,7 @@ ia_css_ptr ia_css_refcount_increment(s32 id, ia_css_ptr ptr)
 
        if (entry->id != id) {
                ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
-                                   "ia_css_refcount_increment(): Ref count IDS do not match!\n");
+                                   "%s(): Ref count IDS do not match!\n", __func__);
                return mmgr_NULL;
        }
 
@@ -165,7 +165,7 @@ bool ia_css_refcount_decrement(s32 id, ia_css_ptr ptr)
        struct ia_css_refcount_entry *entry;
 
        ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
-                           "ia_css_refcount_decrement(%x) 0x%x\n", id, ptr);
+                           "%s(%x) 0x%x\n", __func__, id, ptr);
 
        if (ptr == mmgr_NULL)
                return false;
@@ -175,7 +175,7 @@ bool ia_css_refcount_decrement(s32 id, ia_css_ptr ptr)
        if (entry) {
                if (entry->id != id) {
                        ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
-                                           "ia_css_refcount_decrement(): Ref count IDS do not match!\n");
+                                           "%s(): Ref count IDS do not match!\n", __func__);
                        return false;
                }
                if (entry->count > 0) {
@@ -225,8 +225,8 @@ void ia_css_refcount_clear(s32 id, clear_func clear_func_ptr)
        u32 count = 0;
 
        assert(clear_func_ptr);
-       ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_refcount_clear(%x)\n",
-                           id);
+       ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "%s(%x)\n",
+                           __func__, id);
 
        for (i = 0; i < myrefcount.size; i++) {
                /* driver verifier tool has issues with &arr[i]
@@ -236,14 +236,14 @@ void ia_css_refcount_clear(s32 id, clear_func clear_func_ptr)
                entry = myrefcount.items + i;
                if ((entry->data != mmgr_NULL) && (entry->id == id)) {
                        ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
-                                           "ia_css_refcount_clear: %x: 0x%x\n",
+                                           "%s: %x: 0x%x\n", __func__,
                                            id, entry->data);
                        if (clear_func_ptr) {
                                /* clear using provided function */
                                clear_func_ptr(entry->data);
                        } else {
                                ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
-                                                   "ia_css_refcount_clear: using hmm_free: no clear_func\n");
+                                                   "%s: using hmm_free: no clear_func\n", __func__);
                                hmm_free(entry->data);
                        }
 
@@ -260,7 +260,7 @@ void ia_css_refcount_clear(s32 id, clear_func clear_func_ptr)
                }
        }
        ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
-                           "ia_css_refcount_clear(%x): cleared %d\n", id,
+                           "%s(%x): cleared %d\n", __func__, id,
                            count);
 }
 
index addda9b..4b8a679 100644 (file)
@@ -52,32 +52,14 @@ typedef unsigned short       hive_uint16;
 typedef unsigned int         hive_uint32;
 typedef unsigned long long   hive_uint64;
 
-/* by default assume 32 bit master port (both data and address) */
-#ifndef HRT_DATA_WIDTH
-#define HRT_DATA_WIDTH 32
-#endif
-#ifndef HRT_ADDRESS_WIDTH
-#define HRT_ADDRESS_WIDTH 32
-#endif
-
+#define HRT_DATA_WIDTH   32
+#define HRT_ADDRESS_WIDTH 64
 #define HRT_DATA_BYTES    (HRT_DATA_WIDTH / 8)
 #define HRT_ADDRESS_BYTES (HRT_ADDRESS_WIDTH / 8)
+#define SIZEOF_HRT_REG    (HRT_DATA_WIDTH >> 3)
 
-#if HRT_DATA_WIDTH == 64
-typedef hive_uint64 hrt_data;
-#elif HRT_DATA_WIDTH == 32
 typedef hive_uint32 hrt_data;
-#else
-#error data width not supported
-#endif
-
-#if HRT_ADDRESS_WIDTH == 64
 typedef hive_uint64 hrt_address;
-#elif HRT_ADDRESS_WIDTH == 32
-typedef hive_uint32 hrt_address;
-#else
-#error adddres width not supported
-#endif
 
 /* use 64 bit addresses in simulation, where possible */
 typedef hive_uint64  hive_sim_address;
index 42fef17..2bd39b4 100644 (file)
@@ -735,11 +735,11 @@ ia_css_ptr hmm_host_vaddr_to_hrt_vaddr(const void *ptr)
 
 void hmm_show_mem_stat(const char *func, const int line)
 {
-       trace_printk("tol_cnt=%d usr_size=%d res_size=%d res_cnt=%d sys_size=%d  dyc_thr=%d dyc_size=%d.\n",
-                    hmm_mem_stat.tol_cnt,
-                    hmm_mem_stat.usr_size, hmm_mem_stat.res_size,
-                    hmm_mem_stat.res_cnt, hmm_mem_stat.sys_size,
-                    hmm_mem_stat.dyc_thr, hmm_mem_stat.dyc_size);
+       pr_info("tol_cnt=%d usr_size=%d res_size=%d res_cnt=%d sys_size=%d  dyc_thr=%d dyc_size=%d.\n",
+               hmm_mem_stat.tol_cnt,
+               hmm_mem_stat.usr_size, hmm_mem_stat.res_size,
+               hmm_mem_stat.res_cnt, hmm_mem_stat.sys_size,
+               hmm_mem_stat.dyc_thr, hmm_mem_stat.dyc_size);
 }
 
 void hmm_init_mem_stat(int res_pgnr, int dyc_en, int dyc_pgnr)
index d87ddf1..74fff46 100644 (file)
  * more details.
  */
 
-#ifndef __SYSTEM_GLOBAL_H_INCLUDED__
-#define __SYSTEM_GLOBAL_H_INCLUDED__
-
-#include <hive_isp_css_defs.h>
-#include <type_support.h>
-
-/*
- * The longest allowed (uninteruptible) bus transfer, does not
- * take stalling into account
- */
-#define HIVE_ISP_MAX_BURST_LENGTH      1024
-
-/*
- * Maximum allowed burst length in words for the ISP DMA
- */
-#define ISP_DMA_MAX_BURST_LENGTH       128
-
-/*
- * Create a list of HAS and IS properties that defines the system
- *
- * The configuration assumes the following
- * - The system is hetereogeneous; Multiple cells and devices classes
- * - The cell and device instances are homogeneous, each device type
- *   belongs to the same class
- * - Device instances supporting a subset of the class capabilities are
- *   allowed
- *
- * We could manage different device classes through the enumerated
- * lists (C) or the use of classes (C++), but that is presently not
- * fully supported
- *
- * N.B. the 3 input formatters are of 2 different classess
- */
-
 #define USE_INPUT_SYSTEM_VERSION_2
-
-#define HAS_MMU_VERSION_2
-#define HAS_DMA_VERSION_2
-#define HAS_GDC_VERSION_2
-#define HAS_VAMEM_VERSION_2
-#define HAS_HMEM_VERSION_1
-#define HAS_BAMEM_VERSION_2
-#define HAS_IRQ_VERSION_2
-#define HAS_IRQ_MAP_VERSION_2
-#define HAS_INPUT_FORMATTER_VERSION_2
-/* 2401: HAS_INPUT_SYSTEM_VERSION_2401 */
-#define HAS_INPUT_SYSTEM_VERSION_2
-#define HAS_BUFFERED_SENSOR
-#define HAS_FIFO_MONITORS_VERSION_2
-/* #define HAS_GP_REGS_VERSION_2 */
-#define HAS_GP_DEVICE_VERSION_2
-#define HAS_GPIO_VERSION_1
-#define HAS_TIMED_CTRL_VERSION_1
-#define HAS_RX_VERSION_2
-
-#define DMA_DDR_TO_VAMEM_WORKAROUND
-#define DMA_DDR_TO_HMEM_WORKAROUND
-
-/*
- * Semi global. "HRT" is accessible from SP, but the HRT types do not fully apply
- */
-#define HRT_VADDRESS_WIDTH     32
-//#define HRT_ADDRESS_WIDTH    64              /* Surprise, this is a local property*/
-#define HRT_DATA_WIDTH         32
-
-#define SIZEOF_HRT_REG         (HRT_DATA_WIDTH >> 3)
-#define HIVE_ISP_CTRL_DATA_BYTES (HIVE_ISP_CTRL_DATA_WIDTH / 8)
-
-/* The main bus connecting all devices */
-#define HRT_BUS_WIDTH          HIVE_ISP_CTRL_DATA_WIDTH
-#define HRT_BUS_BYTES          HIVE_ISP_CTRL_DATA_BYTES
-
-/* per-frame parameter handling support */
-#define SH_CSS_ENABLE_PER_FRAME_PARAMS
-
-typedef u32                    hrt_bus_align_t;
-
-/*
- * Enumerate the devices, device access through the API is by ID, through the DLI by address
- * The enumerator terminators are used to size the wiring arrays and as an exception value.
- */
-typedef enum {
-       DDR0_ID = 0,
-       N_DDR_ID
-} ddr_ID_t;
-
-typedef enum {
-       ISP0_ID = 0,
-       N_ISP_ID
-} isp_ID_t;
-
-typedef enum {
-       SP0_ID = 0,
-       N_SP_ID
-} sp_ID_t;
-
-typedef enum {
-       MMU0_ID = 0,
-       MMU1_ID,
-       N_MMU_ID
-} mmu_ID_t;
-
-typedef enum {
-       DMA0_ID = 0,
-       N_DMA_ID
-} dma_ID_t;
-
-typedef enum {
-       GDC0_ID = 0,
-       GDC1_ID,
-       N_GDC_ID
-} gdc_ID_t;
-
-#define N_GDC_ID_CPP 2 // this extra define is needed because we want to use it also in the preprocessor, and that doesn't work with enums.
-
-typedef enum {
-       VAMEM0_ID = 0,
-       VAMEM1_ID,
-       VAMEM2_ID,
-       N_VAMEM_ID
-} vamem_ID_t;
-
-typedef enum {
-       BAMEM0_ID = 0,
-       N_BAMEM_ID
-} bamem_ID_t;
-
-typedef enum {
-       HMEM0_ID = 0,
-       N_HMEM_ID
-} hmem_ID_t;
-
-/*
-typedef enum {
-       IRQ0_ID = 0,
-       N_IRQ_ID
-} irq_ID_t;
-*/
-
-typedef enum {
-       IRQ0_ID = 0,    // GP IRQ block
-       IRQ1_ID,                // Input formatter
-       IRQ2_ID,                // input system
-       IRQ3_ID,                // input selector
-       N_IRQ_ID
-} irq_ID_t;
-
-typedef enum {
-       FIFO_MONITOR0_ID = 0,
-       N_FIFO_MONITOR_ID
-} fifo_monitor_ID_t;
-
-/*
- * Deprecated: Since all gp_reg instances are different
- * and put in the address maps of other devices we cannot
- * enumerate them as that assumes the instrances are the
- * same.
- *
- * We define a single GP_DEVICE containing all gp_regs
- * w.r.t. a single base address
- *
-typedef enum {
-       GP_REGS0_ID = 0,
-       N_GP_REGS_ID
-} gp_regs_ID_t;
- */
-typedef enum {
-       GP_DEVICE0_ID = 0,
-       N_GP_DEVICE_ID
-} gp_device_ID_t;
-
-typedef enum {
-       GP_TIMER0_ID = 0,
-       GP_TIMER1_ID,
-       GP_TIMER2_ID,
-       GP_TIMER3_ID,
-       GP_TIMER4_ID,
-       GP_TIMER5_ID,
-       GP_TIMER6_ID,
-       GP_TIMER7_ID,
-       N_GP_TIMER_ID
-} gp_timer_ID_t;
-
-typedef enum {
-       GPIO0_ID = 0,
-       N_GPIO_ID
-} gpio_ID_t;
-
-typedef enum {
-       TIMED_CTRL0_ID = 0,
-       N_TIMED_CTRL_ID
-} timed_ctrl_ID_t;
-
-typedef enum {
-       INPUT_FORMATTER0_ID = 0,
-       INPUT_FORMATTER1_ID,
-       INPUT_FORMATTER2_ID,
-       INPUT_FORMATTER3_ID,
-       N_INPUT_FORMATTER_ID
-} input_formatter_ID_t;
-
-/* The IF RST is outside the IF */
-#define INPUT_FORMATTER0_SRST_OFFSET   0x0824
-#define INPUT_FORMATTER1_SRST_OFFSET   0x0624
-#define INPUT_FORMATTER2_SRST_OFFSET   0x0424
-#define INPUT_FORMATTER3_SRST_OFFSET   0x0224
-
-#define INPUT_FORMATTER0_SRST_MASK             0x0001
-#define INPUT_FORMATTER1_SRST_MASK             0x0002
-#define INPUT_FORMATTER2_SRST_MASK             0x0004
-#define INPUT_FORMATTER3_SRST_MASK             0x0008
-
-typedef enum {
-       INPUT_SYSTEM0_ID = 0,
-       N_INPUT_SYSTEM_ID
-} input_system_ID_t;
-
-typedef enum {
-       RX0_ID = 0,
-       N_RX_ID
-} rx_ID_t;
-
-enum mipi_port_id {
-       MIPI_PORT0_ID = 0,
-       MIPI_PORT1_ID,
-       MIPI_PORT2_ID,
-       N_MIPI_PORT_ID
-};
-
-#define        N_RX_CHANNEL_ID         4
-
-/* Generic port enumeration with an internal port type ID */
-typedef enum {
-       CSI_PORT0_ID = 0,
-       CSI_PORT1_ID,
-       CSI_PORT2_ID,
-       TPG_PORT0_ID,
-       PRBS_PORT0_ID,
-       FIFO_PORT0_ID,
-       MEMORY_PORT0_ID,
-       N_INPUT_PORT_ID
-} input_port_ID_t;
-
-typedef enum {
-       CAPTURE_UNIT0_ID = 0,
-       CAPTURE_UNIT1_ID,
-       CAPTURE_UNIT2_ID,
-       ACQUISITION_UNIT0_ID,
-       DMA_UNIT0_ID,
-       CTRL_UNIT0_ID,
-       GPREGS_UNIT0_ID,
-       FIFO_UNIT0_ID,
-       IRQ_UNIT0_ID,
-       N_SUB_SYSTEM_ID
-} sub_system_ID_t;
-
-#define        N_CAPTURE_UNIT_ID               3
-#define        N_ACQUISITION_UNIT_ID   1
-#define        N_CTRL_UNIT_ID                  1
-
-enum ia_css_isp_memories {
-       IA_CSS_ISP_PMEM0 = 0,
-       IA_CSS_ISP_DMEM0,
-       IA_CSS_ISP_VMEM0,
-       IA_CSS_ISP_VAMEM0,
-       IA_CSS_ISP_VAMEM1,
-       IA_CSS_ISP_VAMEM2,
-       IA_CSS_ISP_HMEM0,
-       IA_CSS_SP_DMEM0,
-       IA_CSS_DDR,
-       N_IA_CSS_MEMORIES
-};
-
-#define IA_CSS_NUM_MEMORIES 9
-/* For driver compatibility */
-#define N_IA_CSS_ISP_MEMORIES   IA_CSS_NUM_MEMORIES
-#define IA_CSS_NUM_ISP_MEMORIES IA_CSS_NUM_MEMORIES
-
-#if 0
-typedef enum {
-       dev_chn, /* device channels, external resource */
-       ext_mem, /* external memories */
-       int_mem, /* internal memories */
-       int_chn  /* internal channels, user defined */
-} resource_type_t;
-
-/* if this enum is extended with other memory resources, pls also extend the function resource_to_memptr() */
-typedef enum {
-       vied_nci_dev_chn_dma_ext0,
-       int_mem_vmem0,
-       int_mem_dmem0
-} resource_id_t;
-
-/* enum listing the different memories within a program group.
-   This enum is used in the mem_ptr_t type */
-typedef enum {
-       buf_mem_invalid = 0,
-       buf_mem_vmem_prog0,
-       buf_mem_dmem_prog0
-} buf_mem_t;
-
-#endif
-#endif /* __SYSTEM_GLOBAL_H_INCLUDED__ */
diff --git a/drivers/staging/media/atomisp/pci/isp2400_system_local.h b/drivers/staging/media/atomisp/pci/isp2400_system_local.h
deleted file mode 100644 (file)
index 675b8e5..0000000
+++ /dev/null
@@ -1,321 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Support for Intel Camera Imaging ISP subsystem.
- * Copyright (c) 2010-2015, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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.
- */
-
-#ifndef __SYSTEM_LOCAL_H_INCLUDED__
-#define __SYSTEM_LOCAL_H_INCLUDED__
-
-#ifdef HRT_ISP_CSS_CUSTOM_HOST
-#ifndef HRT_USE_VIR_ADDRS
-#define HRT_USE_VIR_ADDRS
-#endif
-#endif
-
-#include "system_global.h"
-
-/* HRT assumes 32 by default (see Linux/include/hive_types.h), overrule it in case it is different */
-#undef HRT_ADDRESS_WIDTH
-#define HRT_ADDRESS_WIDTH      64              /* Surprise, this is a local property */
-
-/* This interface is deprecated */
-#include "hive_types.h"
-
-/*
- * Cell specific address maps
- */
-#if HRT_ADDRESS_WIDTH == 64
-
-#define GP_FIFO_BASE   ((hrt_address)0x0000000000090104)               /* This is NOT a base address */
-
-/* DDR */
-static const hrt_address DDR_BASE[N_DDR_ID] = {
-       (hrt_address)0x0000000120000000ULL
-};
-
-/* ISP */
-static const hrt_address ISP_CTRL_BASE[N_ISP_ID] = {
-       (hrt_address)0x0000000000020000ULL
-};
-
-static const hrt_address ISP_DMEM_BASE[N_ISP_ID] = {
-       (hrt_address)0x0000000000200000ULL
-};
-
-static const hrt_address ISP_BAMEM_BASE[N_BAMEM_ID] = {
-       (hrt_address)0x0000000000100000ULL
-};
-
-static const hrt_address ISP_VAMEM_BASE[N_VAMEM_ID] = {
-       (hrt_address)0x00000000001C0000ULL,
-       (hrt_address)0x00000000001D0000ULL,
-       (hrt_address)0x00000000001E0000ULL
-};
-
-static const hrt_address ISP_HMEM_BASE[N_HMEM_ID] = {
-       (hrt_address)0x00000000001F0000ULL
-};
-
-/* SP */
-static const hrt_address SP_CTRL_BASE[N_SP_ID] = {
-       (hrt_address)0x0000000000010000ULL
-};
-
-static const hrt_address SP_DMEM_BASE[N_SP_ID] = {
-       (hrt_address)0x0000000000300000ULL
-};
-
-static const hrt_address SP_PMEM_BASE[N_SP_ID] = {
-       (hrt_address)0x00000000000B0000ULL
-};
-
-/* MMU */
-/*
- * MMU0_ID: The data MMU
- * MMU1_ID: The icache MMU
- */
-static const hrt_address MMU_BASE[N_MMU_ID] = {
-       (hrt_address)0x0000000000070000ULL,
-       (hrt_address)0x00000000000A0000ULL
-};
-
-/* DMA */
-static const hrt_address DMA_BASE[N_DMA_ID] = {
-       (hrt_address)0x0000000000040000ULL
-};
-
-/* IRQ */
-static const hrt_address IRQ_BASE[N_IRQ_ID] = {
-       (hrt_address)0x0000000000000500ULL,
-       (hrt_address)0x0000000000030A00ULL,
-       (hrt_address)0x000000000008C000ULL,
-       (hrt_address)0x0000000000090200ULL
-};
-
-/*
-       (hrt_address)0x0000000000000500ULL};
- */
-
-/* GDC */
-static const hrt_address GDC_BASE[N_GDC_ID] = {
-       (hrt_address)0x0000000000050000ULL,
-       (hrt_address)0x0000000000060000ULL
-};
-
-/* FIFO_MONITOR (not a subset of GP_DEVICE) */
-static const hrt_address FIFO_MONITOR_BASE[N_FIFO_MONITOR_ID] = {
-       (hrt_address)0x0000000000000000ULL
-};
-
-/*
-static const hrt_address GP_REGS_BASE[N_GP_REGS_ID] = {
-       (hrt_address)0x0000000000000000ULL};
-
-static const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = {
-       (hrt_address)0x0000000000090000ULL};
-*/
-
-/* GP_DEVICE (single base for all separate GP_REG instances) */
-static const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = {
-       (hrt_address)0x0000000000000000ULL
-};
-
-/*GP TIMER , all timer registers are inter-twined,
- * so, having multiple base addresses for
- * different timers does not help*/
-static const hrt_address GP_TIMER_BASE =
-    (hrt_address)0x0000000000000600ULL;
-/* GPIO */
-static const hrt_address GPIO_BASE[N_GPIO_ID] = {
-       (hrt_address)0x0000000000000400ULL
-};
-
-/* TIMED_CTRL */
-static const hrt_address TIMED_CTRL_BASE[N_TIMED_CTRL_ID] = {
-       (hrt_address)0x0000000000000100ULL
-};
-
-/* INPUT_FORMATTER */
-static const hrt_address INPUT_FORMATTER_BASE[N_INPUT_FORMATTER_ID] = {
-       (hrt_address)0x0000000000030000ULL,
-       (hrt_address)0x0000000000030200ULL,
-       (hrt_address)0x0000000000030400ULL,
-       (hrt_address)0x0000000000030600ULL
-}; /* memcpy() */
-
-/* INPUT_SYSTEM */
-static const hrt_address INPUT_SYSTEM_BASE[N_INPUT_SYSTEM_ID] = {
-       (hrt_address)0x0000000000080000ULL
-};
-
-/*     (hrt_address)0x0000000000081000ULL, */ /* capture A */
-/*     (hrt_address)0x0000000000082000ULL, */ /* capture B */
-/*     (hrt_address)0x0000000000083000ULL, */ /* capture C */
-/*     (hrt_address)0x0000000000084000ULL, */ /* Acquisition */
-/*     (hrt_address)0x0000000000085000ULL, */ /* DMA */
-/*     (hrt_address)0x0000000000089000ULL, */ /* ctrl */
-/*     (hrt_address)0x000000000008A000ULL, */ /* GP regs */
-/*     (hrt_address)0x000000000008B000ULL, */ /* FIFO */
-/*     (hrt_address)0x000000000008C000ULL, */ /* IRQ */
-
-/* RX, the MIPI lane control regs start at offset 0 */
-static const hrt_address RX_BASE[N_RX_ID] = {
-       (hrt_address)0x0000000000080100ULL
-};
-
-#elif HRT_ADDRESS_WIDTH == 32
-
-#define GP_FIFO_BASE   ((hrt_address)0x00090104)               /* This is NOT a base address */
-
-/* DDR : Attention, this value not defined in 32-bit */
-static const hrt_address DDR_BASE[N_DDR_ID] = {
-       (hrt_address)0x00000000UL
-};
-
-/* ISP */
-static const hrt_address ISP_CTRL_BASE[N_ISP_ID] = {
-       (hrt_address)0x00020000UL
-};
-
-static const hrt_address ISP_DMEM_BASE[N_ISP_ID] = {
-       (hrt_address)0x00200000UL
-};
-
-static const hrt_address ISP_BAMEM_BASE[N_BAMEM_ID] = {
-       (hrt_address)0x100000UL
-};
-
-static const hrt_address ISP_VAMEM_BASE[N_VAMEM_ID] = {
-       (hrt_address)0xffffffffUL,
-       (hrt_address)0xffffffffUL,
-       (hrt_address)0xffffffffUL
-};
-
-static const hrt_address ISP_HMEM_BASE[N_HMEM_ID] = {
-       (hrt_address)0xffffffffUL
-};
-
-/* SP */
-static const hrt_address SP_CTRL_BASE[N_SP_ID] = {
-       (hrt_address)0x00010000UL
-};
-
-static const hrt_address SP_DMEM_BASE[N_SP_ID] = {
-       (hrt_address)0x00300000UL
-};
-
-static const hrt_address SP_PMEM_BASE[N_SP_ID] = {
-       (hrt_address)0x000B0000UL
-};
-
-/* MMU */
-/*
- * MMU0_ID: The data MMU
- * MMU1_ID: The icache MMU
- */
-static const hrt_address MMU_BASE[N_MMU_ID] = {
-       (hrt_address)0x00070000UL,
-       (hrt_address)0x000A0000UL
-};
-
-/* DMA */
-static const hrt_address DMA_BASE[N_DMA_ID] = {
-       (hrt_address)0x00040000UL
-};
-
-/* IRQ */
-static const hrt_address IRQ_BASE[N_IRQ_ID] = {
-       (hrt_address)0x00000500UL,
-       (hrt_address)0x00030A00UL,
-       (hrt_address)0x0008C000UL,
-       (hrt_address)0x00090200UL
-};
-
-/*
-       (hrt_address)0x00000500UL};
- */
-
-/* GDC */
-static const hrt_address GDC_BASE[N_GDC_ID] = {
-       (hrt_address)0x00050000UL,
-       (hrt_address)0x00060000UL
-};
-
-/* FIFO_MONITOR (not a subset of GP_DEVICE) */
-static const hrt_address FIFO_MONITOR_BASE[N_FIFO_MONITOR_ID] = {
-       (hrt_address)0x00000000UL
-};
-
-/*
-static const hrt_address GP_REGS_BASE[N_GP_REGS_ID] = {
-       (hrt_address)0x00000000UL};
-
-static const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = {
-       (hrt_address)0x00090000UL};
-*/
-
-/* GP_DEVICE (single base for all separate GP_REG instances) */
-static const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = {
-       (hrt_address)0x00000000UL
-};
-
-/*GP TIMER , all timer registers are inter-twined,
- * so, having multiple base addresses for
- * different timers does not help*/
-static const hrt_address GP_TIMER_BASE =
-    (hrt_address)0x00000600UL;
-
-/* GPIO */
-static const hrt_address GPIO_BASE[N_GPIO_ID] = {
-       (hrt_address)0x00000400UL
-};
-
-/* TIMED_CTRL */
-static const hrt_address TIMED_CTRL_BASE[N_TIMED_CTRL_ID] = {
-       (hrt_address)0x00000100UL
-};
-
-/* INPUT_FORMATTER */
-static const hrt_address INPUT_FORMATTER_BASE[N_INPUT_FORMATTER_ID] = {
-       (hrt_address)0x00030000UL,
-       (hrt_address)0x00030200UL,
-       (hrt_address)0x00030400UL
-};
-
-/*     (hrt_address)0x00030600UL, */ /* memcpy() */
-
-/* INPUT_SYSTEM */
-static const hrt_address INPUT_SYSTEM_BASE[N_INPUT_SYSTEM_ID] = {
-       (hrt_address)0x00080000UL
-};
-
-/*     (hrt_address)0x00081000UL, */ /* capture A */
-/*     (hrt_address)0x00082000UL, */ /* capture B */
-/*     (hrt_address)0x00083000UL, */ /* capture C */
-/*     (hrt_address)0x00084000UL, */ /* Acquisition */
-/*     (hrt_address)0x00085000UL, */ /* DMA */
-/*     (hrt_address)0x00089000UL, */ /* ctrl */
-/*     (hrt_address)0x0008A000UL, */ /* GP regs */
-/*     (hrt_address)0x0008B000UL, */ /* FIFO */
-/*     (hrt_address)0x0008C000UL, */ /* IRQ */
-
-/* RX, the MIPI lane control regs start at offset 0 */
-static const hrt_address RX_BASE[N_RX_ID] = {
-       (hrt_address)0x00080100UL
-};
-
-#else
-#error "system_local.h: HRT_ADDRESS_WIDTH must be one of {32,64}"
-#endif
-
-#endif /* __SYSTEM_LOCAL_H_INCLUDED__ */
index 8bb2a95..27cd253 100644 (file)
  * more details.
  */
 
-#ifndef __SYSTEM_GLOBAL_H_INCLUDED__
-#define __SYSTEM_GLOBAL_H_INCLUDED__
-
-#include <hive_isp_css_defs.h>
-#include <type_support.h>
-
-/*
- * The longest allowed (uninteruptible) bus transfer, does not
- * take stalling into account
- */
-#define HIVE_ISP_MAX_BURST_LENGTH      1024
-
-/*
- * Maximum allowed burst length in words for the ISP DMA
- * This value is set to 2 to prevent the ISP DMA from blocking
- * the bus for too long; as the input system can only buffer
- * 2 lines on Moorefield and Cherrytrail, the input system buffers
- * may overflow if blocked for too long (BZ 2726).
- */
-#define ISP_DMA_MAX_BURST_LENGTH       2
-
-/*
- * Create a list of HAS and IS properties that defines the system
- *
- * The configuration assumes the following
- * - The system is hetereogeneous; Multiple cells and devices classes
- * - The cell and device instances are homogeneous, each device type
- *   belongs to the same class
- * - Device instances supporting a subset of the class capabilities are
- *   allowed
- *
- * We could manage different device classes through the enumerated
- * lists (C) or the use of classes (C++), but that is presently not
- * fully supported
- *
- * N.B. the 3 input formatters are of 2 different classess
- */
-
+#define HAS_NO_INPUT_FORMATTER
 #define USE_INPUT_SYSTEM_VERSION_2401
-
-#define HAS_MMU_VERSION_2
-#define HAS_DMA_VERSION_2
-#define HAS_GDC_VERSION_2
-#define HAS_VAMEM_VERSION_2
-#define HAS_HMEM_VERSION_1
-#define HAS_BAMEM_VERSION_2
-#define HAS_IRQ_VERSION_2
-#define HAS_IRQ_MAP_VERSION_2
-#define HAS_INPUT_FORMATTER_VERSION_2
-/* 2401: HAS_INPUT_SYSTEM_VERSION_3 */
-/* 2400: HAS_INPUT_SYSTEM_VERSION_2 */
-#define HAS_INPUT_SYSTEM_VERSION_2
 #define HAS_INPUT_SYSTEM_VERSION_2401
-#define HAS_BUFFERED_SENSOR
-#define HAS_FIFO_MONITORS_VERSION_2
-/* #define HAS_GP_REGS_VERSION_2 */
-#define HAS_GP_DEVICE_VERSION_2
-#define HAS_GPIO_VERSION_1
-#define HAS_TIMED_CTRL_VERSION_1
-#define HAS_RX_VERSION_2
-#define HAS_NO_INPUT_FORMATTER
-/*#define HAS_NO_PACKED_RAW_PIXELS*/
-/*#define HAS_NO_DVS_6AXIS_CONFIG_UPDATE*/
-
-#define DMA_DDR_TO_VAMEM_WORKAROUND
-#define DMA_DDR_TO_HMEM_WORKAROUND
-
-/*
- * Semi global. "HRT" is accessible from SP, but
- * the HRT types do not fully apply
- */
-#define HRT_VADDRESS_WIDTH     32
-/* Surprise, this is a local property*/
-/*#define HRT_ADDRESS_WIDTH    64 */
-#define HRT_DATA_WIDTH         32
-
-#define SIZEOF_HRT_REG         (HRT_DATA_WIDTH >> 3)
-#define HIVE_ISP_CTRL_DATA_BYTES (HIVE_ISP_CTRL_DATA_WIDTH / 8)
-
-/* The main bus connecting all devices */
-#define HRT_BUS_WIDTH          HIVE_ISP_CTRL_DATA_WIDTH
-#define HRT_BUS_BYTES          HIVE_ISP_CTRL_DATA_BYTES
-
 #define CSI2P_DISABLE_ISYS2401_ONLINE_MODE
-
-/* per-frame parameter handling support */
-#define SH_CSS_ENABLE_PER_FRAME_PARAMS
-
-typedef u32                    hrt_bus_align_t;
-
-/*
- * Enumerate the devices, device access through the API is by ID,
- * through the DLI by address. The enumerator terminators are used
- * to size the wiring arrays and as an exception value.
- */
-typedef enum {
-       DDR0_ID = 0,
-       N_DDR_ID
-} ddr_ID_t;
-
-typedef enum {
-       ISP0_ID = 0,
-       N_ISP_ID
-} isp_ID_t;
-
-typedef enum {
-       SP0_ID = 0,
-       N_SP_ID
-} sp_ID_t;
-
-typedef enum {
-       MMU0_ID = 0,
-       MMU1_ID,
-       N_MMU_ID
-} mmu_ID_t;
-
-typedef enum {
-       DMA0_ID = 0,
-       N_DMA_ID
-} dma_ID_t;
-
-typedef enum {
-       GDC0_ID = 0,
-       GDC1_ID,
-       N_GDC_ID
-} gdc_ID_t;
-
-/* this extra define is needed because we want to use it also
-   in the preprocessor, and that doesn't work with enums.
- */
-#define N_GDC_ID_CPP 2
-
-typedef enum {
-       VAMEM0_ID = 0,
-       VAMEM1_ID,
-       VAMEM2_ID,
-       N_VAMEM_ID
-} vamem_ID_t;
-
-typedef enum {
-       BAMEM0_ID = 0,
-       N_BAMEM_ID
-} bamem_ID_t;
-
-typedef enum {
-       HMEM0_ID = 0,
-       N_HMEM_ID
-} hmem_ID_t;
-
-typedef enum {
-       ISYS_IRQ0_ID = 0,       /* port a */
-       ISYS_IRQ1_ID,   /* port b */
-       ISYS_IRQ2_ID,   /* port c */
-       N_ISYS_IRQ_ID
-} isys_irq_ID_t;
-
-typedef enum {
-       IRQ0_ID = 0,    /* GP IRQ block */
-       IRQ1_ID,        /* Input formatter */
-       IRQ2_ID,        /* input system */
-       IRQ3_ID,        /* input selector */
-       N_IRQ_ID
-} irq_ID_t;
-
-typedef enum {
-       FIFO_MONITOR0_ID = 0,
-       N_FIFO_MONITOR_ID
-} fifo_monitor_ID_t;
-
-/*
- * Deprecated: Since all gp_reg instances are different
- * and put in the address maps of other devices we cannot
- * enumerate them as that assumes the instrances are the
- * same.
- *
- * We define a single GP_DEVICE containing all gp_regs
- * w.r.t. a single base address
- *
-typedef enum {
-       GP_REGS0_ID = 0,
-       N_GP_REGS_ID
-} gp_regs_ID_t;
- */
-typedef enum {
-       GP_DEVICE0_ID = 0,
-       N_GP_DEVICE_ID
-} gp_device_ID_t;
-
-typedef enum {
-       GP_TIMER0_ID = 0,
-       GP_TIMER1_ID,
-       GP_TIMER2_ID,
-       GP_TIMER3_ID,
-       GP_TIMER4_ID,
-       GP_TIMER5_ID,
-       GP_TIMER6_ID,
-       GP_TIMER7_ID,
-       N_GP_TIMER_ID
-} gp_timer_ID_t;
-
-typedef enum {
-       GPIO0_ID = 0,
-       N_GPIO_ID
-} gpio_ID_t;
-
-typedef enum {
-       TIMED_CTRL0_ID = 0,
-       N_TIMED_CTRL_ID
-} timed_ctrl_ID_t;
-
-typedef enum {
-       INPUT_FORMATTER0_ID = 0,
-       INPUT_FORMATTER1_ID,
-       INPUT_FORMATTER2_ID,
-       INPUT_FORMATTER3_ID,
-       N_INPUT_FORMATTER_ID
-} input_formatter_ID_t;
-
-/* The IF RST is outside the IF */
-#define INPUT_FORMATTER0_SRST_OFFSET   0x0824
-#define INPUT_FORMATTER1_SRST_OFFSET   0x0624
-#define INPUT_FORMATTER2_SRST_OFFSET   0x0424
-#define INPUT_FORMATTER3_SRST_OFFSET   0x0224
-
-#define INPUT_FORMATTER0_SRST_MASK             0x0001
-#define INPUT_FORMATTER1_SRST_MASK             0x0002
-#define INPUT_FORMATTER2_SRST_MASK             0x0004
-#define INPUT_FORMATTER3_SRST_MASK             0x0008
-
-typedef enum {
-       INPUT_SYSTEM0_ID = 0,
-       N_INPUT_SYSTEM_ID
-} input_system_ID_t;
-
-typedef enum {
-       RX0_ID = 0,
-       N_RX_ID
-} rx_ID_t;
-
-enum mipi_port_id {
-       MIPI_PORT0_ID = 0,
-       MIPI_PORT1_ID,
-       MIPI_PORT2_ID,
-       N_MIPI_PORT_ID
-};
-
-#define        N_RX_CHANNEL_ID         4
-
-/* Generic port enumeration with an internal port type ID */
-typedef enum {
-       CSI_PORT0_ID = 0,
-       CSI_PORT1_ID,
-       CSI_PORT2_ID,
-       TPG_PORT0_ID,
-       PRBS_PORT0_ID,
-       FIFO_PORT0_ID,
-       MEMORY_PORT0_ID,
-       N_INPUT_PORT_ID
-} input_port_ID_t;
-
-typedef enum {
-       CAPTURE_UNIT0_ID = 0,
-       CAPTURE_UNIT1_ID,
-       CAPTURE_UNIT2_ID,
-       ACQUISITION_UNIT0_ID,
-       DMA_UNIT0_ID,
-       CTRL_UNIT0_ID,
-       GPREGS_UNIT0_ID,
-       FIFO_UNIT0_ID,
-       IRQ_UNIT0_ID,
-       N_SUB_SYSTEM_ID
-} sub_system_ID_t;
-
-#define        N_CAPTURE_UNIT_ID               3
-#define        N_ACQUISITION_UNIT_ID   1
-#define        N_CTRL_UNIT_ID                  1
-
-/*
- * Input-buffer Controller.
- */
-typedef enum {
-       IBUF_CTRL0_ID = 0,      /* map to ISYS2401_IBUF_CNTRL_A */
-       IBUF_CTRL1_ID,          /* map to ISYS2401_IBUF_CNTRL_B */
-       IBUF_CTRL2_ID,          /* map ISYS2401_IBUF_CNTRL_C */
-       N_IBUF_CTRL_ID
-} ibuf_ctrl_ID_t;
-/* end of Input-buffer Controller */
-
-/*
- * Stream2MMIO.
- */
-typedef enum {
-       STREAM2MMIO0_ID = 0,    /* map to ISYS2401_S2M_A */
-       STREAM2MMIO1_ID,        /* map to ISYS2401_S2M_B */
-       STREAM2MMIO2_ID,        /* map to ISYS2401_S2M_C */
-       N_STREAM2MMIO_ID
-} stream2mmio_ID_t;
-
-typedef enum {
-       /*
-        * Stream2MMIO 0 has 8 SIDs that are indexed by
-        * [STREAM2MMIO_SID0_ID...STREAM2MMIO_SID7_ID].
-        *
-        * Stream2MMIO 1 has 4 SIDs that are indexed by
-        * [STREAM2MMIO_SID0_ID...TREAM2MMIO_SID3_ID].
-        *
-        * Stream2MMIO 2 has 4 SIDs that are indexed by
-        * [STREAM2MMIO_SID0_ID...STREAM2MMIO_SID3_ID].
-        */
-       STREAM2MMIO_SID0_ID = 0,
-       STREAM2MMIO_SID1_ID,
-       STREAM2MMIO_SID2_ID,
-       STREAM2MMIO_SID3_ID,
-       STREAM2MMIO_SID4_ID,
-       STREAM2MMIO_SID5_ID,
-       STREAM2MMIO_SID6_ID,
-       STREAM2MMIO_SID7_ID,
-       N_STREAM2MMIO_SID_ID
-} stream2mmio_sid_ID_t;
-/* end of Stream2MMIO */
-
-/**
- * Input System 2401: CSI-MIPI recevier.
- */
-typedef enum {
-       CSI_RX_BACKEND0_ID = 0, /* map to ISYS2401_MIPI_BE_A */
-       CSI_RX_BACKEND1_ID,             /* map to ISYS2401_MIPI_BE_B */
-       CSI_RX_BACKEND2_ID,             /* map to ISYS2401_MIPI_BE_C */
-       N_CSI_RX_BACKEND_ID
-} csi_rx_backend_ID_t;
-
-typedef enum {
-       CSI_RX_FRONTEND0_ID = 0,        /* map to ISYS2401_CSI_RX_A */
-       CSI_RX_FRONTEND1_ID,            /* map to ISYS2401_CSI_RX_B */
-       CSI_RX_FRONTEND2_ID,            /* map to ISYS2401_CSI_RX_C */
-#define N_CSI_RX_FRONTEND_ID (CSI_RX_FRONTEND2_ID + 1)
-} csi_rx_frontend_ID_t;
-
-typedef enum {
-       CSI_RX_DLANE0_ID = 0,           /* map to DLANE0 in CSI RX */
-       CSI_RX_DLANE1_ID,               /* map to DLANE1 in CSI RX */
-       CSI_RX_DLANE2_ID,               /* map to DLANE2 in CSI RX */
-       CSI_RX_DLANE3_ID,               /* map to DLANE3 in CSI RX */
-       N_CSI_RX_DLANE_ID
-} csi_rx_fe_dlane_ID_t;
-/* end of CSI-MIPI receiver */
-
-typedef enum {
-       ISYS2401_DMA0_ID = 0,
-       N_ISYS2401_DMA_ID
-} isys2401_dma_ID_t;
-
-/**
- * Pixel-generator. ("system_global.h")
- */
-typedef enum {
-       PIXELGEN0_ID = 0,
-       PIXELGEN1_ID,
-       PIXELGEN2_ID,
-       N_PIXELGEN_ID
-} pixelgen_ID_t;
-/* end of pixel-generator. ("system_global.h") */
-
-typedef enum {
-       INPUT_SYSTEM_CSI_PORT0_ID = 0,
-       INPUT_SYSTEM_CSI_PORT1_ID,
-       INPUT_SYSTEM_CSI_PORT2_ID,
-
-       INPUT_SYSTEM_PIXELGEN_PORT0_ID,
-       INPUT_SYSTEM_PIXELGEN_PORT1_ID,
-       INPUT_SYSTEM_PIXELGEN_PORT2_ID,
-
-       N_INPUT_SYSTEM_INPUT_PORT_ID
-} input_system_input_port_ID_t;
-
-#define N_INPUT_SYSTEM_CSI_PORT        3
-
-typedef enum {
-       ISYS2401_DMA_CHANNEL_0 = 0,
-       ISYS2401_DMA_CHANNEL_1,
-       ISYS2401_DMA_CHANNEL_2,
-       ISYS2401_DMA_CHANNEL_3,
-       ISYS2401_DMA_CHANNEL_4,
-       ISYS2401_DMA_CHANNEL_5,
-       ISYS2401_DMA_CHANNEL_6,
-       ISYS2401_DMA_CHANNEL_7,
-       ISYS2401_DMA_CHANNEL_8,
-       ISYS2401_DMA_CHANNEL_9,
-       ISYS2401_DMA_CHANNEL_10,
-       ISYS2401_DMA_CHANNEL_11,
-       N_ISYS2401_DMA_CHANNEL
-} isys2401_dma_channel;
-
-enum ia_css_isp_memories {
-       IA_CSS_ISP_PMEM0 = 0,
-       IA_CSS_ISP_DMEM0,
-       IA_CSS_ISP_VMEM0,
-       IA_CSS_ISP_VAMEM0,
-       IA_CSS_ISP_VAMEM1,
-       IA_CSS_ISP_VAMEM2,
-       IA_CSS_ISP_HMEM0,
-       IA_CSS_SP_DMEM0,
-       IA_CSS_DDR,
-       N_IA_CSS_MEMORIES
-};
-
-#define IA_CSS_NUM_MEMORIES 9
-/* For driver compatibility */
-#define N_IA_CSS_ISP_MEMORIES   IA_CSS_NUM_MEMORIES
-#define IA_CSS_NUM_ISP_MEMORIES IA_CSS_NUM_MEMORIES
-
-#endif /* __SYSTEM_GLOBAL_H_INCLUDED__ */
diff --git a/drivers/staging/media/atomisp/pci/isp2401_system_local.h b/drivers/staging/media/atomisp/pci/isp2401_system_local.h
deleted file mode 100644 (file)
index b09f8fa..0000000
+++ /dev/null
@@ -1,402 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Support for Intel Camera Imaging ISP subsystem.
- * Copyright (c) 2015, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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.
- */
-
-#ifndef __SYSTEM_LOCAL_H_INCLUDED__
-#define __SYSTEM_LOCAL_H_INCLUDED__
-
-#ifdef HRT_ISP_CSS_CUSTOM_HOST
-#ifndef HRT_USE_VIR_ADDRS
-#define HRT_USE_VIR_ADDRS
-#endif
-#endif
-
-#include "system_global.h"
-
-#define HRT_ADDRESS_WIDTH      64              /* Surprise, this is a local property */
-
-/* This interface is deprecated */
-#include "hive_types.h"
-
-/*
- * Cell specific address maps
- */
-#if HRT_ADDRESS_WIDTH == 64
-
-#define GP_FIFO_BASE   ((hrt_address)0x0000000000090104)               /* This is NOT a base address */
-
-/* DDR */
-static const hrt_address DDR_BASE[N_DDR_ID] = {
-       0x0000000120000000ULL
-};
-
-/* ISP */
-static const hrt_address ISP_CTRL_BASE[N_ISP_ID] = {
-       0x0000000000020000ULL
-};
-
-static const hrt_address ISP_DMEM_BASE[N_ISP_ID] = {
-       0x0000000000200000ULL
-};
-
-static const hrt_address ISP_BAMEM_BASE[N_BAMEM_ID] = {
-       0x0000000000100000ULL
-};
-
-static const hrt_address ISP_VAMEM_BASE[N_VAMEM_ID] = {
-       0x00000000001C0000ULL,
-       0x00000000001D0000ULL,
-       0x00000000001E0000ULL
-};
-
-static const hrt_address ISP_HMEM_BASE[N_HMEM_ID] = {
-       0x00000000001F0000ULL
-};
-
-/* SP */
-static const hrt_address SP_CTRL_BASE[N_SP_ID] = {
-       0x0000000000010000ULL
-};
-
-static const hrt_address SP_DMEM_BASE[N_SP_ID] = {
-       0x0000000000300000ULL
-};
-
-/* MMU */
-/*
- * MMU0_ID: The data MMU
- * MMU1_ID: The icache MMU
- */
-static const hrt_address MMU_BASE[N_MMU_ID] = {
-       0x0000000000070000ULL,
-       0x00000000000A0000ULL
-};
-
-/* DMA */
-static const hrt_address DMA_BASE[N_DMA_ID] = {
-       0x0000000000040000ULL
-};
-
-static const hrt_address ISYS2401_DMA_BASE[N_ISYS2401_DMA_ID] = {
-       0x00000000000CA000ULL
-};
-
-/* IRQ */
-static const hrt_address IRQ_BASE[N_IRQ_ID] = {
-       0x0000000000000500ULL,
-       0x0000000000030A00ULL,
-       0x000000000008C000ULL,
-       0x0000000000090200ULL
-};
-
-/*
-       0x0000000000000500ULL};
- */
-
-/* GDC */
-static const hrt_address GDC_BASE[N_GDC_ID] = {
-       0x0000000000050000ULL,
-       0x0000000000060000ULL
-};
-
-/* FIFO_MONITOR (not a subset of GP_DEVICE) */
-static const hrt_address FIFO_MONITOR_BASE[N_FIFO_MONITOR_ID] = {
-       0x0000000000000000ULL
-};
-
-/*
-static const hrt_address GP_REGS_BASE[N_GP_REGS_ID] = {
-       0x0000000000000000ULL};
-
-static const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = {
-       0x0000000000090000ULL};
-*/
-
-/* GP_DEVICE (single base for all separate GP_REG instances) */
-static const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = {
-       0x0000000000000000ULL
-};
-
-/*GP TIMER , all timer registers are inter-twined,
- * so, having multiple base addresses for
- * different timers does not help*/
-static const hrt_address GP_TIMER_BASE =
-    (hrt_address)0x0000000000000600ULL;
-
-/* GPIO */
-static const hrt_address GPIO_BASE[N_GPIO_ID] = {
-       0x0000000000000400ULL
-};
-
-/* TIMED_CTRL */
-static const hrt_address TIMED_CTRL_BASE[N_TIMED_CTRL_ID] = {
-       0x0000000000000100ULL
-};
-
-/* INPUT_FORMATTER */
-static const hrt_address INPUT_FORMATTER_BASE[N_INPUT_FORMATTER_ID] = {
-       0x0000000000030000ULL,
-       0x0000000000030200ULL,
-       0x0000000000030400ULL,
-       0x0000000000030600ULL
-}; /* memcpy() */
-
-/* INPUT_SYSTEM */
-static const hrt_address INPUT_SYSTEM_BASE[N_INPUT_SYSTEM_ID] = {
-       0x0000000000080000ULL
-};
-
-/*     0x0000000000081000ULL, */ /* capture A */
-/*     0x0000000000082000ULL, */ /* capture B */
-/*     0x0000000000083000ULL, */ /* capture C */
-/*     0x0000000000084000ULL, */ /* Acquisition */
-/*     0x0000000000085000ULL, */ /* DMA */
-/*     0x0000000000089000ULL, */ /* ctrl */
-/*     0x000000000008A000ULL, */ /* GP regs */
-/*     0x000000000008B000ULL, */ /* FIFO */
-/*     0x000000000008C000ULL, */ /* IRQ */
-
-/* RX, the MIPI lane control regs start at offset 0 */
-static const hrt_address RX_BASE[N_RX_ID] = {
-       0x0000000000080100ULL
-};
-
-/* IBUF_CTRL, part of the Input System 2401 */
-static const hrt_address IBUF_CTRL_BASE[N_IBUF_CTRL_ID] = {
-       0x00000000000C1800ULL,  /* ibuf controller A */
-       0x00000000000C3800ULL,  /* ibuf controller B */
-       0x00000000000C5800ULL   /* ibuf controller C */
-};
-
-/* ISYS IRQ Controllers, part of the Input System 2401 */
-static const hrt_address ISYS_IRQ_BASE[N_ISYS_IRQ_ID] = {
-       0x00000000000C1400ULL,  /* port a */
-       0x00000000000C3400ULL,  /* port b */
-       0x00000000000C5400ULL   /* port c */
-};
-
-/* CSI FE, part of the Input System 2401 */
-static const hrt_address CSI_RX_FE_CTRL_BASE[N_CSI_RX_FRONTEND_ID] = {
-       0x00000000000C0400ULL,  /* csi fe controller A */
-       0x00000000000C2400ULL,  /* csi fe controller B */
-       0x00000000000C4400ULL   /* csi fe controller C */
-};
-
-/* CSI BE, part of the Input System 2401 */
-static const hrt_address CSI_RX_BE_CTRL_BASE[N_CSI_RX_BACKEND_ID] = {
-       0x00000000000C0800ULL,  /* csi be controller A */
-       0x00000000000C2800ULL,  /* csi be controller B */
-       0x00000000000C4800ULL   /* csi be controller C */
-};
-
-/* PIXEL Generator, part of the Input System 2401 */
-static const hrt_address PIXELGEN_CTRL_BASE[N_PIXELGEN_ID] = {
-       0x00000000000C1000ULL,  /* pixel gen controller A */
-       0x00000000000C3000ULL,  /* pixel gen controller B */
-       0x00000000000C5000ULL   /* pixel gen controller C */
-};
-
-/* Stream2MMIO, part of the Input System 2401 */
-static const hrt_address STREAM2MMIO_CTRL_BASE[N_STREAM2MMIO_ID] = {
-       0x00000000000C0C00ULL,  /* stream2mmio controller A */
-       0x00000000000C2C00ULL,  /* stream2mmio controller B */
-       0x00000000000C4C00ULL   /* stream2mmio controller C */
-};
-#elif HRT_ADDRESS_WIDTH == 32
-
-#define GP_FIFO_BASE   ((hrt_address)0x00090104)               /* This is NOT a base address */
-
-/* DDR : Attention, this value not defined in 32-bit */
-static const hrt_address DDR_BASE[N_DDR_ID] = {
-       0x00000000UL
-};
-
-/* ISP */
-static const hrt_address ISP_CTRL_BASE[N_ISP_ID] = {
-       0x00020000UL
-};
-
-static const hrt_address ISP_DMEM_BASE[N_ISP_ID] = {
-       0xffffffffUL
-};
-
-static const hrt_address ISP_BAMEM_BASE[N_BAMEM_ID] = {
-       0xffffffffUL
-};
-
-static const hrt_address ISP_VAMEM_BASE[N_VAMEM_ID] = {
-       0xffffffffUL,
-       0xffffffffUL,
-       0xffffffffUL
-};
-
-static const hrt_address ISP_HMEM_BASE[N_HMEM_ID] = {
-       0xffffffffUL
-};
-
-/* SP */
-static const hrt_address SP_CTRL_BASE[N_SP_ID] = {
-       0x00010000UL
-};
-
-static const hrt_address SP_DMEM_BASE[N_SP_ID] = {
-       0x00300000UL
-};
-
-/* MMU */
-/*
- * MMU0_ID: The data MMU
- * MMU1_ID: The icache MMU
- */
-static const hrt_address MMU_BASE[N_MMU_ID] = {
-       0x00070000UL,
-       0x000A0000UL
-};
-
-/* DMA */
-static const hrt_address DMA_BASE[N_DMA_ID] = {
-       0x00040000UL
-};
-
-static const hrt_address ISYS2401_DMA_BASE[N_ISYS2401_DMA_ID] = {
-       0x000CA000UL
-};
-
-/* IRQ */
-static const hrt_address IRQ_BASE[N_IRQ_ID] = {
-       0x00000500UL,
-       0x00030A00UL,
-       0x0008C000UL,
-       0x00090200UL
-};
-
-/*
-       0x00000500UL};
- */
-
-/* GDC */
-static const hrt_address GDC_BASE[N_GDC_ID] = {
-       0x00050000UL,
-       0x00060000UL
-};
-
-/* FIFO_MONITOR (not a subset of GP_DEVICE) */
-static const hrt_address FIFO_MONITOR_BASE[N_FIFO_MONITOR_ID] = {
-       0x00000000UL
-};
-
-/*
-static const hrt_address GP_REGS_BASE[N_GP_REGS_ID] = {
-       0x00000000UL};
-
-static const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = {
-       0x00090000UL};
-*/
-
-/* GP_DEVICE (single base for all separate GP_REG instances) */
-static const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = {
-       0x00000000UL
-};
-
-/*GP TIMER , all timer registers are inter-twined,
- * so, having multiple base addresses for
- * different timers does not help*/
-static const hrt_address GP_TIMER_BASE =
-    (hrt_address)0x00000600UL;
-/* GPIO */
-static const hrt_address GPIO_BASE[N_GPIO_ID] = {
-       0x00000400UL
-};
-
-/* TIMED_CTRL */
-static const hrt_address TIMED_CTRL_BASE[N_TIMED_CTRL_ID] = {
-       0x00000100UL
-};
-
-/* INPUT_FORMATTER */
-static const hrt_address INPUT_FORMATTER_BASE[N_INPUT_FORMATTER_ID] = {
-       0x00030000UL,
-       0x00030200UL,
-       0x00030400UL
-};
-
-/*     0x00030600UL, */ /* memcpy() */
-
-/* INPUT_SYSTEM */
-static const hrt_address INPUT_SYSTEM_BASE[N_INPUT_SYSTEM_ID] = {
-       0x00080000UL
-};
-
-/*     0x00081000UL, */ /* capture A */
-/*     0x00082000UL, */ /* capture B */
-/*     0x00083000UL, */ /* capture C */
-/*     0x00084000UL, */ /* Acquisition */
-/*     0x00085000UL, */ /* DMA */
-/*     0x00089000UL, */ /* ctrl */
-/*     0x0008A000UL, */ /* GP regs */
-/*     0x0008B000UL, */ /* FIFO */
-/*     0x0008C000UL, */ /* IRQ */
-
-/* RX, the MIPI lane control regs start at offset 0 */
-static const hrt_address RX_BASE[N_RX_ID] = {
-       0x00080100UL
-};
-
-/* IBUF_CTRL, part of the Input System 2401 */
-static const hrt_address IBUF_CTRL_BASE[N_IBUF_CTRL_ID] = {
-       0x000C1800UL,   /* ibuf controller A */
-       0x000C3800UL,   /* ibuf controller B */
-       0x000C5800UL    /* ibuf controller C */
-};
-
-/* ISYS IRQ Controllers, part of the Input System 2401 */
-static const hrt_address ISYS_IRQ_BASE[N_ISYS_IRQ_ID] = {
-       0x000C1400ULL,  /* port a */
-       0x000C3400ULL,  /* port b */
-       0x000C5400ULL   /* port c */
-};
-
-/* CSI FE, part of the Input System 2401 */
-static const hrt_address CSI_RX_FE_CTRL_BASE[N_CSI_RX_FRONTEND_ID] = {
-       0x000C0400UL,   /* csi fe controller A */
-       0x000C2400UL,   /* csi fe controller B */
-       0x000C4400UL    /* csi fe controller C */
-};
-
-/* CSI BE, part of the Input System 2401 */
-static const hrt_address CSI_RX_FE_CTRL_BASE[N_CSI_RX_BACKEND_ID] = {
-       0x000C0800UL,   /* csi be controller A */
-       0x000C2800UL,   /* csi be controller B */
-       0x000C4800UL    /* csi be controller C */
-};
-
-/* PIXEL Generator, part of the Input System 2401 */
-static const hrt_address PIXELGEN_CTRL_BASE[N_PIXELGEN_ID] = {
-       0x000C1000UL,   /* pixel gen controller A */
-       0x000C3000UL,   /* pixel gen controller B */
-       0x000C5000UL    /* pixel gen controller C */
-};
-
-/* Stream2MMIO, part of the Input System 2401 */
-static const hrt_address STREAM2MMIO_CTRL_BASE[N_STREAM2MMIO_ID] = {
-       0x000C0C00UL,   /* stream2mmio controller A */
-       0x000C2C00UL,   /* stream2mmio controller B */
-       0x000C4C00UL    /* stream2mmio controller C */
-};
-
-#else
-#error "system_local.h: HRT_ADDRESS_WIDTH must be one of {32,64}"
-#endif
-
-#endif /* __SYSTEM_LOCAL_H_INCLUDED__ */
index 6676537..54434c2 100644 (file)
@@ -1841,8 +1841,13 @@ ia_css_init(struct device *dev, const struct ia_css_env *env,
 #endif
 
 #if !defined(HAS_NO_INPUT_SYSTEM)
-       dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN,
-                              ISP_DMA_MAX_BURST_LENGTH);
+
+       if (!IS_ISP2401)
+               dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN,
+                                      ISP2400_DMA_MAX_BURST_LENGTH);
+       else
+               dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN,
+                                      ISP2401_DMA_MAX_BURST_LENGTH);
 
        if (ia_css_isys_init() != INPUT_SYSTEM_ERR_NO_ERROR)
                err = -EINVAL;
index 16d0a2e..90210f6 100644 (file)
@@ -4,8 +4,403 @@
  *    (c) 2020 Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
  */
 
+#ifndef __SYSTEM_GLOBAL_H_INCLUDED__
+#define __SYSTEM_GLOBAL_H_INCLUDED__
+
+/*
+ * Create a list of HAS and IS properties that defines the system
+ * Those are common for both ISP2400 and ISP2401
+ *
+ * The configuration assumes the following
+ * - The system is hetereogeneous; Multiple cells and devices classes
+ * - The cell and device instances are homogeneous, each device type
+ *   belongs to the same class
+ * - Device instances supporting a subset of the class capabilities are
+ *   allowed
+ *
+ * We could manage different device classes through the enumerated
+ * lists (C) or the use of classes (C++), but that is presently not
+ * fully supported
+ *
+ * N.B. the 3 input formatters are of 2 different classess
+ */
+
+#define HAS_MMU_VERSION_2
+#define HAS_DMA_VERSION_2
+#define HAS_GDC_VERSION_2
+#define HAS_VAMEM_VERSION_2
+#define HAS_HMEM_VERSION_1
+#define HAS_BAMEM_VERSION_2
+#define HAS_IRQ_VERSION_2
+#define HAS_IRQ_MAP_VERSION_2
+#define HAS_INPUT_FORMATTER_VERSION_2
+#define HAS_INPUT_SYSTEM_VERSION_2
+#define HAS_BUFFERED_SENSOR
+#define HAS_FIFO_MONITORS_VERSION_2
+#define HAS_GP_DEVICE_VERSION_2
+#define HAS_GPIO_VERSION_1
+#define HAS_TIMED_CTRL_VERSION_1
+#define HAS_RX_VERSION_2
+
+/* per-frame parameter handling support */
+#define SH_CSS_ENABLE_PER_FRAME_PARAMS
+
+#define DMA_DDR_TO_VAMEM_WORKAROUND
+#define DMA_DDR_TO_HMEM_WORKAROUND
+
+/*
+ * The longest allowed (uninteruptible) bus transfer, does not
+ * take stalling into account
+ */
+#define HIVE_ISP_MAX_BURST_LENGTH      1024
+
+/*
+ * Maximum allowed burst length in words for the ISP DMA
+ * This value is set to 2 to prevent the ISP DMA from blocking
+ * the bus for too long; as the input system can only buffer
+ * 2 lines on Moorefield and Cherrytrail, the input system buffers
+ * may overflow if blocked for too long (BZ 2726).
+ */
+#define ISP2400_DMA_MAX_BURST_LENGTH   128
+#define ISP2401_DMA_MAX_BURST_LENGTH   2
+
 #ifdef ISP2401
 #  include "isp2401_system_global.h"
 #else
 #  include "isp2400_system_global.h"
 #endif
+
+#include <hive_isp_css_defs.h>
+#include <type_support.h>
+
+/* This interface is deprecated */
+#include "hive_types.h"
+
+/*
+ * Semi global. "HRT" is accessible from SP, but the HRT types do not fully apply
+ */
+#define HRT_VADDRESS_WIDTH     32
+
+#define SIZEOF_HRT_REG         (HRT_DATA_WIDTH >> 3)
+#define HIVE_ISP_CTRL_DATA_BYTES (HIVE_ISP_CTRL_DATA_WIDTH / 8)
+
+/* The main bus connecting all devices */
+#define HRT_BUS_WIDTH          HIVE_ISP_CTRL_DATA_WIDTH
+#define HRT_BUS_BYTES          HIVE_ISP_CTRL_DATA_BYTES
+
+typedef u32                    hrt_bus_align_t;
+
+/*
+ * Enumerate the devices, device access through the API is by ID,
+ * through the DLI by address. The enumerator terminators are used
+ * to size the wiring arrays and as an exception value.
+ */
+typedef enum {
+       DDR0_ID = 0,
+       N_DDR_ID
+} ddr_ID_t;
+
+typedef enum {
+       ISP0_ID = 0,
+       N_ISP_ID
+} isp_ID_t;
+
+typedef enum {
+       SP0_ID = 0,
+       N_SP_ID
+} sp_ID_t;
+
+typedef enum {
+       MMU0_ID = 0,
+       MMU1_ID,
+       N_MMU_ID
+} mmu_ID_t;
+
+typedef enum {
+       DMA0_ID = 0,
+       N_DMA_ID
+} dma_ID_t;
+
+typedef enum {
+       GDC0_ID = 0,
+       GDC1_ID,
+       N_GDC_ID
+} gdc_ID_t;
+
+/* this extra define is needed because we want to use it also
+   in the preprocessor, and that doesn't work with enums.
+ */
+#define N_GDC_ID_CPP 2
+
+typedef enum {
+       VAMEM0_ID = 0,
+       VAMEM1_ID,
+       VAMEM2_ID,
+       N_VAMEM_ID
+} vamem_ID_t;
+
+typedef enum {
+       BAMEM0_ID = 0,
+       N_BAMEM_ID
+} bamem_ID_t;
+
+typedef enum {
+       HMEM0_ID = 0,
+       N_HMEM_ID
+} hmem_ID_t;
+
+typedef enum {
+       IRQ0_ID = 0,    /* GP IRQ block */
+       IRQ1_ID,        /* Input formatter */
+       IRQ2_ID,        /* input system */
+       IRQ3_ID,        /* input selector */
+       N_IRQ_ID
+} irq_ID_t;
+
+typedef enum {
+       FIFO_MONITOR0_ID = 0,
+       N_FIFO_MONITOR_ID
+} fifo_monitor_ID_t;
+
+typedef enum {
+       GP_DEVICE0_ID = 0,
+       N_GP_DEVICE_ID
+} gp_device_ID_t;
+
+typedef enum {
+       GP_TIMER0_ID = 0,
+       GP_TIMER1_ID,
+       GP_TIMER2_ID,
+       GP_TIMER3_ID,
+       GP_TIMER4_ID,
+       GP_TIMER5_ID,
+       GP_TIMER6_ID,
+       GP_TIMER7_ID,
+       N_GP_TIMER_ID
+} gp_timer_ID_t;
+
+typedef enum {
+       GPIO0_ID = 0,
+       N_GPIO_ID
+} gpio_ID_t;
+
+typedef enum {
+       TIMED_CTRL0_ID = 0,
+       N_TIMED_CTRL_ID
+} timed_ctrl_ID_t;
+
+typedef enum {
+       INPUT_FORMATTER0_ID = 0,
+       INPUT_FORMATTER1_ID,
+       INPUT_FORMATTER2_ID,
+       INPUT_FORMATTER3_ID,
+       N_INPUT_FORMATTER_ID
+} input_formatter_ID_t;
+
+/* The IF RST is outside the IF */
+#define INPUT_FORMATTER0_SRST_OFFSET   0x0824
+#define INPUT_FORMATTER1_SRST_OFFSET   0x0624
+#define INPUT_FORMATTER2_SRST_OFFSET   0x0424
+#define INPUT_FORMATTER3_SRST_OFFSET   0x0224
+
+#define INPUT_FORMATTER0_SRST_MASK             0x0001
+#define INPUT_FORMATTER1_SRST_MASK             0x0002
+#define INPUT_FORMATTER2_SRST_MASK             0x0004
+#define INPUT_FORMATTER3_SRST_MASK             0x0008
+
+typedef enum {
+       INPUT_SYSTEM0_ID = 0,
+       N_INPUT_SYSTEM_ID
+} input_system_ID_t;
+
+typedef enum {
+       RX0_ID = 0,
+       N_RX_ID
+} rx_ID_t;
+
+enum mipi_port_id {
+       MIPI_PORT0_ID = 0,
+       MIPI_PORT1_ID,
+       MIPI_PORT2_ID,
+       N_MIPI_PORT_ID
+};
+
+#define        N_RX_CHANNEL_ID         4
+
+/* Generic port enumeration with an internal port type ID */
+typedef enum {
+       CSI_PORT0_ID = 0,
+       CSI_PORT1_ID,
+       CSI_PORT2_ID,
+       TPG_PORT0_ID,
+       PRBS_PORT0_ID,
+       FIFO_PORT0_ID,
+       MEMORY_PORT0_ID,
+       N_INPUT_PORT_ID
+} input_port_ID_t;
+
+typedef enum {
+       CAPTURE_UNIT0_ID = 0,
+       CAPTURE_UNIT1_ID,
+       CAPTURE_UNIT2_ID,
+       ACQUISITION_UNIT0_ID,
+       DMA_UNIT0_ID,
+       CTRL_UNIT0_ID,
+       GPREGS_UNIT0_ID,
+       FIFO_UNIT0_ID,
+       IRQ_UNIT0_ID,
+       N_SUB_SYSTEM_ID
+} sub_system_ID_t;
+
+#define        N_CAPTURE_UNIT_ID               3
+#define        N_ACQUISITION_UNIT_ID           1
+#define        N_CTRL_UNIT_ID                  1
+
+
+enum ia_css_isp_memories {
+       IA_CSS_ISP_PMEM0 = 0,
+       IA_CSS_ISP_DMEM0,
+       IA_CSS_ISP_VMEM0,
+       IA_CSS_ISP_VAMEM0,
+       IA_CSS_ISP_VAMEM1,
+       IA_CSS_ISP_VAMEM2,
+       IA_CSS_ISP_HMEM0,
+       IA_CSS_SP_DMEM0,
+       IA_CSS_DDR,
+       N_IA_CSS_MEMORIES
+};
+
+#define IA_CSS_NUM_MEMORIES 9
+/* For driver compatibility */
+#define N_IA_CSS_ISP_MEMORIES   IA_CSS_NUM_MEMORIES
+#define IA_CSS_NUM_ISP_MEMORIES IA_CSS_NUM_MEMORIES
+
+/*
+ * ISP2401 specific enums
+ */
+
+typedef enum {
+       ISYS_IRQ0_ID = 0,       /* port a */
+       ISYS_IRQ1_ID,   /* port b */
+       ISYS_IRQ2_ID,   /* port c */
+       N_ISYS_IRQ_ID
+} isys_irq_ID_t;
+
+
+/*
+ * Input-buffer Controller.
+ */
+typedef enum {
+       IBUF_CTRL0_ID = 0,      /* map to ISYS2401_IBUF_CNTRL_A */
+       IBUF_CTRL1_ID,          /* map to ISYS2401_IBUF_CNTRL_B */
+       IBUF_CTRL2_ID,          /* map ISYS2401_IBUF_CNTRL_C */
+       N_IBUF_CTRL_ID
+} ibuf_ctrl_ID_t;
+/* end of Input-buffer Controller */
+
+/*
+ * Stream2MMIO.
+ */
+typedef enum {
+       STREAM2MMIO0_ID = 0,    /* map to ISYS2401_S2M_A */
+       STREAM2MMIO1_ID,        /* map to ISYS2401_S2M_B */
+       STREAM2MMIO2_ID,        /* map to ISYS2401_S2M_C */
+       N_STREAM2MMIO_ID
+} stream2mmio_ID_t;
+
+typedef enum {
+       /*
+        * Stream2MMIO 0 has 8 SIDs that are indexed by
+        * [STREAM2MMIO_SID0_ID...STREAM2MMIO_SID7_ID].
+        *
+        * Stream2MMIO 1 has 4 SIDs that are indexed by
+        * [STREAM2MMIO_SID0_ID...TREAM2MMIO_SID3_ID].
+        *
+        * Stream2MMIO 2 has 4 SIDs that are indexed by
+        * [STREAM2MMIO_SID0_ID...STREAM2MMIO_SID3_ID].
+        */
+       STREAM2MMIO_SID0_ID = 0,
+       STREAM2MMIO_SID1_ID,
+       STREAM2MMIO_SID2_ID,
+       STREAM2MMIO_SID3_ID,
+       STREAM2MMIO_SID4_ID,
+       STREAM2MMIO_SID5_ID,
+       STREAM2MMIO_SID6_ID,
+       STREAM2MMIO_SID7_ID,
+       N_STREAM2MMIO_SID_ID
+} stream2mmio_sid_ID_t;
+/* end of Stream2MMIO */
+
+/**
+ * Input System 2401: CSI-MIPI recevier.
+ */
+typedef enum {
+       CSI_RX_BACKEND0_ID = 0, /* map to ISYS2401_MIPI_BE_A */
+       CSI_RX_BACKEND1_ID,             /* map to ISYS2401_MIPI_BE_B */
+       CSI_RX_BACKEND2_ID,             /* map to ISYS2401_MIPI_BE_C */
+       N_CSI_RX_BACKEND_ID
+} csi_rx_backend_ID_t;
+
+typedef enum {
+       CSI_RX_FRONTEND0_ID = 0,        /* map to ISYS2401_CSI_RX_A */
+       CSI_RX_FRONTEND1_ID,            /* map to ISYS2401_CSI_RX_B */
+       CSI_RX_FRONTEND2_ID,            /* map to ISYS2401_CSI_RX_C */
+#define N_CSI_RX_FRONTEND_ID (CSI_RX_FRONTEND2_ID + 1)
+} csi_rx_frontend_ID_t;
+
+typedef enum {
+       CSI_RX_DLANE0_ID = 0,           /* map to DLANE0 in CSI RX */
+       CSI_RX_DLANE1_ID,               /* map to DLANE1 in CSI RX */
+       CSI_RX_DLANE2_ID,               /* map to DLANE2 in CSI RX */
+       CSI_RX_DLANE3_ID,               /* map to DLANE3 in CSI RX */
+       N_CSI_RX_DLANE_ID
+} csi_rx_fe_dlane_ID_t;
+/* end of CSI-MIPI receiver */
+
+typedef enum {
+       ISYS2401_DMA0_ID = 0,
+       N_ISYS2401_DMA_ID
+} isys2401_dma_ID_t;
+
+/**
+ * Pixel-generator. ("system_global.h")
+ */
+typedef enum {
+       PIXELGEN0_ID = 0,
+       PIXELGEN1_ID,
+       PIXELGEN2_ID,
+       N_PIXELGEN_ID
+} pixelgen_ID_t;
+/* end of pixel-generator. ("system_global.h") */
+
+typedef enum {
+       INPUT_SYSTEM_CSI_PORT0_ID = 0,
+       INPUT_SYSTEM_CSI_PORT1_ID,
+       INPUT_SYSTEM_CSI_PORT2_ID,
+
+       INPUT_SYSTEM_PIXELGEN_PORT0_ID,
+       INPUT_SYSTEM_PIXELGEN_PORT1_ID,
+       INPUT_SYSTEM_PIXELGEN_PORT2_ID,
+
+       N_INPUT_SYSTEM_INPUT_PORT_ID
+} input_system_input_port_ID_t;
+
+#define N_INPUT_SYSTEM_CSI_PORT        3
+
+typedef enum {
+       ISYS2401_DMA_CHANNEL_0 = 0,
+       ISYS2401_DMA_CHANNEL_1,
+       ISYS2401_DMA_CHANNEL_2,
+       ISYS2401_DMA_CHANNEL_3,
+       ISYS2401_DMA_CHANNEL_4,
+       ISYS2401_DMA_CHANNEL_5,
+       ISYS2401_DMA_CHANNEL_6,
+       ISYS2401_DMA_CHANNEL_7,
+       ISYS2401_DMA_CHANNEL_8,
+       ISYS2401_DMA_CHANNEL_9,
+       ISYS2401_DMA_CHANNEL_10,
+       ISYS2401_DMA_CHANNEL_11,
+       N_ISYS2401_DMA_CHANNEL
+} isys2401_dma_channel;
+
+#endif /* __SYSTEM_GLOBAL_H_INCLUDED__ */
diff --git a/drivers/staging/media/atomisp/pci/system_local.c b/drivers/staging/media/atomisp/pci/system_local.c
new file mode 100644 (file)
index 0000000..4ca8569
--- /dev/null
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Support for Intel Camera Imaging ISP subsystem.
+ * Copyright (c) 2015, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 "system_local.h"
+
+/* ISP */
+const hrt_address ISP_CTRL_BASE[N_ISP_ID] = {
+       0x0000000000020000ULL
+};
+
+const hrt_address ISP_DMEM_BASE[N_ISP_ID] = {
+       0x0000000000200000ULL
+};
+
+const hrt_address ISP_BAMEM_BASE[N_BAMEM_ID] = {
+       0x0000000000100000ULL
+};
+
+/* SP */
+const hrt_address SP_CTRL_BASE[N_SP_ID] = {
+       0x0000000000010000ULL
+};
+
+const hrt_address SP_DMEM_BASE[N_SP_ID] = {
+       0x0000000000300000ULL
+};
+
+/* MMU */
+/*
+ * MMU0_ID: The data MMU
+ * MMU1_ID: The icache MMU
+ */
+const hrt_address MMU_BASE[N_MMU_ID] = {
+       0x0000000000070000ULL,
+       0x00000000000A0000ULL
+};
+
+/* DMA */
+const hrt_address DMA_BASE[N_DMA_ID] = {
+       0x0000000000040000ULL
+};
+
+const hrt_address ISYS2401_DMA_BASE[N_ISYS2401_DMA_ID] = {
+       0x00000000000CA000ULL
+};
+
+/* IRQ */
+const hrt_address IRQ_BASE[N_IRQ_ID] = {
+       0x0000000000000500ULL,
+       0x0000000000030A00ULL,
+       0x000000000008C000ULL,
+       0x0000000000090200ULL
+};
+
+/*
+       0x0000000000000500ULL};
+ */
+
+/* GDC */
+const hrt_address GDC_BASE[N_GDC_ID] = {
+       0x0000000000050000ULL,
+       0x0000000000060000ULL
+};
+
+/* FIFO_MONITOR (not a subset of GP_DEVICE) */
+const hrt_address FIFO_MONITOR_BASE[N_FIFO_MONITOR_ID] = {
+       0x0000000000000000ULL
+};
+
+/*
+const hrt_address GP_REGS_BASE[N_GP_REGS_ID] = {
+       0x0000000000000000ULL};
+
+const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = {
+       0x0000000000090000ULL};
+*/
+
+/* GP_DEVICE (single base for all separate GP_REG instances) */
+const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = {
+       0x0000000000000000ULL
+};
+
+/*GP TIMER , all timer registers are inter-twined,
+ * so, having multiple base addresses for
+ * different timers does not help*/
+const hrt_address GP_TIMER_BASE =
+    (hrt_address)0x0000000000000600ULL;
+
+/* GPIO */
+const hrt_address GPIO_BASE[N_GPIO_ID] = {
+       0x0000000000000400ULL
+};
+
+/* TIMED_CTRL */
+const hrt_address TIMED_CTRL_BASE[N_TIMED_CTRL_ID] = {
+       0x0000000000000100ULL
+};
+
+/* INPUT_FORMATTER */
+const hrt_address INPUT_FORMATTER_BASE[N_INPUT_FORMATTER_ID] = {
+       0x0000000000030000ULL,
+       0x0000000000030200ULL,
+       0x0000000000030400ULL,
+       0x0000000000030600ULL
+}; /* memcpy() */
+
+/* INPUT_SYSTEM */
+const hrt_address INPUT_SYSTEM_BASE[N_INPUT_SYSTEM_ID] = {
+       0x0000000000080000ULL
+};
+
+/*     0x0000000000081000ULL, */ /* capture A */
+/*     0x0000000000082000ULL, */ /* capture B */
+/*     0x0000000000083000ULL, */ /* capture C */
+/*     0x0000000000084000ULL, */ /* Acquisition */
+/*     0x0000000000085000ULL, */ /* DMA */
+/*     0x0000000000089000ULL, */ /* ctrl */
+/*     0x000000000008A000ULL, */ /* GP regs */
+/*     0x000000000008B000ULL, */ /* FIFO */
+/*     0x000000000008C000ULL, */ /* IRQ */
+
+/* RX, the MIPI lane control regs start at offset 0 */
+const hrt_address RX_BASE[N_RX_ID] = {
+       0x0000000000080100ULL
+};
+
+/* IBUF_CTRL, part of the Input System 2401 */
+const hrt_address IBUF_CTRL_BASE[N_IBUF_CTRL_ID] = {
+       0x00000000000C1800ULL,  /* ibuf controller A */
+       0x00000000000C3800ULL,  /* ibuf controller B */
+       0x00000000000C5800ULL   /* ibuf controller C */
+};
+
+/* ISYS IRQ Controllers, part of the Input System 2401 */
+const hrt_address ISYS_IRQ_BASE[N_ISYS_IRQ_ID] = {
+       0x00000000000C1400ULL,  /* port a */
+       0x00000000000C3400ULL,  /* port b */
+       0x00000000000C5400ULL   /* port c */
+};
+
+/* CSI FE, part of the Input System 2401 */
+const hrt_address CSI_RX_FE_CTRL_BASE[N_CSI_RX_FRONTEND_ID] = {
+       0x00000000000C0400ULL,  /* csi fe controller A */
+       0x00000000000C2400ULL,  /* csi fe controller B */
+       0x00000000000C4400ULL   /* csi fe controller C */
+};
+
+/* CSI BE, part of the Input System 2401 */
+const hrt_address CSI_RX_BE_CTRL_BASE[N_CSI_RX_BACKEND_ID] = {
+       0x00000000000C0800ULL,  /* csi be controller A */
+       0x00000000000C2800ULL,  /* csi be controller B */
+       0x00000000000C4800ULL   /* csi be controller C */
+};
+
+/* PIXEL Generator, part of the Input System 2401 */
+const hrt_address PIXELGEN_CTRL_BASE[N_PIXELGEN_ID] = {
+       0x00000000000C1000ULL,  /* pixel gen controller A */
+       0x00000000000C3000ULL,  /* pixel gen controller B */
+       0x00000000000C5000ULL   /* pixel gen controller C */
+};
+
+/* Stream2MMIO, part of the Input System 2401 */
+const hrt_address STREAM2MMIO_CTRL_BASE[N_STREAM2MMIO_ID] = {
+       0x00000000000C0C00ULL,  /* stream2mmio controller A */
+       0x00000000000C2C00ULL,  /* stream2mmio controller B */
+       0x00000000000C4C00ULL   /* stream2mmio controller C */
+};
index dfcc4c2..a47258c 100644 (file)
 /* SPDX-License-Identifier: GPL-2.0 */
-// SPDX-License-Identifier: GPL-2.0-or-later
 /*
- *    (c) 2020 Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+ * Support for Intel Camera Imaging ISP subsystem.
+ * Copyright (c) 2015, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 ISP2401
-#  include "isp2401_system_local.h"
-#else
-#  include "isp2400_system_local.h"
+#ifndef __SYSTEM_LOCAL_H_INCLUDED__
+#define __SYSTEM_LOCAL_H_INCLUDED__
+
+#ifdef HRT_ISP_CSS_CUSTOM_HOST
+#ifndef HRT_USE_VIR_ADDRS
+#define HRT_USE_VIR_ADDRS
+#endif
 #endif
+
+#include "system_global.h"
+
+/* This interface is deprecated */
+#include "hive_types.h"
+
+/*
+ * Cell specific address maps
+ */
+
+#define GP_FIFO_BASE   ((hrt_address)0x0000000000090104)               /* This is NOT a base address */
+
+/* ISP */
+extern const hrt_address ISP_CTRL_BASE[N_ISP_ID];
+extern const hrt_address ISP_DMEM_BASE[N_ISP_ID];
+extern const hrt_address ISP_BAMEM_BASE[N_BAMEM_ID];
+
+/* SP */
+extern const hrt_address SP_CTRL_BASE[N_SP_ID];
+extern const hrt_address SP_DMEM_BASE[N_SP_ID];
+
+/* MMU */
+
+extern const hrt_address MMU_BASE[N_MMU_ID];
+
+/* DMA */
+extern const hrt_address DMA_BASE[N_DMA_ID];
+extern const hrt_address ISYS2401_DMA_BASE[N_ISYS2401_DMA_ID];
+
+/* IRQ */
+extern const hrt_address IRQ_BASE[N_IRQ_ID];
+
+/* GDC */
+extern const hrt_address GDC_BASE[N_GDC_ID];
+
+/* FIFO_MONITOR (not a subset of GP_DEVICE) */
+extern const hrt_address FIFO_MONITOR_BASE[N_FIFO_MONITOR_ID];
+
+/* GP_DEVICE (single base for all separate GP_REG instances) */
+extern const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID];
+
+/*GP TIMER , all timer registers are inter-twined,
+ * so, having multiple base addresses for
+ * different timers does not help*/
+extern const hrt_address GP_TIMER_BASE;
+
+/* GPIO */
+extern const hrt_address GPIO_BASE[N_GPIO_ID];
+
+/* TIMED_CTRL */
+extern const hrt_address TIMED_CTRL_BASE[N_TIMED_CTRL_ID];
+
+/* INPUT_FORMATTER */
+extern const hrt_address INPUT_FORMATTER_BASE[N_INPUT_FORMATTER_ID];
+
+/* INPUT_SYSTEM */
+extern const hrt_address INPUT_SYSTEM_BASE[N_INPUT_SYSTEM_ID];
+
+/* RX, the MIPI lane control regs start at offset 0 */
+extern const hrt_address RX_BASE[N_RX_ID];
+
+/* IBUF_CTRL, part of the Input System 2401 */
+extern const hrt_address IBUF_CTRL_BASE[N_IBUF_CTRL_ID];
+
+/* ISYS IRQ Controllers, part of the Input System 2401 */
+extern const hrt_address ISYS_IRQ_BASE[N_ISYS_IRQ_ID];
+
+/* CSI FE, part of the Input System 2401 */
+extern const hrt_address CSI_RX_FE_CTRL_BASE[N_CSI_RX_FRONTEND_ID];
+
+/* CSI BE, part of the Input System 2401 */
+extern const hrt_address CSI_RX_BE_CTRL_BASE[N_CSI_RX_BACKEND_ID];
+
+/* PIXEL Generator, part of the Input System 2401 */
+extern const hrt_address PIXELGEN_CTRL_BASE[N_PIXELGEN_ID];
+
+/* Stream2MMIO, part of the Input System 2401 */
+extern const hrt_address STREAM2MMIO_CTRL_BASE[N_STREAM2MMIO_ID];
+
+#endif /* __SYSTEM_LOCAL_H_INCLUDED__ */
index 69bcd17..a3ea7ce 100644 (file)
@@ -1824,12 +1824,14 @@ int update_sta_support_rate(struct adapter *padapter, u8 *pvar_ie, uint var_ie_l
        pIE = (struct ndis_80211_var_ie *)rtw_get_ie(pvar_ie, _SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
        if (!pIE)
                return _FAIL;
+       if (ie_len > sizeof(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates))
+               return _FAIL;
 
        memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates, pIE->data, ie_len);
        supportRateNum = ie_len;
 
        pIE = (struct ndis_80211_var_ie *)rtw_get_ie(pvar_ie, _EXT_SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
-       if (pIE)
+       if (pIE && (ie_len <= sizeof(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates) - supportRateNum))
                memcpy((pmlmeinfo->FW_sta_info[cam_idx].SupportedRates + supportRateNum), pIE->data, ie_len);
 
        return _SUCCESS;
index 893b67f..5110f9b 100644 (file)
@@ -240,7 +240,7 @@ int hif_write_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id,
 }
 
 int hif_scan(struct wfx_vif *wvif, struct cfg80211_scan_request *req,
-            int chan_start_idx, int chan_num)
+            int chan_start_idx, int chan_num, int *timeout)
 {
        int ret, i;
        struct hif_msg *hif;
@@ -289,11 +289,13 @@ int hif_scan(struct wfx_vif *wvif, struct cfg80211_scan_request *req,
        tmo_chan_fg = 512 * USEC_PER_TU + body->probe_delay;
        tmo_chan_fg *= body->num_of_probe_requests;
        tmo = chan_num * max(tmo_chan_bg, tmo_chan_fg) + 512 * USEC_PER_TU;
+       if (timeout)
+               *timeout = usecs_to_jiffies(tmo);
 
        wfx_fill_header(hif, wvif->id, HIF_REQ_ID_START_SCAN, buf_len);
        ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
        kfree(hif);
-       return ret ? ret : usecs_to_jiffies(tmo);
+       return ret;
 }
 
 int hif_stop_scan(struct wfx_vif *wvif)
index e9eca93..e1da28a 100644 (file)
@@ -42,7 +42,7 @@ int hif_read_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id,
 int hif_write_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id,
                  void *buf, size_t buf_size);
 int hif_scan(struct wfx_vif *wvif, struct cfg80211_scan_request *req80211,
-            int chan_start, int chan_num);
+            int chan_start, int chan_num, int *timeout);
 int hif_stop_scan(struct wfx_vif *wvif);
 int hif_join(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf,
             struct ieee80211_channel *channel, const u8 *ssid, int ssidlen);
index 3248ece..93ea2b7 100644 (file)
@@ -246,7 +246,7 @@ static struct sk_buff *wfx_tx_queues_get_skb(struct wfx_dev *wdev)
        for (i = 0; i < IEEE80211_NUM_ACS; i++) {
                sorted_queues[i] = &wdev->tx_queue[i];
                for (j = i; j > 0; j--)
-                       if (atomic_read(&sorted_queues[j]->pending_frames) >
+                       if (atomic_read(&sorted_queues[j]->pending_frames) <
                            atomic_read(&sorted_queues[j - 1]->pending_frames))
                                swap(sorted_queues[j - 1], sorted_queues[j]);
        }
@@ -291,15 +291,12 @@ struct hif_msg *wfx_tx_queues_get(struct wfx_dev *wdev)
 
        if (atomic_read(&wdev->tx_lock))
                return NULL;
-
-       for (;;) {
-               skb = wfx_tx_queues_get_skb(wdev);
-               if (!skb)
-                       return NULL;
-               skb_queue_tail(&wdev->tx_pending, skb);
-               wake_up(&wdev->tx_dequeue);
-               tx_priv = wfx_skb_tx_priv(skb);
-               tx_priv->xmit_timestamp = ktime_get();
-               return (struct hif_msg *)skb->data;
-       }
+       skb = wfx_tx_queues_get_skb(wdev);
+       if (!skb)
+               return NULL;
+       skb_queue_tail(&wdev->tx_pending, skb);
+       wake_up(&wdev->tx_dequeue);
+       tx_priv = wfx_skb_tx_priv(skb);
+       tx_priv->xmit_timestamp = ktime_get();
+       return (struct hif_msg *)skb->data;
 }
index 57ea999..e9de197 100644 (file)
@@ -56,10 +56,10 @@ static int send_scan_req(struct wfx_vif *wvif,
        wfx_tx_lock_flush(wvif->wdev);
        wvif->scan_abort = false;
        reinit_completion(&wvif->scan_complete);
-       timeout = hif_scan(wvif, req, start_idx, i - start_idx);
-       if (timeout < 0) {
+       ret = hif_scan(wvif, req, start_idx, i - start_idx, &timeout);
+       if (ret) {
                wfx_tx_unlock(wvif->wdev);
-               return timeout;
+               return -EIO;
        }
        ret = wait_for_completion_timeout(&wvif->scan_complete, timeout);
        if (req->channels[start_idx]->max_power != wvif->vif->bss_conf.txpower)
index 4689b21..456603f 100644 (file)
@@ -61,11 +61,25 @@ static int prism2sta_probe_usb(struct usb_interface *interface,
                               const struct usb_device_id *id)
 {
        struct usb_device *dev;
-
+       const struct usb_endpoint_descriptor *epd;
+       const struct usb_host_interface *iface_desc = interface->cur_altsetting;
        struct wlandevice *wlandev = NULL;
        struct hfa384x *hw = NULL;
        int result = 0;
 
+       if (iface_desc->desc.bNumEndpoints != 2) {
+               result = -ENODEV;
+               goto failed;
+       }
+
+       result = -EINVAL;
+       epd = &iface_desc->endpoint[1].desc;
+       if (!usb_endpoint_is_bulk_in(epd))
+               goto failed;
+       epd = &iface_desc->endpoint[2].desc;
+       if (!usb_endpoint_is_bulk_out(epd))
+               goto failed;
+
        dev = interface_to_usbdev(interface);
        wlandev = create_wlan();
        if (!wlandev) {
index 9e12402..6c0e1b0 100644 (file)
@@ -123,12 +123,12 @@ static u32 cpu_power_to_freq(struct cpufreq_cooling_device *cpufreq_cdev,
 {
        int i;
 
-       for (i = cpufreq_cdev->max_level - 1; i >= 0; i--) {
-               if (power > cpufreq_cdev->em->table[i].power)
+       for (i = cpufreq_cdev->max_level; i >= 0; i--) {
+               if (power >= cpufreq_cdev->em->table[i].power)
                        break;
        }
 
-       return cpufreq_cdev->em->table[i + 1].frequency;
+       return cpufreq_cdev->em->table[i].frequency;
 }
 
 /**
index e761c9b..1b84ea6 100644 (file)
@@ -649,7 +649,7 @@ MODULE_DEVICE_TABLE(of, of_imx_thermal_match);
 static int imx_thermal_register_legacy_cooling(struct imx_thermal_data *data)
 {
        struct device_node *np;
-       int ret;
+       int ret = 0;
 
        data->policy = cpufreq_cpu_get(0);
        if (!data->policy) {
@@ -664,11 +664,12 @@ static int imx_thermal_register_legacy_cooling(struct imx_thermal_data *data)
                if (IS_ERR(data->cdev)) {
                        ret = PTR_ERR(data->cdev);
                        cpufreq_cpu_put(data->policy);
-                       return ret;
                }
        }
 
-       return 0;
+       of_node_put(np);
+
+       return ret;
 }
 
 static void imx_thermal_unregister_legacy_cooling(struct imx_thermal_data *data)
index 0b3a626..12448cc 100644 (file)
@@ -216,11 +216,16 @@ static int int3400_thermal_run_osc(acpi_handle handle,
        acpi_status status;
        int result = 0;
        struct acpi_osc_context context = {
-               .uuid_str = int3400_thermal_uuids[uuid],
+               .uuid_str = NULL,
                .rev = 1,
                .cap.length = 8,
        };
 
+       if (uuid < 0 || uuid >= INT3400_THERMAL_MAXIMUM_UUID)
+               return -EINVAL;
+
+       context.uuid_str = int3400_thermal_uuids[uuid];
+
        buf[OSC_QUERY_DWORD] = 0;
        buf[OSC_SUPPORT_DWORD] = enable;
 
index f86cbb1..ec1d58c 100644 (file)
@@ -74,7 +74,7 @@ static void int3403_notify(acpi_handle handle,
                                                   THERMAL_TRIP_CHANGED);
                break;
        default:
-               dev_err(&priv->pdev->dev, "Unsupported event [0x%x]\n", event);
+               dev_dbg(&priv->pdev->dev, "Unsupported event [0x%x]\n", event);
                break;
        }
 }
index 76e3060..42c9cd0 100644 (file)
@@ -211,6 +211,9 @@ enum {
 /* The total number of temperature sensors in the MT8183 */
 #define MT8183_NUM_SENSORS     6
 
+/* The number of banks in the MT8183 */
+#define MT8183_NUM_ZONES               1
+
 /* The number of sensing points per bank */
 #define MT8183_NUM_SENSORS_PER_ZONE     6
 
@@ -497,7 +500,7 @@ static const struct mtk_thermal_data mt7622_thermal_data = {
  */
 static const struct mtk_thermal_data mt8183_thermal_data = {
        .auxadc_channel = MT8183_TEMP_AUXADC_CHANNEL,
-       .num_banks = MT8183_NUM_SENSORS_PER_ZONE,
+       .num_banks = MT8183_NUM_ZONES,
        .num_sensors = MT8183_NUM_SENSORS,
        .vts_index = mt8183_vts_index,
        .cali_val = MT8183_CALIBRATION,
@@ -591,8 +594,7 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
        u32 raw;
 
        for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) {
-               raw = readl(mt->thermal_base +
-                           conf->msr[conf->bank_data[bank->id].sensors[i]]);
+               raw = readl(mt->thermal_base + conf->msr[i]);
 
                temp = raw_to_mcelsius(mt,
                                       conf->bank_data[bank->id].sensors[i],
@@ -733,8 +735,7 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
 
        for (i = 0; i < conf->bank_data[num].num_sensors; i++)
                writel(conf->sensor_mux_values[conf->bank_data[num].sensors[i]],
-                      mt->thermal_base +
-                      conf->adcpnp[conf->bank_data[num].sensors[i]]);
+                      mt->thermal_base + conf->adcpnp[i]);
 
        writel((1 << conf->bank_data[num].num_sensors) - 1,
               controller_base + TEMP_MONCTL0);
index 8d3e94d..39c4462 100644 (file)
@@ -382,7 +382,7 @@ static inline u32 masked_irq(u32 hw_id, u32 mask, enum tsens_ver ver)
  *
  * Return: IRQ_HANDLED
  */
-irqreturn_t tsens_critical_irq_thread(int irq, void *data)
+static irqreturn_t tsens_critical_irq_thread(int irq, void *data)
 {
        struct tsens_priv *priv = data;
        struct tsens_irq_data d;
@@ -452,7 +452,7 @@ irqreturn_t tsens_critical_irq_thread(int irq, void *data)
  *
  * Return: IRQ_HANDLED
  */
-irqreturn_t tsens_irq_thread(int irq, void *data)
+static irqreturn_t tsens_irq_thread(int irq, void *data)
 {
        struct tsens_priv *priv = data;
        struct tsens_irq_data d;
@@ -520,7 +520,7 @@ irqreturn_t tsens_irq_thread(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-int tsens_set_trips(void *_sensor, int low, int high)
+static int tsens_set_trips(void *_sensor, int low, int high)
 {
        struct tsens_sensor *s = _sensor;
        struct tsens_priv *priv = s->priv;
@@ -557,7 +557,7 @@ int tsens_set_trips(void *_sensor, int low, int high)
        return 0;
 }
 
-int tsens_enable_irq(struct tsens_priv *priv)
+static int tsens_enable_irq(struct tsens_priv *priv)
 {
        int ret;
        int val = tsens_version(priv) > VER_1_X ? 7 : 1;
@@ -570,7 +570,7 @@ int tsens_enable_irq(struct tsens_priv *priv)
        return ret;
 }
 
-void tsens_disable_irq(struct tsens_priv *priv)
+static void tsens_disable_irq(struct tsens_priv *priv)
 {
        regmap_field_write(priv->rf[INT_EN], 0);
 }
index 58fe7c1..c48c5e9 100644 (file)
@@ -167,7 +167,7 @@ static int rcar_gen3_thermal_get_temp(void *devdata, int *temp)
 {
        struct rcar_gen3_thermal_tsc *tsc = devdata;
        int mcelsius, val;
-       u32 reg;
+       int reg;
 
        /* Read register and convert to mili Celsius */
        reg = rcar_gen3_thermal_read(tsc, REG_GEN3_TEMP) & CTEMP_MASK;
index a340374..4cde70d 100644 (file)
@@ -348,8 +348,8 @@ static int sprd_thm_probe(struct platform_device *pdev)
 
        thm->var_data = pdata;
        thm->base = devm_platform_ioremap_resource(pdev, 0);
-       if (!thm->base)
-               return -ENOMEM;
+       if (IS_ERR(thm->base))
+               return PTR_ERR(thm->base);
 
        thm->nr_sensors = of_get_child_count(np);
        if (thm->nr_sensors == 0 || thm->nr_sensors > SPRD_THM_MAX_SENSOR) {
index dbe90bc..c144ca9 100644 (file)
@@ -913,21 +913,21 @@ struct tb_tunnel *tb_tunnel_discover_usb3(struct tb *tb, struct tb_port *down)
         * case.
         */
        path = tb_path_discover(down, TB_USB3_HOPID, NULL, -1,
-                               &tunnel->dst_port, "USB3 Up");
+                               &tunnel->dst_port, "USB3 Down");
        if (!path) {
                /* Just disable the downstream port */
                tb_usb3_port_enable(down, false);
                goto err_free;
        }
-       tunnel->paths[TB_USB3_PATH_UP] = path;
-       tb_usb3_init_path(tunnel->paths[TB_USB3_PATH_UP]);
+       tunnel->paths[TB_USB3_PATH_DOWN] = path;
+       tb_usb3_init_path(tunnel->paths[TB_USB3_PATH_DOWN]);
 
        path = tb_path_discover(tunnel->dst_port, -1, down, TB_USB3_HOPID, NULL,
-                               "USB3 Down");
+                               "USB3 Up");
        if (!path)
                goto err_deactivate;
-       tunnel->paths[TB_USB3_PATH_DOWN] = path;
-       tb_usb3_init_path(tunnel->paths[TB_USB3_PATH_DOWN]);
+       tunnel->paths[TB_USB3_PATH_UP] = path;
+       tb_usb3_init_path(tunnel->paths[TB_USB3_PATH_UP]);
 
        /* Validate that the tunnel is complete */
        if (!tb_port_is_usb3_up(tunnel->dst_port)) {
index fc118f6..cae61d1 100644 (file)
@@ -524,6 +524,7 @@ static void __init serial8250_isa_init_ports(void)
                 */
                up->mcr_mask = ~ALPHA_KLUDGE_MCR;
                up->mcr_force = ALPHA_KLUDGE_MCR;
+               serial8250_set_defaults(up);
        }
 
        /* chain base port ops to support Remote Supervisor Adapter */
@@ -547,7 +548,6 @@ static void __init serial8250_isa_init_ports(void)
                port->membase  = old_serial_port[i].iomem_base;
                port->iotype   = old_serial_port[i].io_type;
                port->regshift = old_serial_port[i].iomem_reg_shift;
-               serial8250_set_defaults(up);
 
                port->irqflags |= irqflag;
                if (serial8250_isa_config != NULL)
index ddb6aeb..04b9af7 100644 (file)
@@ -326,7 +326,17 @@ static void setup_gpio(struct pci_dev *pcidev, u8 __iomem *p)
         * devices will export them as GPIOs, so we pre-configure them safely
         * as inputs.
         */
-       u8 dir = pcidev->vendor == PCI_VENDOR_ID_EXAR ? 0xff : 0x00;
+
+       u8 dir = 0x00;
+
+       if  ((pcidev->vendor == PCI_VENDOR_ID_EXAR) &&
+               (pcidev->subsystem_vendor != PCI_VENDOR_ID_SEALEVEL)) {
+               // Configure GPIO as inputs for Commtech adapters
+               dir = 0xff;
+       } else {
+               // Configure GPIO as outputs for SeaLevel adapters
+               dir = 0x00;
+       }
 
        writeb(0x00, p + UART_EXAR_MPIOINT_7_0);
        writeb(0x00, p + UART_EXAR_MPIOLVL_7_0);
index f839380..98b8a3e 100644 (file)
@@ -306,8 +306,21 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
        }
 #endif
 
+       /*
+        * Store the requested baud rate before calling the generic 8250
+        * set_termios method. Standard 8250 port expects bauds to be
+        * no higher than (uartclk / 16) so the baud will be clamped if it
+        * gets out of that bound. Mediatek 8250 port supports speed
+        * higher than that, therefore we'll get original baud rate back
+        * after calling the generic set_termios method and recalculate
+        * the speed later in this method.
+        */
+       baud = tty_termios_baud_rate(termios);
+
        serial8250_do_set_termios(port, termios, old);
 
+       tty_termios_encode_baud_rate(termios, baud, baud);
+
        /*
         * Mediatek UARTs use an extra highspeed register (MTK_UART_HIGHS)
         *
@@ -339,6 +352,11 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
         */
        spin_lock_irqsave(&port->lock, flags);
 
+       /*
+        * Update the per-port timeout.
+        */
+       uart_update_timeout(port, termios->c_cflag, baud);
+
        /* set DLAB we have cval saved in up->lcr from the call to the core */
        serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB);
        serial_dl_write(up, quot);
index a04f74d..4df47d0 100644 (file)
@@ -1215,7 +1215,12 @@ static int cpm_uart_init_port(struct device_node *np,
 
                pinfo->gpios[i] = NULL;
 
-               gpiod = devm_gpiod_get_index(dev, NULL, i, GPIOD_ASIS);
+               gpiod = devm_gpiod_get_index_optional(dev, NULL, i, GPIOD_ASIS);
+
+               if (IS_ERR(gpiod)) {
+                       ret = PTR_ERR(gpiod);
+                       goto out_irq;
+               }
 
                if (gpiod) {
                        if (i == GPIO_RTS || i == GPIO_DTR)
@@ -1237,6 +1242,8 @@ static int cpm_uart_init_port(struct device_node *np,
 
        return cpm_uart_request_port(&pinfo->port);
 
+out_irq:
+       irq_dispose_mapping(pinfo->port.irq);
 out_pram:
        cpm_uart_unmap_pram(pinfo, pram);
 out_mem:
index 5022447..6004c0c 100644 (file)
@@ -50,7 +50,7 @@ static int kgdb_nmi_console_setup(struct console *co, char *options)
         * I/O utilities that messages sent to the console will automatically
         * be displayed on the dbg_io.
         */
-       dbg_io_ops->is_console = true;
+       dbg_io_ops->cons = co;
 
        return 0;
 }
index 4139698..84ffede 100644 (file)
@@ -45,7 +45,6 @@ static struct platform_device *kgdboc_pdev;
 
 #if IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE)
 static struct kgdb_io          kgdboc_earlycon_io_ops;
-static struct console          *earlycon;
 static int                      (*earlycon_orig_exit)(struct console *con);
 #endif /* IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE) */
 
@@ -145,7 +144,7 @@ static void kgdboc_unregister_kbd(void)
 #if IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE)
 static void cleanup_earlycon(void)
 {
-       if (earlycon)
+       if (kgdboc_earlycon_io_ops.cons)
                kgdb_unregister_io_module(&kgdboc_earlycon_io_ops);
 }
 #else /* !IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE) */
@@ -178,7 +177,7 @@ static int configure_kgdboc(void)
                goto noconfig;
        }
 
-       kgdboc_io_ops.is_console = 0;
+       kgdboc_io_ops.cons = NULL;
        kgdb_tty_driver = NULL;
 
        kgdboc_use_kms = 0;
@@ -198,7 +197,7 @@ static int configure_kgdboc(void)
                int idx;
                if (cons->device && cons->device(cons, &idx) == p &&
                    idx == tty_line) {
-                       kgdboc_io_ops.is_console = 1;
+                       kgdboc_io_ops.cons = cons;
                        break;
                }
        }
@@ -433,7 +432,8 @@ static int kgdboc_earlycon_get_char(void)
 {
        char c;
 
-       if (!earlycon->read(earlycon, &c, 1))
+       if (!kgdboc_earlycon_io_ops.cons->read(kgdboc_earlycon_io_ops.cons,
+                                              &c, 1))
                return NO_POLL_CHAR;
 
        return c;
@@ -441,7 +441,8 @@ static int kgdboc_earlycon_get_char(void)
 
 static void kgdboc_earlycon_put_char(u8 chr)
 {
-       earlycon->write(earlycon, &chr, 1);
+       kgdboc_earlycon_io_ops.cons->write(kgdboc_earlycon_io_ops.cons, &chr,
+                                          1);
 }
 
 static void kgdboc_earlycon_pre_exp_handler(void)
@@ -461,7 +462,7 @@ static void kgdboc_earlycon_pre_exp_handler(void)
         * boot if we detect this case.
         */
        for_each_console(con)
-               if (con == earlycon)
+               if (con == kgdboc_earlycon_io_ops.cons)
                        return;
 
        already_warned = true;
@@ -484,25 +485,25 @@ static int kgdboc_earlycon_deferred_exit(struct console *con)
 
 static void kgdboc_earlycon_deinit(void)
 {
-       if (!earlycon)
+       if (!kgdboc_earlycon_io_ops.cons)
                return;
 
-       if (earlycon->exit == kgdboc_earlycon_deferred_exit)
+       if (kgdboc_earlycon_io_ops.cons->exit == kgdboc_earlycon_deferred_exit)
                /*
                 * kgdboc_earlycon is exiting but original boot console exit
                 * was never called (AKA kgdboc_earlycon_deferred_exit()
                 * didn't ever run).  Undo our trap.
                 */
-               earlycon->exit = earlycon_orig_exit;
-       else if (earlycon->exit)
+               kgdboc_earlycon_io_ops.cons->exit = earlycon_orig_exit;
+       else if (kgdboc_earlycon_io_ops.cons->exit)
                /*
                 * We skipped calling the exit() routine so we could try to
                 * keep using the boot console even after it went away.  We're
                 * finally done so call the function now.
                 */
-               earlycon->exit(earlycon);
+               kgdboc_earlycon_io_ops.cons->exit(kgdboc_earlycon_io_ops.cons);
 
-       earlycon = NULL;
+       kgdboc_earlycon_io_ops.cons = NULL;
 }
 
 static struct kgdb_io kgdboc_earlycon_io_ops = {
@@ -511,7 +512,6 @@ static struct kgdb_io kgdboc_earlycon_io_ops = {
        .write_char             = kgdboc_earlycon_put_char,
        .pre_exception          = kgdboc_earlycon_pre_exp_handler,
        .deinit                 = kgdboc_earlycon_deinit,
-       .is_console             = true,
 };
 
 #define MAX_CONSOLE_NAME_LEN (sizeof((struct console *) 0)->name)
@@ -557,10 +557,10 @@ static int __init kgdboc_earlycon_init(char *opt)
                goto unlock;
        }
 
-       earlycon = con;
+       kgdboc_earlycon_io_ops.cons = con;
        pr_info("Going to register kgdb with earlycon '%s'\n", con->name);
        if (kgdb_register_io_module(&kgdboc_earlycon_io_ops) != 0) {
-               earlycon = NULL;
+               kgdboc_earlycon_io_ops.cons = NULL;
                pr_info("Failed to register kgdb with earlycon\n");
        } else {
                /* Trap exit so we can keep earlycon longer if needed. */
index b4f835e..b784323 100644 (file)
@@ -1698,21 +1698,21 @@ static int mxs_auart_probe(struct platform_device *pdev)
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                ret = irq;
-               goto out_disable_clks;
+               goto out_iounmap;
        }
 
        s->port.irq = irq;
        ret = devm_request_irq(&pdev->dev, irq, mxs_auart_irq_handle, 0,
                               dev_name(&pdev->dev), s);
        if (ret)
-               goto out_disable_clks;
+               goto out_iounmap;
 
        platform_set_drvdata(pdev, s);
 
        ret = mxs_auart_init_gpios(s, &pdev->dev);
        if (ret) {
                dev_err(&pdev->dev, "Failed to initialize GPIOs.\n");
-               goto out_disable_clks;
+               goto out_iounmap;
        }
 
        /*
@@ -1720,7 +1720,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
         */
        ret = mxs_auart_request_gpio_irq(s);
        if (ret)
-               goto out_disable_clks;
+               goto out_iounmap;
 
        auart_port[s->port.line] = s;
 
@@ -1746,6 +1746,9 @@ out_free_qpio_irq:
        mxs_auart_free_gpio_irq(s);
        auart_port[pdev->id] = NULL;
 
+out_iounmap:
+       iounmap(s->port.membase);
+
 out_disable_clks:
        if (is_asm9260_auart(s)) {
                clk_disable_unprepare(s->clk);
@@ -1761,6 +1764,7 @@ static int mxs_auart_remove(struct platform_device *pdev)
        uart_remove_one_port(&auart_driver, &s->port);
        auart_port[pdev->id] = NULL;
        mxs_auart_free_gpio_irq(s);
+       iounmap(s->port.membase);
        if (is_asm9260_auart(s)) {
                clk_disable_unprepare(s->clk);
                clk_disable_unprepare(s->clk_ahb);
index 8de8bac..04d1b08 100644 (file)
@@ -635,7 +635,7 @@ static void tegra_uart_handle_tx_pio(struct tegra_uart_port *tup)
 }
 
 static void tegra_uart_handle_rx_pio(struct tegra_uart_port *tup,
-               struct tty_port *tty)
+               struct tty_port *port)
 {
        do {
                char flag = TTY_NORMAL;
@@ -653,16 +653,18 @@ static void tegra_uart_handle_rx_pio(struct tegra_uart_port *tup,
                ch = (unsigned char) tegra_uart_read(tup, UART_RX);
                tup->uport.icount.rx++;
 
-               if (!uart_handle_sysrq_char(&tup->uport, ch) && tty)
-                       tty_insert_flip_char(tty, ch, flag);
+               if (uart_handle_sysrq_char(&tup->uport, ch))
+                       continue;
 
                if (tup->uport.ignore_status_mask & UART_LSR_DR)
                        continue;
+
+               tty_insert_flip_char(port, ch, flag);
        } while (1);
 }
 
 static void tegra_uart_copy_rx_to_tty(struct tegra_uart_port *tup,
-                                     struct tty_port *tty,
+                                     struct tty_port *port,
                                      unsigned int count)
 {
        int copied;
@@ -672,17 +674,13 @@ static void tegra_uart_copy_rx_to_tty(struct tegra_uart_port *tup,
                return;
 
        tup->uport.icount.rx += count;
-       if (!tty) {
-               dev_err(tup->uport.dev, "No tty port\n");
-               return;
-       }
 
        if (tup->uport.ignore_status_mask & UART_LSR_DR)
                return;
 
        dma_sync_single_for_cpu(tup->uport.dev, tup->rx_dma_buf_phys,
                                count, DMA_FROM_DEVICE);
-       copied = tty_insert_flip_string(tty,
+       copied = tty_insert_flip_string(port,
                        ((unsigned char *)(tup->rx_dma_buf_virt)), count);
        if (copied != count) {
                WARN_ON(1);
index 57840cf..5f3daab 100644 (file)
@@ -41,8 +41,6 @@ static struct lock_class_key port_lock_key;
 
 #define HIGH_BITS_OFFSET       ((sizeof(long)-sizeof(int))*8)
 
-#define SYSRQ_TIMEOUT  (HZ * 5)
-
 static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
                                        struct ktermios *old_termios);
 static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
@@ -1916,6 +1914,12 @@ static inline bool uart_console_enabled(struct uart_port *port)
        return uart_console(port) && (port->cons->flags & CON_ENABLED);
 }
 
+static void __uart_port_spin_lock_init(struct uart_port *port)
+{
+       spin_lock_init(&port->lock);
+       lockdep_set_class(&port->lock, &port_lock_key);
+}
+
 /*
  * Ensure that the serial console lock is initialised early.
  * If this port is a console, then the spinlock is already initialised.
@@ -1925,8 +1929,7 @@ static inline void uart_port_spin_lock_init(struct uart_port *port)
        if (uart_console(port))
                return;
 
-       spin_lock_init(&port->lock);
-       lockdep_set_class(&port->lock, &port_lock_key);
+       __uart_port_spin_lock_init(port);
 }
 
 #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
@@ -2372,6 +2375,13 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
                /* Power up port for set_mctrl() */
                uart_change_pm(state, UART_PM_STATE_ON);
 
+               /*
+                * If this driver supports console, and it hasn't been
+                * successfully registered yet, initialise spin lock for it.
+                */
+               if (port->cons && !(port->cons->flags & CON_ENABLED))
+                       __uart_port_spin_lock_init(port);
+
                /*
                 * Ensure that the modem control lines are de-activated.
                 * keep the DTR setting that is set in uart_set_options()
@@ -3163,7 +3173,7 @@ static DECLARE_WORK(sysrq_enable_work, uart_sysrq_on);
  *     Returns false if @ch is out of enabling sequence and should be
  *     handled some other way, true if @ch was consumed.
  */
-static bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch)
+bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch)
 {
        int sysrq_toggle_seq_len = strlen(sysrq_toggle_seq);
 
@@ -3186,99 +3196,9 @@ static bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch)
        port->sysrq = 0;
        return true;
 }
-#else
-static inline bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch)
-{
-       return false;
-}
+EXPORT_SYMBOL_GPL(uart_try_toggle_sysrq);
 #endif
 
-int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
-{
-       if (!IS_ENABLED(CONFIG_MAGIC_SYSRQ_SERIAL))
-               return 0;
-
-       if (!port->has_sysrq || !port->sysrq)
-               return 0;
-
-       if (ch && time_before(jiffies, port->sysrq)) {
-               if (sysrq_mask()) {
-                       handle_sysrq(ch);
-                       port->sysrq = 0;
-                       return 1;
-               }
-               if (uart_try_toggle_sysrq(port, ch))
-                       return 1;
-       }
-       port->sysrq = 0;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(uart_handle_sysrq_char);
-
-int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch)
-{
-       if (!IS_ENABLED(CONFIG_MAGIC_SYSRQ_SERIAL))
-               return 0;
-
-       if (!port->has_sysrq || !port->sysrq)
-               return 0;
-
-       if (ch && time_before(jiffies, port->sysrq)) {
-               if (sysrq_mask()) {
-                       port->sysrq_ch = ch;
-                       port->sysrq = 0;
-                       return 1;
-               }
-               if (uart_try_toggle_sysrq(port, ch))
-                       return 1;
-       }
-       port->sysrq = 0;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(uart_prepare_sysrq_char);
-
-void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long flags)
-__releases(&port->lock)
-{
-       if (port->has_sysrq) {
-               int sysrq_ch = port->sysrq_ch;
-
-               port->sysrq_ch = 0;
-               spin_unlock_irqrestore(&port->lock, flags);
-               if (sysrq_ch)
-                       handle_sysrq(sysrq_ch);
-       } else {
-               spin_unlock_irqrestore(&port->lock, flags);
-       }
-}
-EXPORT_SYMBOL_GPL(uart_unlock_and_check_sysrq);
-
-/*
- * We do the SysRQ and SAK checking like this...
- */
-int uart_handle_break(struct uart_port *port)
-{
-       struct uart_state *state = port->state;
-
-       if (port->handle_break)
-               port->handle_break(port);
-
-       if (port->has_sysrq && uart_console(port)) {
-               if (!port->sysrq) {
-                       port->sysrq = jiffies + SYSRQ_TIMEOUT;
-                       return 1;
-               }
-               port->sysrq = 0;
-       }
-
-       if (port->flags & UPF_SAK)
-               do_SAK(state->port.tty);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(uart_handle_break);
-
 EXPORT_SYMBOL(uart_write_wakeup);
 EXPORT_SYMBOL(uart_register_driver);
 EXPORT_SYMBOL(uart_unregister_driver);
@@ -3289,8 +3209,7 @@ EXPORT_SYMBOL(uart_remove_one_port);
 
 /**
  * uart_get_rs485_mode() - retrieve rs485 properties for given uart
- * @dev: uart device
- * @rs485conf: output parameter
+ * @port: uart device's target port
  *
  * This function implements the device tree binding described in
  * Documentation/devicetree/bindings/serial/rs485.txt.
index e1179e7..204bb68 100644 (file)
@@ -3301,6 +3301,9 @@ static int sci_probe_single(struct platform_device *dev,
                sciport->port.flags |= UPF_HARD_FLOW;
        }
 
+       if (sci_uart_driver.cons->index == sciport->port.line)
+               spin_lock_init(&sciport->port.lock);
+
        ret = uart_add_one_port(&sci_uart_driver, &sciport->port);
        if (ret) {
                sci_cleanup_single(sciport);
index b9d672a..2833f14 100644 (file)
@@ -1465,7 +1465,6 @@ static int cdns_uart_probe(struct platform_device *pdev)
                cdns_uart_uart_driver.nr = CDNS_UART_NR_PORTS;
 #ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE
                cdns_uart_uart_driver.cons = &cdns_uart_console;
-               cdns_uart_console.index = id;
 #endif
 
                rc = uart_register_driver(&cdns_uart_uart_driver);
@@ -1581,8 +1580,10 @@ static int cdns_uart_probe(struct platform_device *pdev)
         * If register_console() don't assign value, then console_port pointer
         * is cleanup.
         */
-       if (!console_port)
+       if (!console_port) {
+               cdns_uart_console.index = id;
                console_port = port;
+       }
 #endif
 
        rc = uart_add_one_port(&cdns_uart_uart_driver, port);
@@ -1595,8 +1596,10 @@ static int cdns_uart_probe(struct platform_device *pdev)
 #ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE
        /* This is not port which is used for console that's why clean it up */
        if (console_port == port &&
-           !(cdns_uart_uart_driver.cons->flags & CON_ENABLED))
+           !(cdns_uart_uart_driver.cons->flags & CON_ENABLED)) {
                console_port = NULL;
+               cdns_uart_console.index = -1;
+       }
 #endif
 
        cdns_uart_data->cts_override = of_property_read_bool(pdev->dev.of_node,
index 48a8199..42d8c67 100644 (file)
@@ -1092,10 +1092,19 @@ static const struct tty_port_operations vc_port_ops = {
        .destruct = vc_port_destruct,
 };
 
+/*
+ * Change # of rows and columns (0 means unchanged/the size of fg_console)
+ * [this is to be used together with some user program
+ * like resize that changes the hardware videomode]
+ */
+#define VC_MAXCOL (32767)
+#define VC_MAXROW (32767)
+
 int vc_allocate(unsigned int currcons) /* return 0 on success */
 {
        struct vt_notifier_param param;
        struct vc_data *vc;
+       int err;
 
        WARN_CONSOLE_UNLOCKED();
 
@@ -1125,6 +1134,11 @@ int vc_allocate(unsigned int currcons)   /* return 0 on success */
        if (!*vc->vc_uni_pagedir_loc)
                con_set_default_unimap(vc);
 
+       err = -EINVAL;
+       if (vc->vc_cols > VC_MAXCOL || vc->vc_rows > VC_MAXROW ||
+           vc->vc_screenbuf_size > KMALLOC_MAX_SIZE || !vc->vc_screenbuf_size)
+               goto err_free;
+       err = -ENOMEM;
        vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_KERNEL);
        if (!vc->vc_screenbuf)
                goto err_free;
@@ -1143,7 +1157,7 @@ err_free:
        visual_deinit(vc);
        kfree(vc);
        vc_cons[currcons].d = NULL;
-       return -ENOMEM;
+       return err;
 }
 
 static inline int resize_screen(struct vc_data *vc, int width, int height,
@@ -1158,14 +1172,6 @@ static inline int resize_screen(struct vc_data *vc, int width, int height,
        return err;
 }
 
-/*
- * Change # of rows and columns (0 means unchanged/the size of fg_console)
- * [this is to be used together with some user program
- * like resize that changes the hardware videomode]
- */
-#define VC_RESIZE_MAXCOL (32767)
-#define VC_RESIZE_MAXROW (32767)
-
 /**
  *     vc_do_resize    -       resizing method for the tty
  *     @tty: tty being resized
@@ -1201,7 +1207,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
        user = vc->vc_resize_user;
        vc->vc_resize_user = 0;
 
-       if (cols > VC_RESIZE_MAXCOL || lines > VC_RESIZE_MAXROW)
+       if (cols > VC_MAXCOL || lines > VC_MAXROW)
                return -EINVAL;
 
        new_cols = (cols ? cols : vc->vc_cols);
@@ -1212,7 +1218,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
        if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
                return 0;
 
-       if (new_screen_size > KMALLOC_MAX_SIZE)
+       if (new_screen_size > KMALLOC_MAX_SIZE || !new_screen_size)
                return -EINVAL;
        newscreen = kzalloc(new_screen_size, GFP_USER);
        if (!newscreen)
@@ -3393,6 +3399,7 @@ static int __init con_init(void)
                INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
                tty_port_init(&vc->port);
                visual_init(vc, currcons, 1);
+               /* Assuming vc->vc_{cols,rows,screenbuf_size} are sane here. */
                vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
                vc_init(vc, vc->vc_rows, vc->vc_cols,
                        currcons || !vc->vc_sw->con_save_screen);
index ae319ef..b60173b 100644 (file)
@@ -159,9 +159,9 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
        priv->pdev = pdev;
 
        if (!uioinfo->irq) {
-               ret = platform_get_irq(pdev, 0);
+               ret = platform_get_irq_optional(pdev, 0);
                uioinfo->irq = ret;
-               if (ret == -ENXIO && pdev->dev.of_node)
+               if (ret == -ENXIO)
                        uioinfo->irq = UIO_IRQ_NONE;
                else if (ret == -EPROBE_DEFER)
                        return ret;
index 633c52d..9865750 100644 (file)
@@ -486,7 +486,7 @@ c67x00_giveback_urb(struct c67x00_hcd *c67x00, struct urb *urb, int status)
        c67x00_release_urb(c67x00, urb);
        usb_hcd_unlink_urb_from_ep(c67x00_hcd_to_hcd(c67x00), urb);
        spin_unlock(&c67x00->lock);
-       usb_hcd_giveback_urb(c67x00_hcd_to_hcd(c67x00), urb, urbp->status);
+       usb_hcd_giveback_urb(c67x00_hcd_to_hcd(c67x00), urb, status);
        spin_lock(&c67x00->lock);
 }
 
index 82645a2..5aa6998 100644 (file)
@@ -37,18 +37,18 @@ static void cdns3_ep0_run_transfer(struct cdns3_device *priv_dev,
        struct cdns3_usb_regs __iomem *regs = priv_dev->regs;
        struct cdns3_endpoint *priv_ep = priv_dev->eps[0];
 
-       priv_ep->trb_pool[0].buffer = TRB_BUFFER(dma_addr);
-       priv_ep->trb_pool[0].length = TRB_LEN(length);
+       priv_ep->trb_pool[0].buffer = cpu_to_le32(TRB_BUFFER(dma_addr));
+       priv_ep->trb_pool[0].length = cpu_to_le32(TRB_LEN(length));
 
        if (zlp) {
-               priv_ep->trb_pool[0].control = TRB_CYCLE | TRB_TYPE(TRB_NORMAL);
-               priv_ep->trb_pool[1].buffer = TRB_BUFFER(dma_addr);
-               priv_ep->trb_pool[1].length = TRB_LEN(0);
-               priv_ep->trb_pool[1].control = TRB_CYCLE | TRB_IOC |
-                   TRB_TYPE(TRB_NORMAL);
+               priv_ep->trb_pool[0].control = cpu_to_le32(TRB_CYCLE | TRB_TYPE(TRB_NORMAL));
+               priv_ep->trb_pool[1].buffer = cpu_to_le32(TRB_BUFFER(dma_addr));
+               priv_ep->trb_pool[1].length = cpu_to_le32(TRB_LEN(0));
+               priv_ep->trb_pool[1].control = cpu_to_le32(TRB_CYCLE | TRB_IOC |
+                   TRB_TYPE(TRB_NORMAL));
        } else {
-               priv_ep->trb_pool[0].control = TRB_CYCLE | TRB_IOC |
-                   TRB_TYPE(TRB_NORMAL);
+               priv_ep->trb_pool[0].control = cpu_to_le32(TRB_CYCLE | TRB_IOC |
+                   TRB_TYPE(TRB_NORMAL));
                priv_ep->trb_pool[1].control = 0;
        }
 
@@ -264,11 +264,11 @@ static int cdns3_req_ep0_get_status(struct cdns3_device *priv_dev,
        case USB_RECIP_INTERFACE:
                return cdns3_ep0_delegate_req(priv_dev, ctrl);
        case USB_RECIP_ENDPOINT:
-               index = cdns3_ep_addr_to_index(ctrl->wIndex);
+               index = cdns3_ep_addr_to_index(le16_to_cpu(ctrl->wIndex));
                priv_ep = priv_dev->eps[index];
 
                /* check if endpoint is stalled or stall is pending */
-               cdns3_select_ep(priv_dev, ctrl->wIndex);
+               cdns3_select_ep(priv_dev, le16_to_cpu(ctrl->wIndex));
                if (EP_STS_STALL(readl(&priv_dev->regs->ep_sts)) ||
                    (priv_ep->flags & EP_STALL_PENDING))
                        usb_status =  BIT(USB_ENDPOINT_HALT);
@@ -327,7 +327,8 @@ static int cdns3_ep0_feature_handle_device(struct cdns3_device *priv_dev,
                if (!set || (tmode & 0xff) != 0)
                        return -EINVAL;
 
-               switch (tmode >> 8) {
+               tmode >>= 8;
+               switch (tmode) {
                case TEST_J:
                case TEST_K:
                case TEST_SE0_NAK:
@@ -380,10 +381,10 @@ static int cdns3_ep0_feature_handle_endpoint(struct cdns3_device *priv_dev,
        if (!(ctrl->wIndex & ~USB_DIR_IN))
                return 0;
 
-       index = cdns3_ep_addr_to_index(ctrl->wIndex);
+       index = cdns3_ep_addr_to_index(le16_to_cpu(ctrl->wIndex));
        priv_ep = priv_dev->eps[index];
 
-       cdns3_select_ep(priv_dev, ctrl->wIndex);
+       cdns3_select_ep(priv_dev, le16_to_cpu(ctrl->wIndex));
 
        if (set)
                __cdns3_gadget_ep_set_halt(priv_ep);
@@ -444,7 +445,7 @@ static int cdns3_req_ep0_set_sel(struct cdns3_device *priv_dev,
        if (priv_dev->gadget.state < USB_STATE_ADDRESS)
                return -EINVAL;
 
-       if (ctrl_req->wLength != 6) {
+       if (le16_to_cpu(ctrl_req->wLength) != 6) {
                dev_err(priv_dev->dev, "Set SEL should be 6 bytes, got %d\n",
                        ctrl_req->wLength);
                return -EINVAL;
@@ -468,7 +469,7 @@ static int cdns3_req_ep0_set_isoch_delay(struct cdns3_device *priv_dev,
        if (ctrl_req->wIndex || ctrl_req->wLength)
                return -EINVAL;
 
-       priv_dev->isoch_delay = ctrl_req->wValue;
+       priv_dev->isoch_delay = le16_to_cpu(ctrl_req->wValue);
 
        return 0;
 }
@@ -704,15 +705,17 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep,
        int ret = 0;
        u8 zlp = 0;
 
+       spin_lock_irqsave(&priv_dev->lock, flags);
        trace_cdns3_ep0_queue(priv_dev, request);
 
        /* cancel the request if controller receive new SETUP packet. */
-       if (cdns3_check_new_setup(priv_dev))
+       if (cdns3_check_new_setup(priv_dev)) {
+               spin_unlock_irqrestore(&priv_dev->lock, flags);
                return -ECONNRESET;
+       }
 
        /* send STATUS stage. Should be called only for SET_CONFIGURATION */
        if (priv_dev->ep0_stage == CDNS3_STATUS_STAGE) {
-               spin_lock_irqsave(&priv_dev->lock, flags);
                cdns3_select_ep(priv_dev, 0x00);
 
                erdy_sent = !priv_dev->hw_configured_flag;
@@ -737,7 +740,6 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep,
                return 0;
        }
 
-       spin_lock_irqsave(&priv_dev->lock, flags);
        if (!list_empty(&priv_ep->pending_req_list)) {
                dev_err(priv_dev->dev,
                        "can't handle multiple requests for ep0\n");
index 8d121e2..0a2a326 100644 (file)
@@ -156,7 +156,7 @@ DECLARE_EVENT_CLASS(cdns3_log_ep0_irq,
                __dynamic_array(char, str, CDNS3_MSG_MAX)
        ),
        TP_fast_assign(
-               __entry->ep_dir = priv_dev->ep0_data_dir;
+               __entry->ep_dir = priv_dev->selected_ep;
                __entry->ep_sts = ep_sts;
        ),
        TP_printk("%s", cdns3_decode_ep0_irq(__get_str(str),
@@ -404,9 +404,9 @@ DECLARE_EVENT_CLASS(cdns3_log_trb,
        TP_fast_assign(
                __assign_str(name, priv_ep->name);
                __entry->trb = trb;
-               __entry->buffer = trb->buffer;
-               __entry->length = trb->length;
-               __entry->control = trb->control;
+               __entry->buffer = le32_to_cpu(trb->buffer);
+               __entry->length = le32_to_cpu(trb->length);
+               __entry->control = le32_to_cpu(trb->control);
                __entry->type = usb_endpoint_type(priv_ep->endpoint.desc);
                __entry->last_stream_id = priv_ep->last_stream_id;
        ),
index 9a7c53d..bb13324 100644 (file)
@@ -1243,6 +1243,29 @@ static void ci_controller_suspend(struct ci_hdrc *ci)
        enable_irq(ci->irq);
 }
 
+/*
+ * Handle the wakeup interrupt triggered by extcon connector
+ * We need to call ci_irq again for extcon since the first
+ * interrupt (wakeup int) only let the controller be out of
+ * low power mode, but not handle any interrupts.
+ */
+static void ci_extcon_wakeup_int(struct ci_hdrc *ci)
+{
+       struct ci_hdrc_cable *cable_id, *cable_vbus;
+       u32 otgsc = hw_read_otgsc(ci, ~0);
+
+       cable_id = &ci->platdata->id_extcon;
+       cable_vbus = &ci->platdata->vbus_extcon;
+
+       if (!IS_ERR(cable_id->edev) && ci->is_otg &&
+               (otgsc & OTGSC_IDIE) && (otgsc & OTGSC_IDIS))
+               ci_irq(ci->irq, ci);
+
+       if (!IS_ERR(cable_vbus->edev) && ci->is_otg &&
+               (otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS))
+               ci_irq(ci->irq, ci);
+}
+
 static int ci_controller_resume(struct device *dev)
 {
        struct ci_hdrc *ci = dev_get_drvdata(dev);
@@ -1275,6 +1298,7 @@ static int ci_controller_resume(struct device *dev)
                enable_irq(ci->irq);
                if (ci_otg_is_fsm_mode(ci))
                        ci_otg_fsm_wakeup_by_srp(ci);
+               ci_extcon_wakeup_int(ci);
        }
 
        return 0;
index f67088b..d5187b5 100644 (file)
@@ -1689,6 +1689,8 @@ static int acm_pre_reset(struct usb_interface *intf)
 
 static const struct usb_device_id acm_ids[] = {
        /* quirky and broken devices */
+       { USB_DEVICE(0x0424, 0x274e), /* Microchip Technology, Inc. (formerly SMSC) */
+         .driver_info = DISABLE_ECHO, }, /* DISABLE ECHO in termios flag */
        { USB_DEVICE(0x076d, 0x0006), /* Denso Cradle CU-321 */
        .driver_info = NO_UNION_NORMAL, },/* has no union descriptor */
        { USB_DEVICE(0x17ef, 0x7000), /* Lenovo USB modem */
index 3e8efe7..e0b7767 100644 (file)
@@ -218,11 +218,12 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Logitech HD Webcam C270 */
        { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME },
 
-       /* Logitech HD Pro Webcams C920, C920-C, C925e and C930e */
+       /* Logitech HD Pro Webcams C920, C920-C, C922, C925e and C930e */
        { USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT },
        { USB_DEVICE(0x046d, 0x0841), .driver_info = USB_QUIRK_DELAY_INIT },
        { USB_DEVICE(0x046d, 0x0843), .driver_info = USB_QUIRK_DELAY_INIT },
        { USB_DEVICE(0x046d, 0x085b), .driver_info = USB_QUIRK_DELAY_INIT },
+       { USB_DEVICE(0x046d, 0x085c), .driver_info = USB_QUIRK_DELAY_INIT },
 
        /* Logitech ConferenceCam CC3000e */
        { USB_DEVICE(0x046d, 0x0847), .driver_info = USB_QUIRK_DELAY_INIT },
index 12b98b4..7faf5f8 100644 (file)
@@ -4920,12 +4920,6 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg)
                                          epnum, 0);
        }
 
-       ret = usb_add_gadget_udc(dev, &hsotg->gadget);
-       if (ret) {
-               dwc2_hsotg_ep_free_request(&hsotg->eps_out[0]->ep,
-                                          hsotg->ctrl_req);
-               return ret;
-       }
        dwc2_hsotg_dump(hsotg);
 
        return 0;
index e571c8a..cb8ddbd 100644 (file)
@@ -342,7 +342,8 @@ static void dwc2_driver_shutdown(struct platform_device *dev)
 {
        struct dwc2_hsotg *hsotg = platform_get_drvdata(dev);
 
-       disable_irq(hsotg->irq);
+       dwc2_disable_global_interrupts(hsotg);
+       synchronize_irq(hsotg->irq);
 }
 
 /**
@@ -575,6 +576,17 @@ static int dwc2_driver_probe(struct platform_device *dev)
        if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
                dwc2_lowlevel_hw_disable(hsotg);
 
+#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \
+       IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
+       /* Postponed adding a new gadget to the udc class driver list */
+       if (hsotg->gadget_enabled) {
+               retval = usb_add_gadget_udc(hsotg->dev, &hsotg->gadget);
+               if (retval) {
+                       dwc2_hsotg_remove(hsotg);
+                       goto error_init;
+               }
+       }
+#endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */
        return 0;
 
 error_init:
index 48b68b6..90bb022 100644 (file)
@@ -162,12 +162,6 @@ static const struct dwc3_exynos_driverdata exynos5250_drvdata = {
        .suspend_clk_idx = -1,
 };
 
-static const struct dwc3_exynos_driverdata exynos5420_drvdata = {
-       .clk_names = { "usbdrd30", "usbdrd30_susp_clk"},
-       .num_clks = 2,
-       .suspend_clk_idx = 1,
-};
-
 static const struct dwc3_exynos_driverdata exynos5433_drvdata = {
        .clk_names = { "aclk", "susp_clk", "pipe_pclk", "phyclk" },
        .num_clks = 4,
@@ -184,9 +178,6 @@ static const struct of_device_id exynos_dwc3_match[] = {
        {
                .compatible = "samsung,exynos5250-dwusb3",
                .data = &exynos5250_drvdata,
-       }, {
-               .compatible = "samsung,exynos5420-dwusb3",
-               .data = &exynos5420_drvdata,
        }, {
                .compatible = "samsung,exynos5433-dwusb3",
                .data = &exynos5433_drvdata,
index b673727..139474c 100644 (file)
@@ -38,6 +38,8 @@
 #define PCI_DEVICE_ID_INTEL_ICLLP              0x34ee
 #define PCI_DEVICE_ID_INTEL_EHLLP              0x4b7e
 #define PCI_DEVICE_ID_INTEL_TGPLP              0xa0ee
+#define PCI_DEVICE_ID_INTEL_TGPH               0x43ee
+#define PCI_DEVICE_ID_INTEL_JSP                        0x4dee
 
 #define PCI_INTEL_BXT_DSM_GUID         "732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511"
 #define PCI_INTEL_BXT_FUNC_PMU_PWR     4
@@ -206,8 +208,10 @@ static void dwc3_pci_resume_work(struct work_struct *work)
        int ret;
 
        ret = pm_runtime_get_sync(&dwc3->dev);
-       if (ret)
+       if (ret) {
+               pm_runtime_put_sync_autosuspend(&dwc3->dev);
                return;
+       }
 
        pm_runtime_mark_last_busy(&dwc3->dev);
        pm_runtime_put_sync_autosuspend(&dwc3->dev);
@@ -356,6 +360,12 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGPLP),
          (kernel_ulong_t) &dwc3_pci_intel_properties, },
 
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGPH),
+         (kernel_ulong_t) &dwc3_pci_intel_properties, },
+
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_JSP),
+         (kernel_ulong_t) &dwc3_pci_intel_properties, },
+
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_NL_USB),
          (kernel_ulong_t) &dwc3_pci_amd_properties, },
        {  }    /* Terminating Entry */
index ea0d531..775cf70 100644 (file)
@@ -1058,7 +1058,8 @@ static int __init kgdbdbgp_parse_config(char *str)
                kgdbdbgp_wait_time = simple_strtoul(ptr, &ptr, 10);
        }
        kgdb_register_io_module(&kgdbdbgp_io_ops);
-       kgdbdbgp_io_ops.is_console = early_dbgp_console.index != -1;
+       if (early_dbgp_console.index != -1)
+               kgdbdbgp_io_ops.cons = &early_dbgp_console;
 
        return 0;
 }
index 349deae..e2d7f69 100644 (file)
@@ -336,7 +336,9 @@ static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req)
 
        /* Copy buffer is full, add it to the play_queue */
        if (audio_buf_size - copy_buf->actual < req->actual) {
+               spin_lock_irq(&audio->lock);
                list_add_tail(&copy_buf->list, &audio->play_queue);
+               spin_unlock_irq(&audio->lock);
                schedule_work(&audio->playback_work);
                copy_buf = f_audio_buffer_alloc(audio_buf_size);
                if (IS_ERR(copy_buf))
index d69f61f..9342a3d 100644 (file)
@@ -676,13 +676,7 @@ static int usba_ep_disable(struct usb_ep *_ep)
 
        if (!ep->ep.desc) {
                spin_unlock_irqrestore(&udc->lock, flags);
-               /* REVISIT because this driver disables endpoints in
-                * reset_all_endpoints() before calling disconnect(),
-                * most gadget drivers would trigger this non-error ...
-                */
-               if (udc->gadget.speed != USB_SPEED_UNKNOWN)
-                       DBG(DBG_ERR, "ep_disable: %s not enabled\n",
-                                       ep->ep.name);
+               DBG(DBG_ERR, "ep_disable: %s not enabled\n", ep->ep.name);
                return -EINVAL;
        }
        ep->ep.desc = NULL;
@@ -871,7 +865,7 @@ static int usba_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
        u32 status;
 
        DBG(DBG_GADGET | DBG_QUEUE, "ep_dequeue: %s, req %p\n",
-                       ep->ep.name, req);
+                       ep->ep.name, _req);
 
        spin_lock_irqsave(&udc->lock, flags);
 
index 7164ad9..7419889 100644 (file)
@@ -1980,9 +1980,12 @@ static int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit)
 
        if (num == 0) {
                _req = gr_alloc_request(&ep->ep, GFP_ATOMIC);
+               if (!_req)
+                       return -ENOMEM;
+
                buf = devm_kzalloc(dev->dev, PAGE_SIZE, GFP_DMA | GFP_ATOMIC);
-               if (!_req || !buf) {
-                       /* possible _req freed by gr_probe via gr_remove */
+               if (!buf) {
+                       gr_free_request(&ep->ep, _req);
                        return -ENOMEM;
                }
 
index cafde05..80a1b52 100644 (file)
@@ -2313,7 +2313,8 @@ static int mv_udc_probe(struct platform_device *pdev)
        return 0;
 
 err_create_workqueue:
-       destroy_workqueue(udc->qwork);
+       if (udc->qwork)
+               destroy_workqueue(udc->qwork);
 err_destroy_dma:
        dma_pool_destroy(udc->dtd_pool);
 err_free_dma:
index 58a4d33..119505f 100644 (file)
@@ -68,7 +68,7 @@ EXPORT_SYMBOL_GPL(usb_gadget_get_string);
 
 /**
  * usb_validate_langid - validate usb language identifiers
- * @lang: usb language identifier
+ * @langid: usb language identifier
  *
  * Returns true for valid language identifier, otherwise false.
  */
index a4e9abc..1a9b757 100644 (file)
@@ -203,9 +203,8 @@ static int exynos_ehci_probe(struct platform_device *pdev)
        hcd->rsrc_len = resource_size(res);
 
        irq = platform_get_irq(pdev, 0);
-       if (!irq) {
-               dev_err(&pdev->dev, "Failed to get IRQ\n");
-               err = -ENODEV;
+       if (irq < 0) {
+               err = irq;
                goto fail_io;
        }
 
index 3c3820a..af3c1b9 100644 (file)
@@ -216,6 +216,13 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                ehci_info(ehci, "applying MosChip frame-index workaround\n");
                ehci->frame_index_bug = 1;
                break;
+       case PCI_VENDOR_ID_HUAWEI:
+               /* Synopsys HC bug */
+               if (pdev->device == 0xa239) {
+                       ehci_info(ehci, "applying Synopsys HC workaround\n");
+                       ehci->has_synopsys_hc_bug = 1;
+               }
+               break;
        }
 
        /* optional debug port, normally in the first BAR */
index cff9652..b91d50d 100644 (file)
@@ -191,6 +191,7 @@ static int ohci_hcd_sm501_drv_remove(struct platform_device *pdev)
        struct resource *mem;
 
        usb_remove_hcd(hcd);
+       iounmap(hcd->regs);
        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
        usb_put_hcd(hcd);
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
index fea5555..45c54d5 100644 (file)
@@ -557,6 +557,10 @@ static bool need_bw_sch(struct usb_host_endpoint *ep,
        if (is_fs_or_ls(speed) && !has_tt)
                return false;
 
+       /* skip endpoint with zero maxpkt */
+       if (usb_endpoint_maxp(&ep->desc) == 0)
+               return false;
+
        return true;
 }
 
index bfbdb3c..4311d4c 100644 (file)
@@ -587,6 +587,9 @@ static int xhci_mtk_remove(struct platform_device *dev)
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
        struct usb_hcd  *shared_hcd = xhci->shared_hcd;
 
+       pm_runtime_put_noidle(&dev->dev);
+       pm_runtime_disable(&dev->dev);
+
        usb_remove_hcd(shared_hcd);
        xhci->shared_hcd = NULL;
        device_init_wakeup(&dev->dev, false);
@@ -597,8 +600,6 @@ static int xhci_mtk_remove(struct platform_device *dev)
        xhci_mtk_sch_exit(mtk);
        xhci_mtk_clks_disable(mtk);
        xhci_mtk_ldos_disable(mtk);
-       pm_runtime_put_sync(&dev->dev);
-       pm_runtime_disable(&dev->dev);
 
        return 0;
 }
index ef513c2..9234c82 100644 (file)
@@ -265,6 +265,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
        if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
                        pdev->device == 0x1142)
                xhci->quirks |= XHCI_TRUST_TX_LENGTH;
+       if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
+                       pdev->device == 0x2142)
+               xhci->quirks |= XHCI_NO_64BIT_SUPPORT;
 
        if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
                pdev->device == PCI_DEVICE_ID_ASMEDIA_1042A_XHCI)
index 2eaf5c0..ee6bf01 100644 (file)
@@ -856,7 +856,7 @@ static int tegra_xusb_init_context(struct tegra_xusb *tegra)
        if (!tegra->context.ipfs)
                return -ENOMEM;
 
-       tegra->context.fpci = devm_kcalloc(tegra->dev, soc->ipfs.num_offsets,
+       tegra->context.fpci = devm_kcalloc(tegra->dev, soc->fpci.num_offsets,
                                           sizeof(u32), GFP_KERNEL);
        if (!tegra->context.fpci)
                return -ENOMEM;
index bee5dec..ed468ee 100644 (file)
@@ -1430,6 +1430,7 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
                                xhci->devs[slot_id]->out_ctx, ep_index);
 
                ep_ctx = xhci_get_ep_ctx(xhci, command->in_ctx, ep_index);
+               ep_ctx->ep_info &= cpu_to_le32(~EP_STATE_MASK);/* must clear */
                ep_ctx->ep_info2 &= cpu_to_le32(~MAX_PACKET_MASK);
                ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet_size));
 
@@ -4390,6 +4391,9 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
        int             hird, exit_latency;
        int             ret;
 
+       if (xhci->quirks & XHCI_HW_LPM_DISABLE)
+               return -EPERM;
+
        if (hcd->speed >= HCD_USB3 || !xhci->hw_lpm_support ||
                        !udev->lpm_capable)
                return -EPERM;
@@ -4412,7 +4416,7 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
        xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n",
                        enable ? "enable" : "disable", port_num + 1);
 
-       if (enable && !(xhci->quirks & XHCI_HW_LPM_DISABLE)) {
+       if (enable) {
                /* Host supports BESL timeout instead of HIRD */
                if (udev->usb2_hw_lpm_besl_capable) {
                        /* if device doesn't have a preferred BESL value use a
@@ -4471,6 +4475,9 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
                        mutex_lock(hcd->bandwidth_mutex);
                        xhci_change_max_exit_latency(xhci, udev, 0);
                        mutex_unlock(hcd->bandwidth_mutex);
+                       readl_poll_timeout(ports[port_num]->addr, pm_val,
+                                          (pm_val & PORT_PLS_MASK) == XDEV_U0,
+                                          100, 10000);
                        return 0;
                }
        }
index 2c6c4f8..c295e8a 100644 (file)
@@ -716,7 +716,7 @@ struct xhci_ep_ctx {
  * 4 - TRB error
  * 5-7 - reserved
  */
-#define EP_STATE_MASK          (0xf)
+#define EP_STATE_MASK          (0x7)
 #define EP_STATE_DISABLED      0
 #define EP_STATE_RUNNING       1
 #define EP_STATE_HALTED                2
index 98ada1a..bae8889 100644 (file)
@@ -2873,6 +2873,7 @@ static void usbtest_disconnect(struct usb_interface *intf)
 
        usb_set_intfdata(intf, NULL);
        dev_dbg(&intf->dev, "disconnect\n");
+       kfree(dev->buf);
        kfree(dev);
 }
 
index cffe2ac..03a3337 100644 (file)
@@ -1199,11 +1199,7 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, tegra_phy);
 
-       err = usb_add_phy_dev(&tegra_phy->u_phy);
-       if (err)
-               return err;
-
-       return 0;
+       return usb_add_phy_dev(&tegra_phy->u_phy);
 }
 
 static int tegra_usb_phy_remove(struct platform_device *pdev)
index 01c6a48..ac9a81a 100644 (file)
@@ -803,7 +803,8 @@ static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
        return info->dma_map_ctrl(chan->device->dev, pkt, map);
 }
 
-static void usbhsf_dma_complete(void *arg);
+static void usbhsf_dma_complete(void *arg,
+                               const struct dmaengine_result *result);
 static void usbhsf_dma_xfer_preparing(struct usbhs_pkt *pkt)
 {
        struct usbhs_pipe *pipe = pkt->pipe;
@@ -813,6 +814,7 @@ static void usbhsf_dma_xfer_preparing(struct usbhs_pkt *pkt)
        struct dma_chan *chan;
        struct device *dev = usbhs_priv_to_dev(priv);
        enum dma_transfer_direction dir;
+       dma_cookie_t cookie;
 
        fifo = usbhs_pipe_to_fifo(pipe);
        if (!fifo)
@@ -827,11 +829,11 @@ static void usbhsf_dma_xfer_preparing(struct usbhs_pkt *pkt)
        if (!desc)
                return;
 
-       desc->callback          = usbhsf_dma_complete;
-       desc->callback_param    = pipe;
+       desc->callback_result   = usbhsf_dma_complete;
+       desc->callback_param    = pkt;
 
-       pkt->cookie = dmaengine_submit(desc);
-       if (pkt->cookie < 0) {
+       cookie = dmaengine_submit(desc);
+       if (cookie < 0) {
                dev_err(dev, "Failed to submit dma descriptor\n");
                return;
        }
@@ -1152,12 +1154,10 @@ static size_t usbhs_dma_calc_received_size(struct usbhs_pkt *pkt,
                                           struct dma_chan *chan, int dtln)
 {
        struct usbhs_pipe *pipe = pkt->pipe;
-       struct dma_tx_state state;
        size_t received_size;
        int maxp = usbhs_pipe_get_maxpacket(pipe);
 
-       dmaengine_tx_status(chan, pkt->cookie, &state);
-       received_size = pkt->length - state.residue;
+       received_size = pkt->length - pkt->dma_result->residue;
 
        if (dtln) {
                received_size -= USBHS_USB_DMAC_XFER_SIZE;
@@ -1363,13 +1363,16 @@ static int usbhsf_irq_ready(struct usbhs_priv *priv,
        return 0;
 }
 
-static void usbhsf_dma_complete(void *arg)
+static void usbhsf_dma_complete(void *arg,
+                               const struct dmaengine_result *result)
 {
-       struct usbhs_pipe *pipe = arg;
+       struct usbhs_pkt *pkt = arg;
+       struct usbhs_pipe *pipe = pkt->pipe;
        struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
        struct device *dev = usbhs_priv_to_dev(priv);
        int ret;
 
+       pkt->dma_result = result;
        ret = usbhsf_pkt_handler(pipe, USBHSF_PKT_DMA_DONE);
        if (ret < 0)
                dev_err(dev, "dma_complete run_error %d : %d\n",
index 7d3700b..039a2b9 100644 (file)
@@ -50,7 +50,7 @@ struct usbhs_pkt {
                     struct usbhs_pkt *pkt);
        struct work_struct work;
        dma_addr_t dma;
-       dma_cookie_t cookie;
+       const struct dmaengine_result *dma_result;
        void *buf;
        int length;
        int trans;
index 89675ee..8fbaef5 100644 (file)
@@ -77,6 +77,7 @@
 
 static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x4348, 0x5523) },
+       { USB_DEVICE(0x1a86, 0x7522) },
        { USB_DEVICE(0x1a86, 0x7523) },
        { USB_DEVICE(0x1a86, 0x5523) },
        { },
index 216edd5..ecda821 100644 (file)
@@ -59,6 +59,7 @@ static const struct usb_device_id id_table_earthmate[] = {
 
 static const struct usb_device_id id_table_cyphidcomrs232[] = {
        { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
+       { USB_DEVICE(VENDOR_ID_SAI, PRODUCT_ID_CYPHIDCOM) },
        { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
        { USB_DEVICE(VENDOR_ID_FRWD, PRODUCT_ID_CYPHIDCOM_FRWD) },
        { }                                             /* Terminating entry */
@@ -73,6 +74,7 @@ static const struct usb_device_id id_table_combined[] = {
        { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
        { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
        { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
+       { USB_DEVICE(VENDOR_ID_SAI, PRODUCT_ID_CYPHIDCOM) },
        { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
        { USB_DEVICE(VENDOR_ID_FRWD, PRODUCT_ID_CYPHIDCOM_FRWD) },
        { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) },
index 35e2237..16b7410 100644 (file)
@@ -25,6 +25,9 @@
 #define VENDOR_ID_CYPRESS              0x04b4
 #define PRODUCT_ID_CYPHIDCOM           0x5500
 
+/* Simply Automated HID->COM UPB PIM (using Cypress PID 0x5500) */
+#define VENDOR_ID_SAI                  0x17dd
+
 /* FRWD Dongle - a GPS sports watch */
 #define VENDOR_ID_FRWD                 0x6737
 #define PRODUCT_ID_CYPHIDCOM_FRWD      0x0001
index d5bff69..b8dfeb4 100644 (file)
@@ -697,14 +697,16 @@ static int iuu_uart_write(struct tty_struct *tty, struct usb_serial_port *port,
        struct iuu_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
 
-       if (count > 256)
-               return -ENOMEM;
-
        spin_lock_irqsave(&priv->lock, flags);
 
+       count = min(count, 256 - priv->writelen);
+       if (count == 0)
+               goto out;
+
        /* fill the buffer */
        memcpy(priv->writebuf + priv->writelen, buf, count);
        priv->writelen += count;
+out:
        spin_unlock_irqrestore(&priv->lock, flags);
 
        return count;
index 254a8bb..9b7cee9 100644 (file)
@@ -245,6 +245,7 @@ static void option_instat_callback(struct urb *urb);
 /* These Quectel products use Quectel's vendor ID */
 #define QUECTEL_PRODUCT_EC21                   0x0121
 #define QUECTEL_PRODUCT_EC25                   0x0125
+#define QUECTEL_PRODUCT_EG95                   0x0195
 #define QUECTEL_PRODUCT_BG96                   0x0296
 #define QUECTEL_PRODUCT_EP06                   0x0306
 #define QUECTEL_PRODUCT_EM12                   0x0512
@@ -1097,6 +1098,8 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = RSVD(4) },
        { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25),
          .driver_info = RSVD(4) },
+       { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95),
+         .driver_info = RSVD(4) },
        { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96),
          .driver_info = RSVD(4) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff),
@@ -2028,6 +2031,9 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = RSVD(4) | RSVD(5) },
        { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff),                     /* Fibocom NL678 series */
          .driver_info = RSVD(6) },
+       { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) },                   /* GosunCn GM500 RNDIS */
+       { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) },                   /* GosunCn GM500 MBIM */
+       { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) },                   /* GosunCn GM500 ECM/NCM */
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
index 962bc69..70ddc9d 100644 (file)
@@ -148,7 +148,8 @@ pmc_usb_mux_dp_hpd(struct pmc_usb_port *port, struct typec_mux_state *state)
        msg[0] = PMC_USB_DP_HPD;
        msg[0] |= port->usb3_port << PMC_USB_MSG_USB3_PORT_SHIFT;
 
-       msg[1] = PMC_USB_DP_HPD_IRQ;
+       if (data->status & DP_STATUS_IRQ_HPD)
+               msg[1] = PMC_USB_DP_HPD_IRQ;
 
        if (data->status & DP_STATUS_HPD_STATE)
                msg[1] |= PMC_USB_DP_HPD_LVL;
@@ -161,6 +162,7 @@ pmc_usb_mux_dp(struct pmc_usb_port *port, struct typec_mux_state *state)
 {
        struct typec_displayport_data *data = state->data;
        struct altmode_req req = { };
+       int ret;
 
        if (data->status & DP_STATUS_IRQ_HPD)
                return pmc_usb_mux_dp_hpd(port, state);
@@ -181,7 +183,14 @@ pmc_usb_mux_dp(struct pmc_usb_port *port, struct typec_mux_state *state)
        if (data->status & DP_STATUS_HPD_STATE)
                req.mode_data |= PMC_USB_ALTMODE_HPD_HIGH;
 
-       return pmc_usb_command(port, (void *)&req, sizeof(req));
+       ret = pmc_usb_command(port, (void *)&req, sizeof(req));
+       if (ret)
+               return ret;
+
+       if (data->status & DP_STATUS_HPD_STATE)
+               return pmc_usb_mux_dp_hpd(port, state);
+
+       return 0;
 }
 
 static int
index 0173890..b56a088 100644 (file)
@@ -179,26 +179,6 @@ out:
        return tcpci_irq(chip->tcpci);
 }
 
-static int rt1711h_init_alert(struct rt1711h_chip *chip,
-                             struct i2c_client *client)
-{
-       int ret;
-
-       /* Disable chip interrupts before requesting irq */
-       ret = rt1711h_write16(chip, TCPC_ALERT_MASK, 0);
-       if (ret < 0)
-               return ret;
-
-       ret = devm_request_threaded_irq(chip->dev, client->irq, NULL,
-                                       rt1711h_irq,
-                                       IRQF_ONESHOT | IRQF_TRIGGER_LOW,
-                                       dev_name(chip->dev), chip);
-       if (ret < 0)
-               return ret;
-       enable_irq_wake(client->irq);
-       return 0;
-}
-
 static int rt1711h_sw_reset(struct rt1711h_chip *chip)
 {
        int ret;
@@ -260,7 +240,8 @@ static int rt1711h_probe(struct i2c_client *client,
        if (ret < 0)
                return ret;
 
-       ret = rt1711h_init_alert(chip, client);
+       /* Disable chip interrupts before requesting irq */
+       ret = rt1711h_write16(chip, TCPC_ALERT_MASK, 0);
        if (ret < 0)
                return ret;
 
@@ -271,6 +252,14 @@ static int rt1711h_probe(struct i2c_client *client,
        if (IS_ERR_OR_NULL(chip->tcpci))
                return PTR_ERR(chip->tcpci);
 
+       ret = devm_request_threaded_irq(chip->dev, client->irq, NULL,
+                                       rt1711h_irq,
+                                       IRQF_ONESHOT | IRQF_TRIGGER_LOW,
+                                       dev_name(chip->dev), chip);
+       if (ret < 0)
+               return ret;
+       enable_irq_wake(client->irq);
+
        return 0;
 }
 
index ff6562f..de211ef 100644 (file)
@@ -63,7 +63,7 @@ static void vdpa_release_dev(struct device *d)
  * @config: the bus operations that is supported by this device
  * @size: size of the parent structure that contains private data
  *
- * Drvier should use vdap_alloc_device() wrapper macro instead of
+ * Driver should use vdpa_alloc_device() wrapper macro instead of
  * using this directly.
  *
  * Returns an error when parent/config/dma_dev is not set or fail to get
index 7c07790..de881a6 100644 (file)
@@ -521,10 +521,19 @@ static void vfio_pci_release(void *device_data)
                vfio_pci_vf_token_user_add(vdev, -1);
                vfio_spapr_pci_eeh_release(vdev->pdev);
                vfio_pci_disable(vdev);
-               if (vdev->err_trigger)
+               mutex_lock(&vdev->igate);
+               if (vdev->err_trigger) {
                        eventfd_ctx_put(vdev->err_trigger);
-               if (vdev->req_trigger)
+                       vdev->err_trigger = NULL;
+               }
+               mutex_unlock(&vdev->igate);
+
+               mutex_lock(&vdev->igate);
+               if (vdev->req_trigger) {
                        eventfd_ctx_put(vdev->req_trigger);
+                       vdev->req_trigger = NULL;
+               }
+               mutex_unlock(&vdev->igate);
        }
 
        mutex_unlock(&vdev->reflck->lock);
index 8746c94..d98843f 100644 (file)
@@ -398,9 +398,15 @@ static inline void p_setd(struct perm_bits *p, int off, u32 virt, u32 write)
 /* Caller should hold memory_lock semaphore */
 bool __vfio_pci_memory_enabled(struct vfio_pci_device *vdev)
 {
+       struct pci_dev *pdev = vdev->pdev;
        u16 cmd = le16_to_cpu(*(__le16 *)&vdev->vconfig[PCI_COMMAND]);
 
-       return cmd & PCI_COMMAND_MEMORY;
+       /*
+        * SR-IOV VF memory enable is handled by the MSE bit in the
+        * PF SR-IOV capability, there's therefore no need to trigger
+        * faults based on the virtual value.
+        */
+       return pdev->is_virtfn || (cmd & PCI_COMMAND_MEMORY);
 }
 
 /*
@@ -1728,6 +1734,15 @@ int vfio_config_init(struct vfio_pci_device *vdev)
                                 vconfig[PCI_INTERRUPT_PIN]);
 
                vconfig[PCI_INTERRUPT_PIN] = 0; /* Gratuitous for good VFs */
+
+               /*
+                * VFs do no implement the memory enable bit of the COMMAND
+                * register therefore we'll not have it set in our initial
+                * copy of config space after pci_enable_device().  For
+                * consistency with PFs, set the virtual enable bit here.
+                */
+               *(__le16 *)&vconfig[PCI_COMMAND] |=
+                                       cpu_to_le16(PCI_COMMAND_MEMORY);
        }
 
        if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx)
index 6fb4d7e..b22adf0 100644 (file)
@@ -1215,7 +1215,7 @@ vhost_scsi_ctl_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
                        continue;
                }
 
-               switch (v_req.type) {
+               switch (vhost32_to_cpu(vq, v_req.type)) {
                case VIRTIO_SCSI_T_TMF:
                        vc.req = &v_req.tmf;
                        vc.req_size = sizeof(struct virtio_scsi_ctrl_tmf_req);
index 0466921..a09dedc 100644 (file)
@@ -263,9 +263,62 @@ static int vhost_test_set_features(struct vhost_test *n, u64 features)
        return 0;
 }
 
+static long vhost_test_set_backend(struct vhost_test *n, unsigned index, int fd)
+{
+       static void *backend;
+
+       const bool enable = fd != -1;
+       struct vhost_virtqueue *vq;
+       int r;
+
+       mutex_lock(&n->dev.mutex);
+       r = vhost_dev_check_owner(&n->dev);
+       if (r)
+               goto err;
+
+       if (index >= VHOST_TEST_VQ_MAX) {
+               r = -ENOBUFS;
+               goto err;
+       }
+       vq = &n->vqs[index];
+       mutex_lock(&vq->mutex);
+
+       /* Verify that ring has been setup correctly. */
+       if (!vhost_vq_access_ok(vq)) {
+               r = -EFAULT;
+               goto err_vq;
+       }
+       if (!enable) {
+               vhost_poll_stop(&vq->poll);
+               backend = vhost_vq_get_backend(vq);
+               vhost_vq_set_backend(vq, NULL);
+       } else {
+               vhost_vq_set_backend(vq, backend);
+               r = vhost_vq_init_access(vq);
+               if (r == 0)
+                       r = vhost_poll_start(&vq->poll, vq->kick);
+       }
+
+       mutex_unlock(&vq->mutex);
+
+       if (enable) {
+               vhost_test_flush_vq(n, index);
+       }
+
+       mutex_unlock(&n->dev.mutex);
+       return 0;
+
+err_vq:
+       mutex_unlock(&vq->mutex);
+err:
+       mutex_unlock(&n->dev.mutex);
+       return r;
+}
+
 static long vhost_test_ioctl(struct file *f, unsigned int ioctl,
                             unsigned long arg)
 {
+       struct vhost_vring_file backend;
        struct vhost_test *n = f->private_data;
        void __user *argp = (void __user *)arg;
        u64 __user *featurep = argp;
@@ -277,6 +330,10 @@ static long vhost_test_ioctl(struct file *f, unsigned int ioctl,
                if (copy_from_user(&test, argp, sizeof test))
                        return -EFAULT;
                return vhost_test_run(n, test);
+       case VHOST_TEST_SET_BACKEND:
+               if (copy_from_user(&backend, argp, sizeof backend))
+                       return -EFAULT;
+               return vhost_test_set_backend(n, backend.index, backend.fd);
        case VHOST_GET_FEATURES:
                features = VHOST_FEATURES;
                if (copy_to_user(featurep, &features, sizeof features))
index 7dd265b..822bc4b 100644 (file)
@@ -4,5 +4,6 @@
 
 /* Start a given test on the virtio null device. 0 stops all tests. */
 #define VHOST_TEST_RUN _IOW(VHOST_VIRTIO, 0x31, int)
+#define VHOST_TEST_SET_BACKEND _IOW(VHOST_VIRTIO, 0x32, int)
 
 #endif
index 7580e34..a54b60d 100644 (file)
@@ -818,7 +818,7 @@ static int vhost_vdpa_mmap(struct file *file, struct vm_area_struct *vma)
        struct vdpa_device *vdpa = v->vdpa;
        const struct vdpa_config_ops *ops = vdpa->config;
        struct vdpa_notification_area notify;
-       int index = vma->vm_pgoff;
+       unsigned long index = vma->vm_pgoff;
 
        if (vma->vm_end - vma->vm_start != PAGE_SIZE)
                return -EINVAL;
index e8ab583..113116d 100644 (file)
@@ -107,7 +107,7 @@ static void tosa_lcd_tg_on(struct tosa_lcd_data *data)
        /* TG LCD GVSS */
        tosa_tg_send(spi, TG_PINICTL, 0x0);
 
-       if (!data->i2c) {
+       if (IS_ERR_OR_NULL(data->i2c)) {
                /*
                 * after the pannel is powered up the first time,
                 * we can access the i2c bus so probe for the DAC
@@ -119,7 +119,7 @@ static void tosa_lcd_tg_on(struct tosa_lcd_data *data)
                        .addr   = DAC_BASE,
                        .platform_data = data->spi,
                };
-               data->i2c = i2c_new_device(adap, &info);
+               data->i2c = i2c_new_client_device(adap, &info);
        }
 }
 
index ca935c0..35ebeec 100644 (file)
@@ -216,7 +216,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
        region.color = color;
        region.rop = ROP_COPY;
 
-       if (rw && !bottom_only) {
+       if ((int) rw > 0 && !bottom_only) {
                region.dx = info->var.xoffset + rs;
                region.dy = 0;
                region.width = rw;
@@ -224,7 +224,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
                info->fbops->fb_fillrect(info, &region);
        }
 
-       if (bh) {
+       if ((int) bh > 0) {
                region.dx = info->var.xoffset;
                region.dy = info->var.yoffset + bs;
                region.width = rs;
index 9d28a8e..e2a490c 100644 (file)
@@ -2402,7 +2402,8 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
                ops->graphics = 1;
 
                if (!blank) {
-                       var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
+                       var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE |
+                               FB_ACTIVATE_KD_TEXT;
                        fb_set_var(info, &var);
                        ops->graphics = 0;
                        ops->var = info->var;
index dfa9a8a..78f3a56 100644 (file)
@@ -201,7 +201,7 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info,
        region.color = color;
        region.rop = ROP_COPY;
 
-       if (rw && !bottom_only) {
+       if ((int) rw > 0 && !bottom_only) {
                region.dx = 0;
                region.dy = info->var.yoffset;
                region.height = rw;
@@ -209,7 +209,7 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info,
                info->fbops->fb_fillrect(info, &region);
        }
 
-       if (bh) {
+       if ((int) bh > 0) {
                region.dx = info->var.xoffset + bs;
                region.dy = 0;
                 region.height = info->var.yres_virtual;
index ce08251..fd098ff 100644 (file)
@@ -184,7 +184,7 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info,
        region.color = color;
        region.rop = ROP_COPY;
 
-       if (rw && !bottom_only) {
+       if ((int) rw > 0 && !bottom_only) {
                region.dx = 0;
                region.dy = info->var.yoffset + rs;
                region.height = rw;
@@ -192,7 +192,7 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info,
                info->fbops->fb_fillrect(info, &region);
        }
 
-       if (bh) {
+       if ((int) bh > 0) {
                region.dx = info->var.xoffset;
                region.dy = info->var.yoffset;
                 region.height = info->var.yres;
index 1936afc..e165a3f 100644 (file)
@@ -231,7 +231,7 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info,
        region.color = color;
        region.rop = ROP_COPY;
 
-       if (rw && !bottom_only) {
+       if ((int) rw > 0 && !bottom_only) {
                region.dy = 0;
                region.dx = info->var.xoffset;
                region.width  = rw;
@@ -239,7 +239,7 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info,
                info->fbops->fb_fillrect(info, &region);
        }
 
-       if (bh) {
+       if ((int) bh > 0) {
                region.dy = info->var.yoffset;
                region.dx = info->var.xoffset;
                 region.height  = bh;
index f02be0d..8d418ab 100644 (file)
@@ -402,7 +402,7 @@ int __init hpfb_init(void)
        if (err)
                return err;
 
-       err = probe_kernel_read(&i, (unsigned char *)INTFBVADDR + DIO_IDOFF, 1);
+       err = copy_from_kernel_nofault(&i, (unsigned char *)INTFBVADDR + DIO_IDOFF, 1);
 
        if (!err && (i == DIO_ID_FBUFFER) && topcat_sid_ok(sid = DIO_SECID(INTFBVADDR))) {
                if (!request_mem_region(INTFBPADDR, DIO_DEVSIZE, "Internal Topcat"))
index bee29aa..def14ac 100644 (file)
@@ -1836,7 +1836,7 @@ static int uvesafb_setup(char *options)
                else if (!strcmp(this_opt, "noedid"))
                        noedid = true;
                else if (!strcmp(this_opt, "noblank"))
-                       blank = true;
+                       blank = false;
                else if (!strncmp(this_opt, "vtotal:", 7))
                        vram_total = simple_strtoul(this_opt + 7, NULL, 0);
                else if (!strncmp(this_opt, "vremap:", 7))
index b690a8a..18ebd7a 100644 (file)
@@ -1444,7 +1444,7 @@ static int vbg_ioctl_change_guest_capabilities(struct vbg_dev *gdev,
        or_mask = caps->u.in.or_mask;
        not_mask = caps->u.in.not_mask;
 
-       if ((or_mask | not_mask) & ~VMMDEV_EVENT_VALID_EVENT_MASK)
+       if ((or_mask | not_mask) & ~VMMDEV_GUEST_CAPABILITIES_MASK)
                return -EINVAL;
 
        ret = vbg_set_session_capabilities(gdev, session, or_mask, not_mask,
@@ -1520,7 +1520,8 @@ int vbg_core_ioctl(struct vbg_session *session, unsigned int req, void *data)
 
        /* For VMMDEV_REQUEST hdr->type != VBG_IOCTL_HDR_TYPE_DEFAULT */
        if (req_no_size == VBG_IOCTL_VMMDEV_REQUEST(0) ||
-           req == VBG_IOCTL_VMMDEV_REQUEST_BIG)
+           req == VBG_IOCTL_VMMDEV_REQUEST_BIG ||
+           req == VBG_IOCTL_VMMDEV_REQUEST_BIG_ALT)
                return vbg_ioctl_vmmrequest(gdev, session, data);
 
        if (hdr->type != VBG_IOCTL_HDR_TYPE_DEFAULT)
@@ -1558,6 +1559,7 @@ int vbg_core_ioctl(struct vbg_session *session, unsigned int req, void *data)
        case VBG_IOCTL_HGCM_CALL(0):
                return vbg_ioctl_hgcm_call(gdev, session, f32bit, data);
        case VBG_IOCTL_LOG(0):
+       case VBG_IOCTL_LOG_ALT(0):
                return vbg_ioctl_log(data);
        }
 
index 4188c12..77c3a9c 100644 (file)
 #include <linux/vboxguest.h>
 #include "vmmdev.h"
 
+/*
+ * The mainline kernel version (this version) of the vboxguest module
+ * contained a bug where it defined VBGL_IOCTL_VMMDEV_REQUEST_BIG and
+ * VBGL_IOCTL_LOG using _IOC(_IOC_READ | _IOC_WRITE, 'V', ...) instead
+ * of _IO(V, ...) as the out of tree VirtualBox upstream version does.
+ *
+ * These _ALT definitions keep compatibility with the wrong defines the
+ * mainline kernel version used for a while.
+ * Note the VirtualBox userspace bits have always been built against
+ * VirtualBox upstream's headers, so this is likely not necessary. But
+ * we must never break our ABI so we keep these around to be 100% sure.
+ */
+#define VBG_IOCTL_VMMDEV_REQUEST_BIG_ALT _IOC(_IOC_READ | _IOC_WRITE, 'V', 3, 0)
+#define VBG_IOCTL_LOG_ALT(s)             _IOC(_IOC_READ | _IOC_WRITE, 'V', 9, s)
+
 struct vbg_session;
 
 /** VBox guest memory balloon. */
index 6e8c0f1..32c2c52 100644 (file)
@@ -131,7 +131,8 @@ static long vbg_misc_device_ioctl(struct file *filp, unsigned int req,
         * the need for a bounce-buffer and another copy later on.
         */
        is_vmmdev_req = (req & ~IOCSIZE_MASK) == VBG_IOCTL_VMMDEV_REQUEST(0) ||
-                        req == VBG_IOCTL_VMMDEV_REQUEST_BIG;
+                        req == VBG_IOCTL_VMMDEV_REQUEST_BIG ||
+                        req == VBG_IOCTL_VMMDEV_REQUEST_BIG_ALT;
 
        if (is_vmmdev_req)
                buf = vbg_req_alloc(size, VBG_IOCTL_HDR_TYPE_DEFAULT,
index 6337b8d..21f4081 100644 (file)
@@ -206,6 +206,8 @@ VMMDEV_ASSERT_SIZE(vmmdev_mask, 24 + 8);
  * not.
  */
 #define VMMDEV_GUEST_SUPPORTS_GRAPHICS                      BIT(2)
+/* The mask of valid capabilities, for sanity checking. */
+#define VMMDEV_GUEST_CAPABILITIES_MASK                      0x00000007U
 
 /** struct vmmdev_hypervisorinfo - Hypervisor info structure. */
 struct vmmdev_hypervisorinfo {
index 5809e5f..5c92e4a 100644 (file)
@@ -85,7 +85,7 @@ config VIRTIO_MEM
        depends on VIRTIO
        depends on MEMORY_HOTPLUG_SPARSE
        depends on MEMORY_HOTREMOVE
-       select CONTIG_ALLOC
+       depends on CONTIG_ALLOC
        help
         This driver provides access to virtio-mem paravirtualized memory
         devices, allowing to hotplug and hotunplug memory.
index 1f157d2..8be02f3 100644 (file)
@@ -578,10 +578,14 @@ static int init_vqs(struct virtio_balloon *vb)
 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))
+                              &vb->config_read_bitmap)) {
                virtio_cread(vb->vdev, struct virtio_balloon_config,
                             free_page_hint_cmd_id,
                             &vb->cmd_id_received_cache);
+               /* Legacy balloon config space is LE, unlike all other devices. */
+               if (!virtio_has_feature(vb->vdev, VIRTIO_F_VERSION_1))
+                       vb->cmd_id_received_cache = le32_to_cpu((__force __le32)vb->cmd_id_received_cache);
+       }
 
        return vb->cmd_id_received_cache;
 }
@@ -974,6 +978,11 @@ static int virtballoon_probe(struct virtio_device *vdev)
                /*
                 * Let the hypervisor know that we are expecting a
                 * specific value to be written back in balloon pages.
+                *
+                * If the PAGE_POISON value was larger than a byte we would
+                * need to byte swap poison_val here to guarantee it is
+                * little-endian. However for now it is a single byte so we
+                * can pass it as-is.
                 */
                if (!want_init_on_free())
                        memset(&poison_val, PAGE_POISON, sizeof(poison_val));
index 50c689f..f26f5f6 100644 (file)
@@ -101,6 +101,11 @@ struct virtio_mem {
 
        /* The parent resource for all memory added via this device. */
        struct resource *parent_resource;
+       /*
+        * Copy of "System RAM (virtio_mem)" to be used for
+        * add_memory_driver_managed().
+        */
+       const char *resource_name;
 
        /* Summary of all memory block states. */
        unsigned long nb_mb_state[VIRTIO_MEM_MB_STATE_COUNT];
@@ -414,8 +419,20 @@ static int virtio_mem_mb_add(struct virtio_mem *vm, unsigned long mb_id)
        if (nid == NUMA_NO_NODE)
                nid = memory_add_physaddr_to_nid(addr);
 
+       /*
+        * When force-unloading the driver and we still have memory added to
+        * Linux, the resource name has to stay.
+        */
+       if (!vm->resource_name) {
+               vm->resource_name = kstrdup_const("System RAM (virtio_mem)",
+                                                 GFP_KERNEL);
+               if (!vm->resource_name)
+                       return -ENOMEM;
+       }
+
        dev_dbg(&vm->vdev->dev, "adding memory block: %lu\n", mb_id);
-       return add_memory(nid, addr, memory_block_size_bytes());
+       return add_memory_driver_managed(nid, addr, memory_block_size_bytes(),
+                                        vm->resource_name);
 }
 
 /*
@@ -1192,7 +1209,7 @@ static int virtio_mem_mb_plug_any_sb(struct virtio_mem *vm, unsigned long mb_id,
                                                VIRTIO_MEM_MB_STATE_OFFLINE);
        }
 
-       return rc;
+       return 0;
 }
 
 /*
@@ -1890,10 +1907,12 @@ static void virtio_mem_remove(struct virtio_device *vdev)
            vm->nb_mb_state[VIRTIO_MEM_MB_STATE_OFFLINE_PARTIAL] ||
            vm->nb_mb_state[VIRTIO_MEM_MB_STATE_ONLINE] ||
            vm->nb_mb_state[VIRTIO_MEM_MB_STATE_ONLINE_PARTIAL] ||
-           vm->nb_mb_state[VIRTIO_MEM_MB_STATE_ONLINE_MOVABLE])
+           vm->nb_mb_state[VIRTIO_MEM_MB_STATE_ONLINE_MOVABLE]) {
                dev_warn(&vdev->dev, "device still has system memory added\n");
-       else
+       } else {
                virtio_mem_delete_resource(vm);
+               kfree_const(vm->resource_name);
+       }
 
        /* remove all tracking data - no locking needed */
        vfree(vm->mb_state);
index 9d16aaf..627ac04 100644 (file)
@@ -641,11 +641,11 @@ static int vm_cmdline_set(const char *device,
                        &vm_cmdline_id, &consumed);
 
        /*
-        * sscanf() must processes at least 2 chunks; also there
+        * sscanf() must process at least 2 chunks; also there
         * must be no extra characters after the last chunk, so
         * str[consumed] must be '\0'
         */
-       if (processed < 2 || str[consumed])
+       if (processed < 2 || str[consumed] || irq == 0)
                return -EINVAL;
 
        resources[0].flags = IORESOURCE_MEM;
index 3041092..449680a 100644 (file)
@@ -73,7 +73,7 @@ struct w1_netlink_msg
                        __u32           res;
                } mst;
        } id;
-       __u8                            data[0];
+       __u8                            data[];
 };
 
 /**
@@ -122,7 +122,7 @@ struct w1_netlink_cmd
        __u8                            cmd;
        __u8                            res;
        __u16                           len;
-       __u8                            data[0];
+       __u8                            data[];
 };
 
 #ifdef __KERNEL__
index 040d2a4..786fbb7 100644 (file)
@@ -69,11 +69,27 @@ struct xenbus_map_node {
        unsigned int   nr_handles;
 };
 
+struct map_ring_valloc {
+       struct xenbus_map_node *node;
+
+       /* Why do we need two arrays? See comment of __xenbus_map_ring */
+       union {
+               unsigned long addrs[XENBUS_MAX_RING_GRANTS];
+               pte_t *ptes[XENBUS_MAX_RING_GRANTS];
+       };
+       phys_addr_t phys_addrs[XENBUS_MAX_RING_GRANTS];
+
+       struct gnttab_map_grant_ref map[XENBUS_MAX_RING_GRANTS];
+       struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_GRANTS];
+
+       unsigned int idx;       /* HVM only. */
+};
+
 static DEFINE_SPINLOCK(xenbus_valloc_lock);
 static LIST_HEAD(xenbus_valloc_pages);
 
 struct xenbus_ring_ops {
-       int (*map)(struct xenbus_device *dev,
+       int (*map)(struct xenbus_device *dev, struct map_ring_valloc *info,
                   grant_ref_t *gnt_refs, unsigned int nr_grefs,
                   void **vaddr);
        int (*unmap)(struct xenbus_device *dev, void *vaddr);
@@ -440,8 +456,7 @@ EXPORT_SYMBOL_GPL(xenbus_free_evtchn);
  * Map @nr_grefs pages of memory into this domain from another
  * domain's grant table.  xenbus_map_ring_valloc allocates @nr_grefs
  * pages of virtual address space, maps the pages to that address, and
- * sets *vaddr to that address.  Returns 0 on success, and GNTST_*
- * (see xen/include/interface/grant_table.h) or -ENOMEM / -EINVAL on
+ * sets *vaddr to that address.  Returns 0 on success, and -errno on
  * error. If an error is returned, device will switch to
  * XenbusStateClosing and the error message will be saved in XenStore.
  */
@@ -449,12 +464,25 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, grant_ref_t *gnt_refs,
                           unsigned int nr_grefs, void **vaddr)
 {
        int err;
+       struct map_ring_valloc *info;
+
+       *vaddr = NULL;
+
+       if (nr_grefs > XENBUS_MAX_RING_GRANTS)
+               return -EINVAL;
+
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
 
-       err = ring_ops->map(dev, gnt_refs, nr_grefs, vaddr);
-       /* Some hypervisors are buggy and can return 1. */
-       if (err > 0)
-               err = GNTST_general_error;
+       info->node = kzalloc(sizeof(*info->node), GFP_KERNEL);
+       if (!info->node)
+               err = -ENOMEM;
+       else
+               err = ring_ops->map(dev, info, gnt_refs, nr_grefs, vaddr);
 
+       kfree(info->node);
+       kfree(info);
        return err;
 }
 EXPORT_SYMBOL_GPL(xenbus_map_ring_valloc);
@@ -466,62 +494,57 @@ static int __xenbus_map_ring(struct xenbus_device *dev,
                             grant_ref_t *gnt_refs,
                             unsigned int nr_grefs,
                             grant_handle_t *handles,
-                            phys_addr_t *addrs,
+                            struct map_ring_valloc *info,
                             unsigned int flags,
                             bool *leaked)
 {
-       struct gnttab_map_grant_ref map[XENBUS_MAX_RING_GRANTS];
-       struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_GRANTS];
        int i, j;
-       int err = GNTST_okay;
 
        if (nr_grefs > XENBUS_MAX_RING_GRANTS)
                return -EINVAL;
 
        for (i = 0; i < nr_grefs; i++) {
-               memset(&map[i], 0, sizeof(map[i]));
-               gnttab_set_map_op(&map[i], addrs[i], flags, gnt_refs[i],
-                                 dev->otherend_id);
+               gnttab_set_map_op(&info->map[i], info->phys_addrs[i], flags,
+                                 gnt_refs[i], dev->otherend_id);
                handles[i] = INVALID_GRANT_HANDLE;
        }
 
-       gnttab_batch_map(map, i);
+       gnttab_batch_map(info->map, i);
 
        for (i = 0; i < nr_grefs; i++) {
-               if (map[i].status != GNTST_okay) {
-                       err = map[i].status;
-                       xenbus_dev_fatal(dev, map[i].status,
+               if (info->map[i].status != GNTST_okay) {
+                       xenbus_dev_fatal(dev, info->map[i].status,
                                         "mapping in shared page %d from domain %d",
                                         gnt_refs[i], dev->otherend_id);
                        goto fail;
                } else
-                       handles[i] = map[i].handle;
+                       handles[i] = info->map[i].handle;
        }
 
-       return GNTST_okay;
+       return 0;
 
  fail:
        for (i = j = 0; i < nr_grefs; i++) {
                if (handles[i] != INVALID_GRANT_HANDLE) {
-                       memset(&unmap[j], 0, sizeof(unmap[j]));
-                       gnttab_set_unmap_op(&unmap[j], (phys_addr_t)addrs[i],
+                       gnttab_set_unmap_op(&info->unmap[j],
+                                           info->phys_addrs[i],
                                            GNTMAP_host_map, handles[i]);
                        j++;
                }
        }
 
-       if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap, j))
+       if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, info->unmap, j))
                BUG();
 
        *leaked = false;
        for (i = 0; i < j; i++) {
-               if (unmap[i].status != GNTST_okay) {
+               if (info->unmap[i].status != GNTST_okay) {
                        *leaked = true;
                        break;
                }
        }
 
-       return err;
+       return -ENOENT;
 }
 
 /**
@@ -566,21 +589,12 @@ static int xenbus_unmap_ring(struct xenbus_device *dev, grant_handle_t *handles,
        return err;
 }
 
-struct map_ring_valloc_hvm
-{
-       unsigned int idx;
-
-       /* Why do we need two arrays? See comment of __xenbus_map_ring */
-       phys_addr_t phys_addrs[XENBUS_MAX_RING_GRANTS];
-       unsigned long addrs[XENBUS_MAX_RING_GRANTS];
-};
-
 static void xenbus_map_ring_setup_grant_hvm(unsigned long gfn,
                                            unsigned int goffset,
                                            unsigned int len,
                                            void *data)
 {
-       struct map_ring_valloc_hvm *info = data;
+       struct map_ring_valloc *info = data;
        unsigned long vaddr = (unsigned long)gfn_to_virt(gfn);
 
        info->phys_addrs[info->idx] = vaddr;
@@ -589,39 +603,28 @@ static void xenbus_map_ring_setup_grant_hvm(unsigned long gfn,
        info->idx++;
 }
 
-static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev,
-                                     grant_ref_t *gnt_ref,
-                                     unsigned int nr_grefs,
-                                     void **vaddr)
+static int xenbus_map_ring_hvm(struct xenbus_device *dev,
+                              struct map_ring_valloc *info,
+                              grant_ref_t *gnt_ref,
+                              unsigned int nr_grefs,
+                              void **vaddr)
 {
-       struct xenbus_map_node *node;
+       struct xenbus_map_node *node = info->node;
        int err;
        void *addr;
        bool leaked = false;
-       struct map_ring_valloc_hvm info = {
-               .idx = 0,
-       };
        unsigned int nr_pages = XENBUS_PAGES(nr_grefs);
 
-       if (nr_grefs > XENBUS_MAX_RING_GRANTS)
-               return -EINVAL;
-
-       *vaddr = NULL;
-
-       node = kzalloc(sizeof(*node), GFP_KERNEL);
-       if (!node)
-               return -ENOMEM;
-
        err = alloc_xenballooned_pages(nr_pages, node->hvm.pages);
        if (err)
                goto out_err;
 
        gnttab_foreach_grant(node->hvm.pages, nr_grefs,
                             xenbus_map_ring_setup_grant_hvm,
-                            &info);
+                            info);
 
        err = __xenbus_map_ring(dev, gnt_ref, nr_grefs, node->handles,
-                               info.phys_addrs, GNTMAP_host_map, &leaked);
+                               info, GNTMAP_host_map, &leaked);
        node->nr_handles = nr_grefs;
 
        if (err)
@@ -641,11 +644,13 @@ static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev,
        spin_unlock(&xenbus_valloc_lock);
 
        *vaddr = addr;
+       info->node = NULL;
+
        return 0;
 
  out_xenbus_unmap_ring:
        if (!leaked)
-               xenbus_unmap_ring(dev, node->handles, nr_grefs, info.addrs);
+               xenbus_unmap_ring(dev, node->handles, nr_grefs, info->addrs);
        else
                pr_alert("leaking %p size %u page(s)",
                         addr, nr_pages);
@@ -653,7 +658,6 @@ static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev,
        if (!leaked)
                free_xenballooned_pages(nr_pages, node->hvm.pages);
  out_err:
-       kfree(node);
        return err;
 }
 
@@ -676,40 +680,28 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
 EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree);
 
 #ifdef CONFIG_XEN_PV
-static int xenbus_map_ring_valloc_pv(struct xenbus_device *dev,
-                                    grant_ref_t *gnt_refs,
-                                    unsigned int nr_grefs,
-                                    void **vaddr)
+static int xenbus_map_ring_pv(struct xenbus_device *dev,
+                             struct map_ring_valloc *info,
+                             grant_ref_t *gnt_refs,
+                             unsigned int nr_grefs,
+                             void **vaddr)
 {
-       struct xenbus_map_node *node;
+       struct xenbus_map_node *node = info->node;
        struct vm_struct *area;
-       pte_t *ptes[XENBUS_MAX_RING_GRANTS];
-       phys_addr_t phys_addrs[XENBUS_MAX_RING_GRANTS];
        int err = GNTST_okay;
        int i;
        bool leaked;
 
-       *vaddr = NULL;
-
-       if (nr_grefs > XENBUS_MAX_RING_GRANTS)
-               return -EINVAL;
-
-       node = kzalloc(sizeof(*node), GFP_KERNEL);
-       if (!node)
+       area = alloc_vm_area(XEN_PAGE_SIZE * nr_grefs, info->ptes);
+       if (!area)
                return -ENOMEM;
 
-       area = alloc_vm_area(XEN_PAGE_SIZE * nr_grefs, ptes);
-       if (!area) {
-               kfree(node);
-               return -ENOMEM;
-       }
-
        for (i = 0; i < nr_grefs; i++)
-               phys_addrs[i] = arbitrary_virt_to_machine(ptes[i]).maddr;
+               info->phys_addrs[i] =
+                       arbitrary_virt_to_machine(info->ptes[i]).maddr;
 
        err = __xenbus_map_ring(dev, gnt_refs, nr_grefs, node->handles,
-                               phys_addrs,
-                               GNTMAP_host_map | GNTMAP_contains_pte,
+                               info, GNTMAP_host_map | GNTMAP_contains_pte,
                                &leaked);
        if (err)
                goto failed;
@@ -722,6 +714,8 @@ static int xenbus_map_ring_valloc_pv(struct xenbus_device *dev,
        spin_unlock(&xenbus_valloc_lock);
 
        *vaddr = area->addr;
+       info->node = NULL;
+
        return 0;
 
 failed:
@@ -730,11 +724,10 @@ failed:
        else
                pr_alert("leaking VM area %p size %u page(s)", area, nr_grefs);
 
-       kfree(node);
        return err;
 }
 
-static int xenbus_unmap_ring_vfree_pv(struct xenbus_device *dev, void *vaddr)
+static int xenbus_unmap_ring_pv(struct xenbus_device *dev, void *vaddr)
 {
        struct xenbus_map_node *node;
        struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_GRANTS];
@@ -798,12 +791,12 @@ static int xenbus_unmap_ring_vfree_pv(struct xenbus_device *dev, void *vaddr)
 }
 
 static const struct xenbus_ring_ops ring_ops_pv = {
-       .map = xenbus_map_ring_valloc_pv,
-       .unmap = xenbus_unmap_ring_vfree_pv,
+       .map = xenbus_map_ring_pv,
+       .unmap = xenbus_unmap_ring_pv,
 };
 #endif
 
-struct unmap_ring_vfree_hvm
+struct unmap_ring_hvm
 {
        unsigned int idx;
        unsigned long addrs[XENBUS_MAX_RING_GRANTS];
@@ -814,19 +807,19 @@ static void xenbus_unmap_ring_setup_grant_hvm(unsigned long gfn,
                                              unsigned int len,
                                              void *data)
 {
-       struct unmap_ring_vfree_hvm *info = data;
+       struct unmap_ring_hvm *info = data;
 
        info->addrs[info->idx] = (unsigned long)gfn_to_virt(gfn);
 
        info->idx++;
 }
 
-static int xenbus_unmap_ring_vfree_hvm(struct xenbus_device *dev, void *vaddr)
+static int xenbus_unmap_ring_hvm(struct xenbus_device *dev, void *vaddr)
 {
        int rv;
        struct xenbus_map_node *node;
        void *addr;
-       struct unmap_ring_vfree_hvm info = {
+       struct unmap_ring_hvm info = {
                .idx = 0,
        };
        unsigned int nr_pages;
@@ -887,8 +880,8 @@ enum xenbus_state xenbus_read_driver_state(const char *path)
 EXPORT_SYMBOL_GPL(xenbus_read_driver_state);
 
 static const struct xenbus_ring_ops ring_ops_hvm = {
-       .map = xenbus_map_ring_valloc_hvm,
-       .unmap = xenbus_unmap_ring_vfree_hvm,
+       .map = xenbus_map_ring_hvm,
+       .unmap = xenbus_unmap_ring_hvm,
 };
 
 void __init xenbus_ring_ops_init(void)
index 005921e..5b79cdc 100644 (file)
@@ -154,10 +154,17 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
                return ERR_PTR(-ENOMEM);
        }
 
+       cell->name = kmalloc(namelen + 1, GFP_KERNEL);
+       if (!cell->name) {
+               kfree(cell);
+               return ERR_PTR(-ENOMEM);
+       }
+
        cell->net = net;
        cell->name_len = namelen;
        for (i = 0; i < namelen; i++)
                cell->name[i] = tolower(name[i]);
+       cell->name[i] = 0;
 
        atomic_set(&cell->usage, 2);
        INIT_WORK(&cell->manager, afs_manage_cell);
@@ -207,6 +214,7 @@ parse_failed:
        if (ret == -EINVAL)
                printk(KERN_ERR "kAFS: bad VL server IP address\n");
 error:
+       kfree(cell->name);
        kfree(cell);
        _leave(" = %d", ret);
        return ERR_PTR(ret);
@@ -489,6 +497,7 @@ static void afs_cell_destroy(struct rcu_head *rcu)
        afs_put_vlserverlist(cell->net, rcu_access_pointer(cell->vl_servers));
        afs_put_cell(cell->net, cell->alias_of);
        key_put(cell->anonymous_key);
+       kfree(cell->name);
        kfree(cell);
 
        _leave(" [destroyed]");
index aa1d341..96757f3 100644 (file)
@@ -648,7 +648,7 @@ static void afs_do_lookup_success(struct afs_operation *op)
                        vp = &op->file[0];
                        abort_code = vp->scb.status.abort_code;
                        if (abort_code != 0) {
-                               op->abort_code = abort_code;
+                               op->ac.abort_code = abort_code;
                                op->error = afs_abort_to_error(abort_code);
                        }
                        break;
@@ -696,10 +696,11 @@ static const struct afs_operation_ops afs_inline_bulk_status_operation = {
        .success        = afs_do_lookup_success,
 };
 
-static const struct afs_operation_ops afs_fetch_status_operation = {
+static const struct afs_operation_ops afs_lookup_fetch_status_operation = {
        .issue_afs_rpc  = afs_fs_fetch_status,
        .issue_yfs_rpc  = yfs_fs_fetch_status,
        .success        = afs_do_lookup_success,
+       .aborted        = afs_check_for_remote_deletion,
 };
 
 /*
@@ -844,7 +845,7 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
                 * to FS.FetchStatus for op->file[1].
                 */
                op->fetch_status.which = 1;
-               op->ops = &afs_fetch_status_operation;
+               op->ops = &afs_lookup_fetch_status_operation;
                afs_begin_vnode_operation(op);
                afs_wait_for_operation(op);
        }
@@ -1236,6 +1237,17 @@ void afs_d_release(struct dentry *dentry)
        _enter("%pd", dentry);
 }
 
+void afs_check_for_remote_deletion(struct afs_operation *op)
+{
+       struct afs_vnode *vnode = op->file[0].vnode;
+
+       switch (op->ac.abort_code) {
+       case VNOVNODE:
+               set_bit(AFS_VNODE_DELETED, &vnode->flags);
+               afs_break_callback(vnode, afs_cb_break_for_deleted);
+       }
+}
+
 /*
  * Create a new inode for create/mkdir/symlink
  */
@@ -1268,7 +1280,7 @@ static void afs_vnode_new_inode(struct afs_operation *op)
 static void afs_create_success(struct afs_operation *op)
 {
        _enter("op=%08x", op->debug_id);
-       afs_check_for_remote_deletion(op, op->file[0].vnode);
+       op->ctime = op->file[0].scb.status.mtime_client;
        afs_vnode_commit_status(op, &op->file[0]);
        afs_update_dentry_version(op, &op->file[0], op->dentry);
        afs_vnode_new_inode(op);
@@ -1302,6 +1314,7 @@ static const struct afs_operation_ops afs_mkdir_operation = {
        .issue_afs_rpc  = afs_fs_make_dir,
        .issue_yfs_rpc  = yfs_fs_make_dir,
        .success        = afs_create_success,
+       .aborted        = afs_check_for_remote_deletion,
        .edit_dir       = afs_create_edit_dir,
        .put            = afs_create_put,
 };
@@ -1325,6 +1338,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 
        afs_op_set_vnode(op, 0, dvnode);
        op->file[0].dv_delta = 1;
+       op->file[0].update_ctime = true;
        op->dentry      = dentry;
        op->create.mode = S_IFDIR | mode;
        op->create.reason = afs_edit_dir_for_mkdir;
@@ -1350,7 +1364,7 @@ static void afs_dir_remove_subdir(struct dentry *dentry)
 static void afs_rmdir_success(struct afs_operation *op)
 {
        _enter("op=%08x", op->debug_id);
-       afs_check_for_remote_deletion(op, op->file[0].vnode);
+       op->ctime = op->file[0].scb.status.mtime_client;
        afs_vnode_commit_status(op, &op->file[0]);
        afs_update_dentry_version(op, &op->file[0], op->dentry);
 }
@@ -1382,6 +1396,7 @@ static const struct afs_operation_ops afs_rmdir_operation = {
        .issue_afs_rpc  = afs_fs_remove_dir,
        .issue_yfs_rpc  = yfs_fs_remove_dir,
        .success        = afs_rmdir_success,
+       .aborted        = afs_check_for_remote_deletion,
        .edit_dir       = afs_rmdir_edit_dir,
        .put            = afs_rmdir_put,
 };
@@ -1404,6 +1419,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
 
        afs_op_set_vnode(op, 0, dvnode);
        op->file[0].dv_delta = 1;
+       op->file[0].update_ctime = true;
 
        op->dentry      = dentry;
        op->ops         = &afs_rmdir_operation;
@@ -1479,7 +1495,8 @@ static void afs_dir_remove_link(struct afs_operation *op)
 static void afs_unlink_success(struct afs_operation *op)
 {
        _enter("op=%08x", op->debug_id);
-       afs_check_for_remote_deletion(op, op->file[0].vnode);
+       op->ctime = op->file[0].scb.status.mtime_client;
+       afs_check_dir_conflict(op, &op->file[0]);
        afs_vnode_commit_status(op, &op->file[0]);
        afs_vnode_commit_status(op, &op->file[1]);
        afs_update_dentry_version(op, &op->file[0], op->dentry);
@@ -1511,6 +1528,7 @@ static const struct afs_operation_ops afs_unlink_operation = {
        .issue_afs_rpc  = afs_fs_remove_file,
        .issue_yfs_rpc  = yfs_fs_remove_file,
        .success        = afs_unlink_success,
+       .aborted        = afs_check_for_remote_deletion,
        .edit_dir       = afs_unlink_edit_dir,
        .put            = afs_unlink_put,
 };
@@ -1537,6 +1555,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
 
        afs_op_set_vnode(op, 0, dvnode);
        op->file[0].dv_delta = 1;
+       op->file[0].update_ctime = true;
 
        /* Try to make sure we have a callback promise on the victim. */
        ret = afs_validate(vnode, op->key);
@@ -1561,9 +1580,25 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
        spin_unlock(&dentry->d_lock);
 
        op->file[1].vnode = vnode;
+       op->file[1].update_ctime = true;
+       op->file[1].op_unlinked = true;
        op->dentry      = dentry;
        op->ops         = &afs_unlink_operation;
-       return afs_do_sync_operation(op);
+       afs_begin_vnode_operation(op);
+       afs_wait_for_operation(op);
+
+       /* If there was a conflict with a third party, check the status of the
+        * unlinked vnode.
+        */
+       if (op->error == 0 && (op->flags & AFS_OPERATION_DIR_CONFLICT)) {
+               op->file[1].update_ctime = false;
+               op->fetch_status.which = 1;
+               op->ops = &afs_fetch_status_operation;
+               afs_begin_vnode_operation(op);
+               afs_wait_for_operation(op);
+       }
+
+       return afs_put_operation(op);
 
 error:
        return afs_put_operation(op);
@@ -1573,6 +1608,7 @@ static const struct afs_operation_ops afs_create_operation = {
        .issue_afs_rpc  = afs_fs_create_file,
        .issue_yfs_rpc  = yfs_fs_create_file,
        .success        = afs_create_success,
+       .aborted        = afs_check_for_remote_deletion,
        .edit_dir       = afs_create_edit_dir,
        .put            = afs_create_put,
 };
@@ -1601,6 +1637,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 
        afs_op_set_vnode(op, 0, dvnode);
        op->file[0].dv_delta = 1;
+       op->file[0].update_ctime = true;
 
        op->dentry      = dentry;
        op->create.mode = S_IFREG | mode;
@@ -1620,6 +1657,7 @@ static void afs_link_success(struct afs_operation *op)
        struct afs_vnode_param *vp = &op->file[1];
 
        _enter("op=%08x", op->debug_id);
+       op->ctime = dvp->scb.status.mtime_client;
        afs_vnode_commit_status(op, dvp);
        afs_vnode_commit_status(op, vp);
        afs_update_dentry_version(op, dvp, op->dentry);
@@ -1640,6 +1678,7 @@ static const struct afs_operation_ops afs_link_operation = {
        .issue_afs_rpc  = afs_fs_link,
        .issue_yfs_rpc  = yfs_fs_link,
        .success        = afs_link_success,
+       .aborted        = afs_check_for_remote_deletion,
        .edit_dir       = afs_create_edit_dir,
        .put            = afs_link_put,
 };
@@ -1672,6 +1711,8 @@ static int afs_link(struct dentry *from, struct inode *dir,
        afs_op_set_vnode(op, 0, dvnode);
        afs_op_set_vnode(op, 1, vnode);
        op->file[0].dv_delta = 1;
+       op->file[0].update_ctime = true;
+       op->file[1].update_ctime = true;
 
        op->dentry              = dentry;
        op->dentry_2            = from;
@@ -1689,6 +1730,7 @@ static const struct afs_operation_ops afs_symlink_operation = {
        .issue_afs_rpc  = afs_fs_symlink,
        .issue_yfs_rpc  = yfs_fs_symlink,
        .success        = afs_create_success,
+       .aborted        = afs_check_for_remote_deletion,
        .edit_dir       = afs_create_edit_dir,
        .put            = afs_create_put,
 };
@@ -1740,9 +1782,13 @@ static void afs_rename_success(struct afs_operation *op)
 {
        _enter("op=%08x", op->debug_id);
 
+       op->ctime = op->file[0].scb.status.mtime_client;
+       afs_check_dir_conflict(op, &op->file[1]);
        afs_vnode_commit_status(op, &op->file[0]);
-       if (op->file[1].vnode != op->file[0].vnode)
+       if (op->file[1].vnode != op->file[0].vnode) {
+               op->ctime = op->file[1].scb.status.mtime_client;
                afs_vnode_commit_status(op, &op->file[1]);
+       }
 }
 
 static void afs_rename_edit_dir(struct afs_operation *op)
@@ -1860,6 +1906,8 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
        afs_op_set_vnode(op, 1, new_dvnode); /* May be same as orig_dvnode */
        op->file[0].dv_delta = 1;
        op->file[1].dv_delta = 1;
+       op->file[0].update_ctime = true;
+       op->file[1].update_ctime = true;
 
        op->dentry              = old_dentry;
        op->dentry_2            = new_dentry;
index b14e3d9..04f75a4 100644 (file)
@@ -16,6 +16,7 @@ static void afs_silly_rename_success(struct afs_operation *op)
 {
        _enter("op=%08x", op->debug_id);
 
+       afs_check_dir_conflict(op, &op->file[0]);
        afs_vnode_commit_status(op, &op->file[0]);
 }
 
@@ -69,6 +70,11 @@ static int afs_do_silly_rename(struct afs_vnode *dvnode, struct afs_vnode *vnode
                return PTR_ERR(op);
 
        afs_op_set_vnode(op, 0, dvnode);
+       afs_op_set_vnode(op, 1, dvnode);
+       op->file[0].dv_delta = 1;
+       op->file[1].dv_delta = 1;
+       op->file[0].update_ctime = true;
+       op->file[1].update_ctime = true;
 
        op->dentry              = old;
        op->dentry_2            = new;
@@ -129,6 +135,7 @@ int afs_sillyrename(struct afs_vnode *dvnode, struct afs_vnode *vnode,
        switch (ret) {
        case 0:
                /* The rename succeeded. */
+               set_bit(AFS_VNODE_SILLY_DELETED, &vnode->flags);
                d_move(dentry, sdentry);
                break;
        case -ERESTARTSYS:
@@ -148,19 +155,11 @@ out:
 
 static void afs_silly_unlink_success(struct afs_operation *op)
 {
-       struct afs_vnode *vnode = op->file[1].vnode;
-
        _enter("op=%08x", op->debug_id);
-       afs_check_for_remote_deletion(op, op->file[0].vnode);
+       afs_check_dir_conflict(op, &op->file[0]);
        afs_vnode_commit_status(op, &op->file[0]);
        afs_vnode_commit_status(op, &op->file[1]);
        afs_update_dentry_version(op, &op->file[0], op->dentry);
-
-       drop_nlink(&vnode->vfs_inode);
-       if (vnode->vfs_inode.i_nlink == 0) {
-               set_bit(AFS_VNODE_DELETED, &vnode->flags);
-               clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
-       }
 }
 
 static void afs_silly_unlink_edit_dir(struct afs_operation *op)
@@ -181,6 +180,7 @@ static const struct afs_operation_ops afs_silly_unlink_operation = {
        .issue_afs_rpc  = afs_fs_remove_file,
        .issue_yfs_rpc  = yfs_fs_remove_file,
        .success        = afs_silly_unlink_success,
+       .aborted        = afs_check_for_remote_deletion,
        .edit_dir       = afs_silly_unlink_edit_dir,
 };
 
@@ -200,12 +200,30 @@ static int afs_do_silly_unlink(struct afs_vnode *dvnode, struct afs_vnode *vnode
 
        afs_op_set_vnode(op, 0, dvnode);
        afs_op_set_vnode(op, 1, vnode);
+       op->file[0].dv_delta = 1;
+       op->file[0].update_ctime = true;
+       op->file[1].op_unlinked = true;
+       op->file[1].update_ctime = true;
 
        op->dentry      = dentry;
        op->ops         = &afs_silly_unlink_operation;
 
        trace_afs_silly_rename(vnode, true);
-       return afs_do_sync_operation(op);
+       afs_begin_vnode_operation(op);
+       afs_wait_for_operation(op);
+
+       /* If there was a conflict with a third party, check the status of the
+        * unlinked vnode.
+        */
+       if (op->error == 0 && (op->flags & AFS_OPERATION_DIR_CONFLICT)) {
+               op->file[1].update_ctime = false;
+               op->fetch_status.which = 1;
+               op->ops = &afs_fetch_status_operation;
+               afs_begin_vnode_operation(op);
+               afs_wait_for_operation(op);
+       }
+
+       return afs_put_operation(op);
 }
 
 /*
index 506c474..6f6ed16 100644 (file)
@@ -225,7 +225,6 @@ static void afs_fetch_data_success(struct afs_operation *op)
        struct afs_vnode *vnode = op->file[0].vnode;
 
        _enter("op=%08x", op->debug_id);
-       afs_check_for_remote_deletion(op, vnode);
        afs_vnode_commit_status(op, &op->file[0]);
        afs_stat_v(vnode, n_fetches);
        atomic_long_add(op->fetch.req->actual_len, &op->net->n_fetch_bytes);
@@ -240,6 +239,7 @@ static const struct afs_operation_ops afs_fetch_data_operation = {
        .issue_afs_rpc  = afs_fs_fetch_data,
        .issue_yfs_rpc  = yfs_fs_fetch_data,
        .success        = afs_fetch_data_success,
+       .aborted        = afs_check_for_remote_deletion,
        .put            = afs_fetch_data_put,
 };
 
index 71eea2a..ffb8575 100644 (file)
@@ -175,10 +175,7 @@ static void afs_kill_lockers_enoent(struct afs_vnode *vnode)
 
 static void afs_lock_success(struct afs_operation *op)
 {
-       struct afs_vnode *vnode = op->file[0].vnode;
-
        _enter("op=%08x", op->debug_id);
-       afs_check_for_remote_deletion(op, vnode);
        afs_vnode_commit_status(op, &op->file[0]);
 }
 
@@ -186,6 +183,7 @@ static const struct afs_operation_ops afs_set_lock_operation = {
        .issue_afs_rpc  = afs_fs_set_lock,
        .issue_yfs_rpc  = yfs_fs_set_lock,
        .success        = afs_lock_success,
+       .aborted        = afs_check_for_remote_deletion,
 };
 
 /*
index 2d2dff5..24fd163 100644 (file)
@@ -71,7 +71,7 @@ static bool afs_get_io_locks(struct afs_operation *op)
                swap(vnode, vnode2);
 
        if (mutex_lock_interruptible(&vnode->io_lock) < 0) {
-               op->error = -EINTR;
+               op->error = -ERESTARTSYS;
                op->flags |= AFS_OPERATION_STOP;
                _leave(" = f [I 0]");
                return false;
@@ -80,7 +80,7 @@ static bool afs_get_io_locks(struct afs_operation *op)
 
        if (vnode2) {
                if (mutex_lock_interruptible_nested(&vnode2->io_lock, 1) < 0) {
-                       op->error = -EINTR;
+                       op->error = -ERESTARTSYS;
                        op->flags |= AFS_OPERATION_STOP;
                        mutex_unlock(&vnode->io_lock);
                        op->flags &= ~AFS_OPERATION_LOCK_0;
@@ -187,9 +187,17 @@ void afs_wait_for_operation(struct afs_operation *op)
                op->error = afs_wait_for_call_to_complete(op->call, &op->ac);
        }
 
-       if (op->error == 0) {
+       switch (op->error) {
+       case 0:
                _debug("success");
                op->ops->success(op);
+               break;
+       case -ECONNABORTED:
+               if (op->ops->aborted)
+                       op->ops->aborted(op);
+               break;
+       default:
+               break;
        }
 
        afs_end_vnode_operation(op);
index b34f74b..5d9ef51 100644 (file)
@@ -314,7 +314,7 @@ void afs_fs_probe_timer(struct timer_list *timer)
 {
        struct afs_net *net = container_of(timer, struct afs_net, fs_probe_timer);
 
-       if (!queue_work(afs_wq, &net->fs_prober))
+       if (!net->live || !queue_work(afs_wq, &net->fs_prober))
                afs_dec_servers_outstanding(net);
 }
 
@@ -458,3 +458,12 @@ dont_wait:
                return -ETIME;
        return -EDESTADDRREQ;
 }
+
+/*
+ * Clean up the probing when the namespace is killed off.
+ */
+void afs_fs_probe_cleanup(struct afs_net *net)
+{
+       if (del_timer_sync(&net->fs_probe_timer))
+               afs_dec_servers_outstanding(net);
+}
index cd0a006..1d13d2e 100644 (file)
@@ -165,9 +165,11 @@ static void afs_apply_status(struct afs_operation *op,
 {
        struct afs_file_status *status = &vp->scb.status;
        struct afs_vnode *vnode = vp->vnode;
+       struct inode *inode = &vnode->vfs_inode;
        struct timespec64 t;
        umode_t mode;
        bool data_changed = false;
+       bool change_size = vp->set_size;
 
        _enter("{%llx:%llu.%u} %s",
               vp->fid.vid, vp->fid.vnode, vp->fid.unique,
@@ -186,25 +188,25 @@ static void afs_apply_status(struct afs_operation *op,
        }
 
        if (status->nlink != vnode->status.nlink)
-               set_nlink(&vnode->vfs_inode, status->nlink);
+               set_nlink(inode, status->nlink);
 
        if (status->owner != vnode->status.owner)
-               vnode->vfs_inode.i_uid = make_kuid(&init_user_ns, status->owner);
+               inode->i_uid = make_kuid(&init_user_ns, status->owner);
 
        if (status->group != vnode->status.group)
-               vnode->vfs_inode.i_gid = make_kgid(&init_user_ns, status->group);
+               inode->i_gid = make_kgid(&init_user_ns, status->group);
 
        if (status->mode != vnode->status.mode) {
-               mode = vnode->vfs_inode.i_mode;
+               mode = inode->i_mode;
                mode &= ~S_IALLUGO;
                mode |= status->mode;
-               WRITE_ONCE(vnode->vfs_inode.i_mode, mode);
+               WRITE_ONCE(inode->i_mode, mode);
        }
 
        t = status->mtime_client;
-       vnode->vfs_inode.i_ctime = t;
-       vnode->vfs_inode.i_mtime = t;
-       vnode->vfs_inode.i_atime = t;
+       inode->i_mtime = t;
+       if (vp->update_ctime)
+               inode->i_ctime = op->ctime;
 
        if (vnode->status.data_version != status->data_version)
                data_changed = true;
@@ -226,6 +228,7 @@ static void afs_apply_status(struct afs_operation *op,
                } else {
                        set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
                }
+               change_size = true;
        } else if (vnode->status.type == AFS_FTYPE_DIR) {
                /* Expected directory change is handled elsewhere so
                 * that we can locally edit the directory and save on a
@@ -233,11 +236,22 @@ static void afs_apply_status(struct afs_operation *op,
                 */
                if (test_bit(AFS_VNODE_DIR_VALID, &vnode->flags))
                        data_changed = false;
+               change_size = true;
        }
 
        if (data_changed) {
-               inode_set_iversion_raw(&vnode->vfs_inode, status->data_version);
-               afs_set_i_size(vnode, status->size);
+               inode_set_iversion_raw(inode, status->data_version);
+
+               /* Only update the size if the data version jumped.  If the
+                * file is being modified locally, then we might have our own
+                * idea of what the size should be that's not the same as
+                * what's on the server.
+                */
+               if (change_size) {
+                       afs_set_i_size(vnode, status->size);
+                       inode->i_ctime = t;
+                       inode->i_atime = t;
+               }
        }
 }
 
@@ -267,32 +281,39 @@ void afs_vnode_commit_status(struct afs_operation *op, struct afs_vnode_param *v
 
        _enter("");
 
-       ASSERTCMP(op->error, ==, 0);
-
        write_seqlock(&vnode->cb_lock);
 
        if (vp->scb.have_error) {
+               /* A YFS server will return this from RemoveFile2 and AFS and
+                * YFS will return this from InlineBulkStatus.
+                */
                if (vp->scb.status.abort_code == VNOVNODE) {
                        set_bit(AFS_VNODE_DELETED, &vnode->flags);
                        clear_nlink(&vnode->vfs_inode);
                        __afs_break_callback(vnode, afs_cb_break_for_deleted);
+                       op->flags &= ~AFS_OPERATION_DIR_CONFLICT;
                }
-       } else {
-               if (vp->scb.have_status)
-                       afs_apply_status(op, vp);
+       } else if (vp->scb.have_status) {
+               afs_apply_status(op, vp);
                if (vp->scb.have_cb)
                        afs_apply_callback(op, vp);
+       } else if (vp->op_unlinked && !(op->flags & AFS_OPERATION_DIR_CONFLICT)) {
+               drop_nlink(&vnode->vfs_inode);
+               if (vnode->vfs_inode.i_nlink == 0) {
+                       set_bit(AFS_VNODE_DELETED, &vnode->flags);
+                       __afs_break_callback(vnode, afs_cb_break_for_deleted);
+               }
        }
 
        write_sequnlock(&vnode->cb_lock);
 
-       if (op->error == 0 && vp->scb.have_status)
+       if (vp->scb.have_status)
                afs_cache_permit(vnode, op->key, vp->cb_break_before, &vp->scb);
 }
 
 static void afs_fetch_status_success(struct afs_operation *op)
 {
-       struct afs_vnode_param *vp = &op->file[0];
+       struct afs_vnode_param *vp = &op->file[op->fetch_status.which];
        struct afs_vnode *vnode = vp->vnode;
        int ret;
 
@@ -306,10 +327,11 @@ static void afs_fetch_status_success(struct afs_operation *op)
        }
 }
 
-static const struct afs_operation_ops afs_fetch_status_operation = {
+const struct afs_operation_ops afs_fetch_status_operation = {
        .issue_afs_rpc  = afs_fs_fetch_status,
        .issue_yfs_rpc  = yfs_fs_fetch_status,
        .success        = afs_fetch_status_success,
+       .aborted        = afs_check_for_remote_deletion,
 };
 
 /*
@@ -716,6 +738,9 @@ int afs_getattr(const struct path *path, struct kstat *stat,
        do {
                read_seqbegin_or_lock(&vnode->cb_lock, &seq);
                generic_fillattr(inode, stat);
+               if (test_bit(AFS_VNODE_SILLY_DELETED, &vnode->flags) &&
+                   stat->nlink > 0)
+                       stat->nlink -= 1;
        } while (need_seqretry(&vnode->cb_lock, seq));
 
        done_seqretry(&vnode->cb_lock, seq);
@@ -785,7 +810,15 @@ void afs_evict_inode(struct inode *inode)
 
 static void afs_setattr_success(struct afs_operation *op)
 {
+       struct inode *inode = &op->file[0].vnode->vfs_inode;
+
        afs_vnode_commit_status(op, &op->file[0]);
+       if (op->setattr.attr->ia_valid & ATTR_SIZE) {
+               loff_t i_size = inode->i_size, size = op->setattr.attr->ia_size;
+               if (size > i_size)
+                       pagecache_isize_extended(inode, i_size, size);
+               truncate_pagecache(inode, size);
+       }
 }
 
 static const struct afs_operation_ops afs_setattr_operation = {
@@ -801,17 +834,31 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr)
 {
        struct afs_operation *op;
        struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
+       int ret;
 
        _enter("{%llx:%llu},{n=%pd},%x",
               vnode->fid.vid, vnode->fid.vnode, dentry,
               attr->ia_valid);
 
        if (!(attr->ia_valid & (ATTR_SIZE | ATTR_MODE | ATTR_UID | ATTR_GID |
-                               ATTR_MTIME))) {
+                               ATTR_MTIME | ATTR_MTIME_SET | ATTR_TIMES_SET |
+                               ATTR_TOUCH))) {
                _leave(" = 0 [unsupported]");
                return 0;
        }
 
+       if (attr->ia_valid & ATTR_SIZE) {
+               if (!S_ISREG(vnode->vfs_inode.i_mode))
+                       return -EISDIR;
+
+               ret = inode_newsize_ok(&vnode->vfs_inode, attr->ia_size);
+               if (ret)
+                       return ret;
+
+               if (attr->ia_size == i_size_read(&vnode->vfs_inode))
+                       attr->ia_valid &= ~ATTR_SIZE;
+       }
+
        /* flush any dirty data outstanding on a regular file */
        if (S_ISREG(vnode->vfs_inode.i_mode))
                filemap_write_and_wait(vnode->vfs_inode.i_mapping);
@@ -825,8 +872,12 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr)
        afs_op_set_vnode(op, 0, vnode);
        op->setattr.attr = attr;
 
-       if (attr->ia_valid & ATTR_SIZE)
+       if (attr->ia_valid & ATTR_SIZE) {
                op->file[0].dv_delta = 1;
+               op->file[0].set_size = true;
+       }
+       op->ctime = attr->ia_ctime;
+       op->file[0].update_ctime = 1;
 
        op->ops = &afs_setattr_operation;
        return afs_do_sync_operation(op);
index 0c9806e..792ac71 100644 (file)
@@ -388,7 +388,7 @@ struct afs_cell {
        struct afs_vlserver_list __rcu *vl_servers;
 
        u8                      name_len;       /* Length of name */
-       char                    name[64 + 1];   /* Cell name, case-flattened and NUL-padded */
+       char                    *name;          /* Cell name, case-flattened and NUL-padded */
 };
 
 /*
@@ -634,6 +634,7 @@ struct afs_vnode {
 #define AFS_VNODE_AUTOCELL     6               /* set if Vnode is an auto mount point */
 #define AFS_VNODE_PSEUDODIR    7               /* set if Vnode is a pseudo directory */
 #define AFS_VNODE_NEW_CONTENT  8               /* Set if file has new content (create/trunc-0) */
+#define AFS_VNODE_SILLY_DELETED        9               /* Set if file has been silly-deleted */
 
        struct list_head        wb_keys;        /* List of keys available for writeback */
        struct list_head        pending_locks;  /* locks waiting to be granted */
@@ -744,8 +745,11 @@ struct afs_vnode_param {
        afs_dataversion_t       dv_before;      /* Data version before the call */
        unsigned int            cb_break_before; /* cb_break + cb_s_break before the call */
        u8                      dv_delta;       /* Expected change in data version */
-       bool                    put_vnode;      /* T if we have a ref on the vnode */
-       bool                    need_io_lock;   /* T if we need the I/O lock on this */
+       bool                    put_vnode:1;    /* T if we have a ref on the vnode */
+       bool                    need_io_lock:1; /* T if we need the I/O lock on this */
+       bool                    update_ctime:1; /* Need to update the ctime */
+       bool                    set_size:1;     /* Must update i_size */
+       bool                    op_unlinked:1;  /* True if file was unlinked by op */
 };
 
 /*
@@ -766,9 +770,9 @@ struct afs_operation {
        struct dentry           *dentry;        /* Dentry to be altered */
        struct dentry           *dentry_2;      /* Second dentry to be altered */
        struct timespec64       mtime;          /* Modification time to record */
+       struct timespec64       ctime;          /* Change time to set */
        short                   nr_files;       /* Number of entries in file[], more_files */
        short                   error;
-       unsigned int            abort_code;
        unsigned int            debug_id;
 
        unsigned int            cb_v_break;     /* Volume break counter before op */
@@ -837,6 +841,7 @@ struct afs_operation {
 #define AFS_OPERATION_LOCK_1           0x0200  /* Set if have io_lock on file[1] */
 #define AFS_OPERATION_TRIED_ALL                0x0400  /* Set if we've tried all the fileservers */
 #define AFS_OPERATION_RETRY_SERVER     0x0800  /* Set if we should retry the current server */
+#define AFS_OPERATION_DIR_CONFLICT     0x1000  /* Set if we detected a 3rd-party dir change */
 };
 
 /*
@@ -932,6 +937,7 @@ extern const struct address_space_operations afs_dir_aops;
 extern const struct dentry_operations afs_fs_dentry_operations;
 
 extern void afs_d_release(struct dentry *);
+extern void afs_check_for_remote_deletion(struct afs_operation *);
 
 /*
  * dir_edit.c
@@ -1059,10 +1065,13 @@ extern int afs_wait_for_fs_probes(struct afs_server_list *, unsigned long);
 extern void afs_probe_fileserver(struct afs_net *, struct afs_server *);
 extern void afs_fs_probe_dispatcher(struct work_struct *);
 extern int afs_wait_for_one_fs_probe(struct afs_server *, bool);
+extern void afs_fs_probe_cleanup(struct afs_net *);
 
 /*
  * inode.c
  */
+extern const struct afs_operation_ops afs_fetch_status_operation;
+
 extern void afs_vnode_commit_status(struct afs_operation *, struct afs_vnode_param *);
 extern int afs_fetch_status(struct afs_vnode *, struct key *, bool, afs_access_t *);
 extern int afs_ilookup5_test_by_fid(struct inode *, void *);
@@ -1435,7 +1444,6 @@ extern ssize_t afs_listxattr(struct dentry *, char *, size_t);
 /*
  * yfsclient.c
  */
-extern void yfs_fs_fetch_file_status(struct afs_operation *);
 extern void yfs_fs_fetch_data(struct afs_operation *);
 extern void yfs_fs_create_file(struct afs_operation *);
 extern void yfs_fs_make_dir(struct afs_operation *);
@@ -1481,15 +1489,6 @@ static inline struct inode *AFS_VNODE_TO_I(struct afs_vnode *vnode)
        return &vnode->vfs_inode;
 }
 
-static inline void afs_check_for_remote_deletion(struct afs_operation *op,
-                                                struct afs_vnode *vnode)
-{
-       if (op->error == -ENOENT) {
-               set_bit(AFS_VNODE_DELETED, &vnode->flags);
-               afs_break_callback(vnode, afs_cb_break_for_deleted);
-       }
-}
-
 /*
  * Note that a dentry got changed.  We need to set d_fsdata to the data version
  * number derived from the result of the operation.  It doesn't matter if
@@ -1504,6 +1503,18 @@ static inline void afs_update_dentry_version(struct afs_operation *op,
                        (void *)(unsigned long)dir_vp->scb.status.data_version;
 }
 
+/*
+ * Check for a conflicting operation on a directory that we just unlinked from.
+ * If someone managed to sneak a link or an unlink in on the file we just
+ * unlinked, we won't be able to trust nlink on an AFS file (but not YFS).
+ */
+static inline void afs_check_dir_conflict(struct afs_operation *op,
+                                         struct afs_vnode_param *dvp)
+{
+       if (dvp->dv_before + dvp->dv_delta != dvp->scb.status.data_version)
+               op->flags |= AFS_OPERATION_DIR_CONFLICT;
+}
+
 static inline int afs_io_error(struct afs_call *call, enum afs_io_error where)
 {
        trace_afs_io_error(call->debug_id, -EIO, where);
index 9c79c91..31b472f 100644 (file)
@@ -100,6 +100,7 @@ static int __net_init afs_net_init(struct net *net_ns)
        timer_setup(&net->fs_timer, afs_servers_timer, 0);
        INIT_WORK(&net->fs_prober, afs_fs_probe_dispatcher);
        timer_setup(&net->fs_probe_timer, afs_fs_probe_timer, 0);
+       atomic_set(&net->servers_outstanding, 1);
 
        ret = -ENOMEM;
        sysnames = kzalloc(sizeof(*sysnames), GFP_KERNEL);
@@ -130,6 +131,7 @@ static int __net_init afs_net_init(struct net *net_ns)
 
 error_open_socket:
        net->live = false;
+       afs_fs_probe_cleanup(net);
        afs_cell_purge(net);
        afs_purge_servers(net);
 error_cell_init:
@@ -150,6 +152,7 @@ static void __net_exit afs_net_exit(struct net *net_ns)
        struct afs_net *net = afs_net(net_ns);
 
        net->live = false;
+       afs_fs_probe_cleanup(net);
        afs_cell_purge(net);
        afs_purge_servers(net);
        afs_close_socket(net);
index 52b19e9..5334f1b 100644 (file)
@@ -83,6 +83,7 @@ int afs_abort_to_error(u32 abort_code)
        case UAENOLCK:                  return -ENOLCK;
        case UAENOTEMPTY:               return -ENOTEMPTY;
        case UAELOOP:                   return -ELOOP;
+       case UAEOVERFLOW:               return -EOVERFLOW;
        case UAENOMEDIUM:               return -ENOMEDIUM;
        case UAEDQUOT:                  return -EDQUOT;
 
index 039e348..e82e452 100644 (file)
@@ -605,11 +605,12 @@ void afs_purge_servers(struct afs_net *net)
        _enter("");
 
        if (del_timer_sync(&net->fs_timer))
-               atomic_dec(&net->servers_outstanding);
+               afs_dec_servers_outstanding(net);
 
        afs_queue_server_manager(net);
 
        _debug("wait");
+       atomic_dec(&net->servers_outstanding);
        wait_var_event(&net->servers_outstanding,
                       !atomic_read(&net->servers_outstanding));
        _leave("");
index 768497f..a121c24 100644 (file)
@@ -194,11 +194,11 @@ int afs_write_end(struct file *file, struct address_space *mapping,
 
        i_size = i_size_read(&vnode->vfs_inode);
        if (maybe_i_size > i_size) {
-               spin_lock(&vnode->wb_lock);
+               write_seqlock(&vnode->cb_lock);
                i_size = i_size_read(&vnode->vfs_inode);
                if (maybe_i_size > i_size)
                        i_size_write(&vnode->vfs_inode, maybe_i_size);
-               spin_unlock(&vnode->wb_lock);
+               write_sequnlock(&vnode->cb_lock);
        }
 
        if (!PageUptodate(page)) {
@@ -393,6 +393,7 @@ static void afs_store_data_success(struct afs_operation *op)
 {
        struct afs_vnode *vnode = op->file[0].vnode;
 
+       op->ctime = op->file[0].scb.status.mtime_client;
        afs_vnode_commit_status(op, &op->file[0]);
        if (op->error == 0) {
                afs_pages_written_back(vnode, op->store.first, op->store.last);
@@ -448,6 +449,7 @@ static int afs_store_data(struct address_space *mapping,
        op->store.first_offset = offset;
        op->store.last_to = to;
        op->mtime = vnode->vfs_inode.i_mtime;
+       op->flags |= AFS_OPERATION_UNINTR;
        op->ops = &afs_store_data_operation;
 
 try_next_key:
@@ -491,6 +493,7 @@ static int afs_write_back_from_locked_page(struct address_space *mapping,
        unsigned long count, priv;
        unsigned n, offset, to, f, t;
        pgoff_t start, first, last;
+       loff_t i_size, end;
        int loop, ret;
 
        _enter(",%lx", primary_page->index);
@@ -591,7 +594,12 @@ no_more:
        first = primary_page->index;
        last = first + count - 1;
 
+       end = (loff_t)last * PAGE_SIZE + to;
+       i_size = i_size_read(&vnode->vfs_inode);
+
        _debug("write back %lx[%u..] to %lx[..%u]", first, offset, last, to);
+       if (end > i_size)
+               to = i_size & ~PAGE_MASK;
 
        ret = afs_store_data(mapping, first, last, offset, to);
        switch (ret) {
@@ -844,6 +852,7 @@ vm_fault_t afs_page_mkwrite(struct vm_fault *vmf)
                             vmf->page->index, priv);
        SetPagePrivate(vmf->page);
        set_page_private(vmf->page, priv);
+       file_update_time(file);
 
        sb_end_pagefault(inode->i_sb);
        return VM_FAULT_LOCKED;
index 52d5af5..8c24fdc 100644 (file)
@@ -329,29 +329,6 @@ static void xdr_decode_YFSFetchVolumeStatus(const __be32 **_bp,
        *_bp += sizeof(*x) / sizeof(__be32);
 }
 
-/*
- * Deliver a reply that's a status, callback and volsync.
- */
-static int yfs_deliver_fs_status_cb_and_volsync(struct afs_call *call)
-{
-       struct afs_operation *op = call->op;
-       const __be32 *bp;
-       int ret;
-
-       ret = afs_transfer_reply(call);
-       if (ret < 0)
-               return ret;
-
-       /* unmarshall the reply once we've received all of it */
-       bp = call->buffer;
-       xdr_decode_YFSFetchStatus(&bp, call, &op->file[0].scb);
-       xdr_decode_YFSCallBack(&bp, call, &op->file[0].scb);
-       xdr_decode_YFSVolSync(&bp, &op->volsync);
-
-       _leave(" = 0 [done]");
-       return 0;
-}
-
 /*
  * Deliver reply data to operations that just return a file status and a volume
  * sync record.
@@ -374,48 +351,6 @@ static int yfs_deliver_status_and_volsync(struct afs_call *call)
        return 0;
 }
 
-/*
- * YFS.FetchStatus operation type
- */
-static const struct afs_call_type yfs_RXYFSFetchStatus_vnode = {
-       .name           = "YFS.FetchStatus(vnode)",
-       .op             = yfs_FS_FetchStatus,
-       .deliver        = yfs_deliver_fs_status_cb_and_volsync,
-       .destructor     = afs_flat_call_destructor,
-};
-
-/*
- * Fetch the status information for a file.
- */
-void yfs_fs_fetch_file_status(struct afs_operation *op)
-{
-       struct afs_vnode_param *vp = &op->file[0];
-       struct afs_call *call;
-       __be32 *bp;
-
-       _enter(",%x,{%llx:%llu},,",
-              key_serial(op->key), vp->fid.vid, vp->fid.vnode);
-
-       call = afs_alloc_flat_call(op->net, &yfs_RXYFSFetchStatus_vnode,
-                                  sizeof(__be32) * 2 +
-                                  sizeof(struct yfs_xdr_YFSFid),
-                                  sizeof(struct yfs_xdr_YFSFetchStatus) +
-                                  sizeof(struct yfs_xdr_YFSCallBack) +
-                                  sizeof(struct yfs_xdr_YFSVolSync));
-       if (!call)
-               return afs_op_nomem(op);
-
-       /* marshall the parameters */
-       bp = call->request;
-       bp = xdr_encode_u32(bp, YFSFETCHSTATUS);
-       bp = xdr_encode_u32(bp, 0); /* RPC flags */
-       bp = xdr_encode_YFSFid(bp, &vp->fid);
-       yfs_check_req(call, bp);
-
-       trace_afs_make_fs_call(call, &vp->fid);
-       afs_make_op_call(op, call, GFP_NOFS);
-}
-
 /*
  * Deliver reply data to an YFS.FetchData64.
  */
@@ -1604,13 +1539,37 @@ void yfs_fs_release_lock(struct afs_operation *op)
        afs_make_op_call(op, call, GFP_NOFS);
 }
 
+/*
+ * Deliver a reply to YFS.FetchStatus
+ */
+static int yfs_deliver_fs_fetch_status(struct afs_call *call)
+{
+       struct afs_operation *op = call->op;
+       struct afs_vnode_param *vp = &op->file[op->fetch_status.which];
+       const __be32 *bp;
+       int ret;
+
+       ret = afs_transfer_reply(call);
+       if (ret < 0)
+               return ret;
+
+       /* unmarshall the reply once we've received all of it */
+       bp = call->buffer;
+       xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);
+       xdr_decode_YFSCallBack(&bp, call, &vp->scb);
+       xdr_decode_YFSVolSync(&bp, &op->volsync);
+
+       _leave(" = 0 [done]");
+       return 0;
+}
+
 /*
  * YFS.FetchStatus operation type
  */
 static const struct afs_call_type yfs_RXYFSFetchStatus = {
        .name           = "YFS.FetchStatus",
        .op             = yfs_FS_FetchStatus,
-       .deliver        = yfs_deliver_fs_status_cb_and_volsync,
+       .deliver        = yfs_deliver_fs_fetch_status,
        .destructor     = afs_flat_call_destructor,
 };
 
@@ -1619,7 +1578,7 @@ static const struct afs_call_type yfs_RXYFSFetchStatus = {
  */
 void yfs_fs_fetch_status(struct afs_operation *op)
 {
-       struct afs_vnode_param *vp = &op->file[0];
+       struct afs_vnode_param *vp = &op->file[op->fetch_status.which];
        struct afs_call *call;
        __be32 *bp;
 
index 7ecddc2..91e7cc4 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -67,7 +67,7 @@ struct aio_ring {
        unsigned        header_length;  /* size of aio_ring */
 
 
-       struct io_event         io_events[0];
+       struct io_event         io_events[];
 }; /* 128 bytes + ring size */
 
 /*
index b04c528..74c886f 100644 (file)
@@ -53,7 +53,7 @@ static int autofs_write(struct autofs_sb_info *sbi,
 
        mutex_lock(&sbi->pipe_mutex);
        while (bytes) {
-               wr = __kernel_write(file, data, bytes, &file->f_pos);
+               wr = kernel_write(file, data, bytes, &file->f_pos);
                if (wr <= 0)
                        break;
                data += wr;
index 47860e5..0ae656e 100644 (file)
@@ -75,7 +75,7 @@ static void bdev_write_inode(struct block_device *bdev)
 }
 
 /* Kill _all_ buffers and pagecache , dirty or not.. */
-void kill_bdev(struct block_device *bdev)
+static void kill_bdev(struct block_device *bdev)
 {
        struct address_space *mapping = bdev->bd_inode->i_mapping;
 
@@ -84,8 +84,7 @@ void kill_bdev(struct block_device *bdev)
 
        invalidate_bh_lrus();
        truncate_inode_pages(mapping, 0);
-}      
-EXPORT_SYMBOL(kill_bdev);
+}
 
 /* Invalidate clean unused buffers and pagecache. */
 void invalidate_bdev(struct block_device *bdev)
@@ -1565,10 +1564,8 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
         */
        if (!for_part) {
                ret = devcgroup_inode_permission(bdev->bd_inode, perm);
-               if (ret != 0) {
-                       bdput(bdev);
+               if (ret != 0)
                        return ret;
-               }
        }
 
  restart:
@@ -1637,8 +1634,10 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                                goto out_clear;
                        BUG_ON(for_part);
                        ret = __blkdev_get(whole, mode, 1);
-                       if (ret)
+                       if (ret) {
+                               bdput(whole);
                                goto out_clear;
+                       }
                        bdev->bd_contains = whole;
                        bdev->bd_part = disk_get_part(disk, partno);
                        if (!(disk->flags & GENHD_FL_UP) ||
@@ -1688,7 +1687,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
        disk_unblock_events(disk);
        put_disk_and_module(disk);
  out:
-       bdput(bdev);
 
        return ret;
 }
@@ -1755,6 +1753,9 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)
                bdput(whole);
        }
 
+       if (res)
+               bdput(bdev);
+
        return res;
 }
 EXPORT_SYMBOL(blkdev_get);
index d888e71..ea10f7b 100644 (file)
@@ -1461,6 +1461,7 @@ static int btrfs_find_all_roots_safe(struct btrfs_trans_handle *trans,
                if (ret < 0 && ret != -ENOENT) {
                        ulist_free(tmp);
                        ulist_free(*roots);
+                       *roots = NULL;
                        return ret;
                }
                node = ulist_next(tmp, &uiter);
index 176e8a2..c037ef5 100644 (file)
@@ -940,7 +940,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
        path = btrfs_alloc_path();
        if (!path) {
                ret = -ENOMEM;
-               goto out_put_group;
+               goto out;
        }
 
        /*
@@ -978,7 +978,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
                ret = btrfs_orphan_add(trans, BTRFS_I(inode));
                if (ret) {
                        btrfs_add_delayed_iput(inode);
-                       goto out_put_group;
+                       goto out;
                }
                clear_nlink(inode);
                /* One for the block groups ref */
@@ -1001,13 +1001,13 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
 
        ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1);
        if (ret < 0)
-               goto out_put_group;
+               goto out;
        if (ret > 0)
                btrfs_release_path(path);
        if (ret == 0) {
                ret = btrfs_del_item(trans, tree_root, path);
                if (ret)
-                       goto out_put_group;
+                       goto out;
                btrfs_release_path(path);
        }
 
@@ -1016,6 +1016,9 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
                 &fs_info->block_group_cache_tree);
        RB_CLEAR_NODE(&block_group->cache_node);
 
+       /* Once for the block groups rbtree */
+       btrfs_put_block_group(block_group);
+
        if (fs_info->first_logical_byte == block_group->start)
                fs_info->first_logical_byte = (u64)-1;
        spin_unlock(&fs_info->block_group_cache_lock);
@@ -1089,6 +1092,25 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
 
        spin_unlock(&block_group->space_info->lock);
 
+       /*
+        * Remove the free space for the block group from the free space tree
+        * and the block group's item from the extent tree before marking the
+        * block group as removed. This is to prevent races with tasks that
+        * freeze and unfreeze a block group, this task and another task
+        * allocating a new block group - the unfreeze task ends up removing
+        * the block group's extent map before the task calling this function
+        * deletes the block group item from the extent tree, allowing for
+        * another task to attempt to create another block group with the same
+        * item key (and failing with -EEXIST and a transaction abort).
+        */
+       ret = remove_block_group_free_space(trans, block_group);
+       if (ret)
+               goto out;
+
+       ret = remove_block_group_item(trans, path, block_group);
+       if (ret < 0)
+               goto out;
+
        mutex_lock(&fs_info->chunk_mutex);
        spin_lock(&block_group->lock);
        block_group->removed = 1;
@@ -1123,17 +1145,6 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
 
        mutex_unlock(&fs_info->chunk_mutex);
 
-       ret = remove_block_group_free_space(trans, block_group);
-       if (ret)
-               goto out_put_group;
-
-       /* Once for the block groups rbtree */
-       btrfs_put_block_group(block_group);
-
-       ret = remove_block_group_item(trans, path, block_group);
-       if (ret < 0)
-               goto out;
-
        if (remove_em) {
                struct extent_map_tree *em_tree;
 
@@ -1145,10 +1156,9 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
                free_extent_map(em);
        }
 
-out_put_group:
+out:
        /* Once for the lookup reference */
        btrfs_put_block_group(block_group);
-out:
        if (remove_rsv)
                btrfs_delayed_refs_rsv_release(fs_info, 1);
        btrfs_free_path(path);
index 3a7648b..82ab6e5 100644 (file)
@@ -1196,7 +1196,7 @@ __tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb,
                switch (tm->op) {
                case MOD_LOG_KEY_REMOVE_WHILE_FREEING:
                        BUG_ON(tm->slot < n);
-                       /* Fallthrough */
+                       fallthrough;
                case MOD_LOG_KEY_REMOVE_WHILE_MOVING:
                case MOD_LOG_KEY_REMOVE:
                        btrfs_set_node_key(eb, &tm->key, tm->slot);
index 30ce703..d404cce 100644 (file)
@@ -1009,6 +1009,8 @@ enum {
        BTRFS_ROOT_DEAD_RELOC_TREE,
        /* Mark dead root stored on device whose cleanup needs to be resumed */
        BTRFS_ROOT_DEAD_TREE,
+       /* The root has a log tree. Used only for subvolume roots. */
+       BTRFS_ROOT_HAS_LOG_TREE,
 };
 
 /*
index 5615320..741c7e1 100644 (file)
@@ -619,6 +619,7 @@ void btrfs_discard_punt_unused_bgs_list(struct btrfs_fs_info *fs_info)
        list_for_each_entry_safe(block_group, next, &fs_info->unused_bgs,
                                 bg_list) {
                list_del_init(&block_group->bg_list);
+               btrfs_put_block_group(block_group);
                btrfs_discard_queue_work(&fs_info->discard_ctl, block_group);
        }
        spin_unlock(&fs_info->unused_bgs_lock);
index 7c6f0bb..b1a1480 100644 (file)
@@ -2593,10 +2593,12 @@ static int __cold init_tree_roots(struct btrfs_fs_info *fs_info)
                    !extent_buffer_uptodate(tree_root->node)) {
                        handle_error = true;
 
-                       if (IS_ERR(tree_root->node))
+                       if (IS_ERR(tree_root->node)) {
                                ret = PTR_ERR(tree_root->node);
-                       else if (!extent_buffer_uptodate(tree_root->node))
+                               tree_root->node = NULL;
+                       } else if (!extent_buffer_uptodate(tree_root->node)) {
                                ret = -EUCLEAN;
+                       }
 
                        btrfs_warn(fs_info, "failed to read tree root");
                        continue;
index 68c9605..60278e5 100644 (file)
@@ -1999,7 +1999,8 @@ static int __process_pages_contig(struct address_space *mapping,
                                if (!PageDirty(pages[i]) ||
                                    pages[i]->mapping != mapping) {
                                        unlock_page(pages[i]);
-                                       put_page(pages[i]);
+                                       for (; i < ret; i++)
+                                               put_page(pages[i]);
                                        err = -EAGAIN;
                                        goto out;
                                }
@@ -5058,25 +5059,28 @@ struct extent_buffer *alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info,
 static void check_buffer_tree_ref(struct extent_buffer *eb)
 {
        int refs;
-       /* the ref bit is tricky.  We have to make sure it is set
-        * if we have the buffer dirty.   Otherwise the
-        * code to free a buffer can end up dropping a dirty
-        * page
+       /*
+        * The TREE_REF bit is first set when the extent_buffer is added
+        * to the radix tree. It is also reset, if unset, when a new reference
+        * is created by find_extent_buffer.
         *
-        * Once the ref bit is set, it won't go away while the
-        * buffer is dirty or in writeback, and it also won't
-        * go away while we have the reference count on the
-        * eb bumped.
+        * It is only cleared in two cases: freeing the last non-tree
+        * reference to the extent_buffer when its STALE bit is set or
+        * calling releasepage when the tree reference is the only reference.
         *
-        * We can't just set the ref bit without bumping the
-        * ref on the eb because free_extent_buffer might
-        * see the ref bit and try to clear it.  If this happens
-        * free_extent_buffer might end up dropping our original
-        * ref by mistake and freeing the page before we are able
-        * to add one more ref.
+        * In both cases, care is taken to ensure that the extent_buffer's
+        * pages are not under io. However, releasepage can be concurrently
+        * called with creating new references, which is prone to race
+        * conditions between the calls to check_buffer_tree_ref in those
+        * codepaths and clearing TREE_REF in try_release_extent_buffer.
         *
-        * So bump the ref count first, then set the bit.  If someone
-        * beat us to it, drop the ref we added.
+        * The actual lifetime of the extent_buffer in the radix tree is
+        * adequately protected by the refcount, but the TREE_REF bit and
+        * its corresponding reference are not. To protect against this
+        * class of races, we call check_buffer_tree_ref from the codepaths
+        * which trigger io after they set eb->io_pages. Note that once io is
+        * initiated, TREE_REF can no longer be cleared, so that is the
+        * moment at which any such race is best fixed.
         */
        refs = atomic_read(&eb->refs);
        if (refs >= 2 && test_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags))
@@ -5527,6 +5531,11 @@ int read_extent_buffer_pages(struct extent_buffer *eb, int wait, int mirror_num)
        clear_bit(EXTENT_BUFFER_READ_ERR, &eb->bflags);
        eb->read_mirror = 0;
        atomic_set(&eb->io_pages, num_reads);
+       /*
+        * It is possible for releasepage to clear the TREE_REF bit before we
+        * set io_pages. See check_buffer_tree_ref for a more detailed comment.
+        */
+       check_buffer_tree_ref(eb);
        for (i = 0; i < num_pages; i++) {
                page = eb->pages[i];
 
index 2c14312..b0d2c97 100644 (file)
@@ -1533,7 +1533,7 @@ lock_and_cleanup_extent_if_need(struct btrfs_inode *inode, struct page **pages,
 }
 
 static noinline int check_can_nocow(struct btrfs_inode *inode, loff_t pos,
-                                   size_t *write_bytes)
+                                   size_t *write_bytes, bool nowait)
 {
        struct btrfs_fs_info *fs_info = inode->root->fs_info;
        struct btrfs_root *root = inode->root;
@@ -1541,27 +1541,43 @@ static noinline int check_can_nocow(struct btrfs_inode *inode, loff_t pos,
        u64 num_bytes;
        int ret;
 
-       if (!btrfs_drew_try_write_lock(&root->snapshot_lock))
+       if (!nowait && !btrfs_drew_try_write_lock(&root->snapshot_lock))
                return -EAGAIN;
 
        lockstart = round_down(pos, fs_info->sectorsize);
        lockend = round_up(pos + *write_bytes,
                           fs_info->sectorsize) - 1;
+       num_bytes = lockend - lockstart + 1;
 
-       btrfs_lock_and_flush_ordered_range(inode, lockstart,
-                                          lockend, NULL);
+       if (nowait) {
+               struct btrfs_ordered_extent *ordered;
+
+               if (!try_lock_extent(&inode->io_tree, lockstart, lockend))
+                       return -EAGAIN;
+
+               ordered = btrfs_lookup_ordered_range(inode, lockstart,
+                                                    num_bytes);
+               if (ordered) {
+                       btrfs_put_ordered_extent(ordered);
+                       ret = -EAGAIN;
+                       goto out_unlock;
+               }
+       } else {
+               btrfs_lock_and_flush_ordered_range(inode, lockstart,
+                                                  lockend, NULL);
+       }
 
-       num_bytes = lockend - lockstart + 1;
        ret = can_nocow_extent(&inode->vfs_inode, lockstart, &num_bytes,
                        NULL, NULL, NULL);
        if (ret <= 0) {
                ret = 0;
-               btrfs_drew_write_unlock(&root->snapshot_lock);
+               if (!nowait)
+                       btrfs_drew_write_unlock(&root->snapshot_lock);
        } else {
                *write_bytes = min_t(size_t, *write_bytes ,
                                     num_bytes - pos + lockstart);
        }
-
+out_unlock:
        unlock_extent(&inode->io_tree, lockstart, lockend);
 
        return ret;
@@ -1633,7 +1649,7 @@ static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
                        if ((BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
                                                      BTRFS_INODE_PREALLOC)) &&
                            check_can_nocow(BTRFS_I(inode), pos,
-                                       &write_bytes) > 0) {
+                                           &write_bytes, false) > 0) {
                                /*
                                 * For nodata cow case, no need to reserve
                                 * data space.
@@ -1904,13 +1920,25 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
        pos = iocb->ki_pos;
        count = iov_iter_count(from);
        if (iocb->ki_flags & IOCB_NOWAIT) {
+               size_t nocow_bytes = count;
+
                /*
                 * We will allocate space in case nodatacow is not set,
                 * so bail
                 */
                if (!(BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
                                              BTRFS_INODE_PREALLOC)) ||
-                   check_can_nocow(BTRFS_I(inode), pos, &count) <= 0) {
+                   check_can_nocow(BTRFS_I(inode), pos, &nocow_bytes,
+                                   true) <= 0) {
+                       inode_unlock(inode);
+                       return -EAGAIN;
+               }
+               /*
+                * There are holes in the range or parts of the range that must
+                * be COWed (shared extents, RO block groups, etc), so just bail
+                * out.
+                */
+               if (nocow_bytes < count) {
                        inode_unlock(inode);
                        return -EAGAIN;
                }
@@ -3481,6 +3509,7 @@ const struct file_operations btrfs_file_operations = {
        .read_iter      = generic_file_read_iter,
        .splice_read    = generic_file_splice_read,
        .write_iter     = btrfs_file_write_iter,
+       .splice_write   = iter_file_splice_write,
        .mmap           = btrfs_file_mmap,
        .open           = btrfs_file_open,
        .release        = btrfs_release_file,
index d04c82c..6862cd7 100644 (file)
@@ -985,6 +985,7 @@ static noinline int cow_file_range(struct inode *inode,
        u64 num_bytes;
        unsigned long ram_size;
        u64 cur_alloc_size = 0;
+       u64 min_alloc_size;
        u64 blocksize = fs_info->sectorsize;
        struct btrfs_key ins;
        struct extent_map *em;
@@ -1035,10 +1036,26 @@ static noinline int cow_file_range(struct inode *inode,
        btrfs_drop_extent_cache(BTRFS_I(inode), start,
                        start + num_bytes - 1, 0);
 
+       /*
+        * Relocation relies on the relocated extents to have exactly the same
+        * size as the original extents. Normally writeback for relocation data
+        * extents follows a NOCOW path because relocation preallocates the
+        * extents. However, due to an operation such as scrub turning a block
+        * group to RO mode, it may fallback to COW mode, so we must make sure
+        * an extent allocated during COW has exactly the requested size and can
+        * not be split into smaller extents, otherwise relocation breaks and
+        * fails during the stage where it updates the bytenr of file extent
+        * items.
+        */
+       if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID)
+               min_alloc_size = num_bytes;
+       else
+               min_alloc_size = fs_info->sectorsize;
+
        while (num_bytes > 0) {
                cur_alloc_size = num_bytes;
                ret = btrfs_reserve_extent(root, cur_alloc_size, cur_alloc_size,
-                                          fs_info->sectorsize, 0, alloc_hint,
+                                          min_alloc_size, 0, alloc_hint,
                                           &ins, 1, 1);
                if (ret < 0)
                        goto out_unlock;
@@ -1361,6 +1378,8 @@ static int fallback_to_cow(struct inode *inode, struct page *locked_page,
                           int *page_started, unsigned long *nr_written)
 {
        const bool is_space_ino = btrfs_is_free_space_inode(BTRFS_I(inode));
+       const bool is_reloc_ino = (BTRFS_I(inode)->root->root_key.objectid ==
+                                  BTRFS_DATA_RELOC_TREE_OBJECTID);
        const u64 range_bytes = end + 1 - start;
        struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
        u64 range_start = start;
@@ -1391,18 +1410,23 @@ static int fallback_to_cow(struct inode *inode, struct page *locked_page,
         *    data space info, which we incremented in the step above.
         *
         * If we need to fallback to cow and the inode corresponds to a free
-        * space cache inode, we must also increment bytes_may_use of the data
-        * space_info for the same reason. Space caches always get a prealloc
+        * space cache inode or an inode of the data relocation tree, we must
+        * also increment bytes_may_use of the data space_info for the same
+        * reason. Space caches and relocated data extents always get a prealloc
         * extent for them, however scrub or balance may have set the block
-        * group that contains that extent to RO mode.
+        * group that contains that extent to RO mode and therefore force COW
+        * when starting writeback.
         */
        count = count_range_bits(io_tree, &range_start, end, range_bytes,
                                 EXTENT_NORESERVE, 0);
-       if (count > 0 || is_space_ino) {
-               const u64 bytes = is_space_ino ? range_bytes : count;
+       if (count > 0 || is_space_ino || is_reloc_ino) {
+               u64 bytes = count;
                struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info;
                struct btrfs_space_info *sinfo = fs_info->data_sinfo;
 
+               if (is_space_ino || is_reloc_ino)
+                       bytes = range_bytes;
+
                spin_lock(&sinfo->lock);
                btrfs_space_info_update_bytes_may_use(fs_info, sinfo, bytes);
                spin_unlock(&sinfo->lock);
@@ -1666,12 +1690,8 @@ out_check:
                        ret = fallback_to_cow(inode, locked_page, cow_start,
                                              found_key.offset - 1,
                                              page_started, nr_written);
-                       if (ret) {
-                               if (nocow)
-                                       btrfs_dec_nocow_writers(fs_info,
-                                                               disk_bytenr);
+                       if (ret)
                                goto error;
-                       }
                        cow_start = (u64)-1;
                }
 
@@ -1687,9 +1707,6 @@ out_check:
                                          ram_bytes, BTRFS_COMPRESS_NONE,
                                          BTRFS_ORDERED_PREALLOC);
                        if (IS_ERR(em)) {
-                               if (nocow)
-                                       btrfs_dec_nocow_writers(fs_info,
-                                                               disk_bytenr);
                                ret = PTR_ERR(em);
                                goto error;
                        }
@@ -7865,9 +7882,6 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
                        dio_data.overwrite = 1;
                        inode_unlock(inode);
                        relock = true;
-               } else if (iocb->ki_flags & IOCB_NOWAIT) {
-                       ret = -EAGAIN;
-                       goto out;
                }
                ret = btrfs_delalloc_reserve_space(inode, &data_reserved,
                                                   offset, count);
@@ -8109,20 +8123,17 @@ again:
        /*
         * Qgroup reserved space handler
         * Page here will be either
-        * 1) Already written to disk
-        *    In this case, its reserved space is released from data rsv map
-        *    and will be freed by delayed_ref handler finally.
-        *    So even we call qgroup_free_data(), it won't decrease reserved
-        *    space.
-        * 2) Not written to disk
-        *    This means the reserved space should be freed here. However,
-        *    if a truncate invalidates the page (by clearing PageDirty)
-        *    and the page is accounted for while allocating extent
-        *    in btrfs_check_data_free_space() we let delayed_ref to
-        *    free the entire extent.
+        * 1) Already written to disk or ordered extent already submitted
+        *    Then its QGROUP_RESERVED bit in io_tree is already cleaned.
+        *    Qgroup will be handled by its qgroup_record then.
+        *    btrfs_qgroup_free_data() call will do nothing here.
+        *
+        * 2) Not written to disk yet
+        *    Then btrfs_qgroup_free_data() call will clear the QGROUP_RESERVED
+        *    bit of its io_tree, and free the qgroup reserved data space.
+        *    Since the IO will never happen for this page.
         */
-       if (PageDirty(page))
-               btrfs_qgroup_free_data(inode, NULL, page_start, PAGE_SIZE);
+       btrfs_qgroup_free_data(inode, NULL, page_start, PAGE_SIZE);
        if (!inode_evicting) {
                clear_extent_bit(tree, page_start, page_end, EXTENT_LOCKED |
                                 EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
index 168deb8..e8f7c5f 100644 (file)
@@ -2692,7 +2692,7 @@ out:
        btrfs_put_root(root);
 out_free:
        btrfs_free_path(path);
-       kzfree(subvol_info);
+       kfree(subvol_info);
        return ret;
 }
 
index 7887317..af92525 100644 (file)
@@ -509,7 +509,7 @@ static int process_leaf(struct btrfs_root *root,
                switch (key.type) {
                case BTRFS_EXTENT_ITEM_KEY:
                        *num_bytes = key.offset;
-                       /* fall through */
+                       fallthrough;
                case BTRFS_METADATA_ITEM_KEY:
                        *bytenr = key.objectid;
                        ret = process_extent_item(fs_info, path, &key, i,
index 41ee886..c7bd3fd 100644 (file)
@@ -879,8 +879,8 @@ static bool steal_from_global_rsv(struct btrfs_fs_info *fs_info,
                return false;
        }
        global_rsv->reserved -= ticket->bytes;
+       remove_ticket(space_info, ticket);
        ticket->bytes = 0;
-       list_del_init(&ticket->list);
        wake_up(&ticket->wait);
        space_info->tickets_id++;
        if (global_rsv->reserved < global_rsv->size)
index bc73fd6..c3826ae 100644 (file)
@@ -523,7 +523,7 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
                case Opt_compress_force:
                case Opt_compress_force_type:
                        compress_force = true;
-                       /* Fallthrough */
+                       fallthrough;
                case Opt_compress:
                case Opt_compress_type:
                        saved_compress_type = btrfs_test_opt(info,
@@ -622,7 +622,7 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
                        btrfs_set_opt(info->mount_opt, NOSSD);
                        btrfs_clear_and_info(info, SSD,
                                             "not using ssd optimizations");
-                       /* Fallthrough */
+                       fallthrough;
                case Opt_nossd_spread:
                        btrfs_clear_and_info(info, SSD_SPREAD,
                                             "not using spread ssd allocation scheme");
@@ -793,7 +793,7 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
                case Opt_recovery:
                        btrfs_warn(info,
                                   "'recovery' is deprecated, use 'usebackuproot' instead");
-                       /* fall through */
+                       fallthrough;
                case Opt_usebackuproot:
                        btrfs_info(info,
                                   "trying to use backup root at mount time");
index 920cee3..cd5348f 100644 (file)
@@ -169,6 +169,7 @@ static int start_log_trans(struct btrfs_trans_handle *trans,
                if (ret)
                        goto out;
 
+               set_bit(BTRFS_ROOT_HAS_LOG_TREE, &root->state);
                clear_bit(BTRFS_ROOT_MULTI_LOG_TASKS, &root->state);
                root->log_start_pid = current->pid;
        }
@@ -195,6 +196,9 @@ static int join_running_log_trans(struct btrfs_root *root)
 {
        int ret = -ENOENT;
 
+       if (!test_bit(BTRFS_ROOT_HAS_LOG_TREE, &root->state))
+               return ret;
+
        mutex_lock(&root->log_mutex);
        if (root->log_root) {
                ret = 0;
@@ -3303,6 +3307,7 @@ int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root)
        if (root->log_root) {
                free_log_tree(trans, root->log_root);
                root->log_root = NULL;
+               clear_bit(BTRFS_ROOT_HAS_LOG_TREE, &root->state);
        }
        return 0;
 }
index 0d6e785..f403fb1 100644 (file)
@@ -7051,6 +7051,14 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
        mutex_lock(&uuid_mutex);
        mutex_lock(&fs_info->chunk_mutex);
 
+       /*
+        * It is possible for mount and umount to race in such a way that
+        * we execute this code path, but open_fs_devices failed to clear
+        * total_rw_bytes. We certainly want it cleared before reading the
+        * device items, so clear it here.
+        */
+       fs_info->fs_devices->total_rw_bytes = 0;
+
        /*
         * Read all device items, and then all the chunk items. All
         * device items are found before any chunk item (their object id
index f067b59..75af233 100644 (file)
@@ -408,7 +408,7 @@ static inline enum btrfs_map_op btrfs_op(struct bio *bio)
                return BTRFS_MAP_WRITE;
        default:
                WARN_ON_ONCE(1);
-               /* fall through */
+               fallthrough;
        case REQ_OP_READ:
                return BTRFS_MAP_READ;
        }
index e7726f5..3080cda 100644 (file)
@@ -937,7 +937,7 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page)
        }
 
        data = kmap(page);
-       ret = __kernel_write(file, data, len, &pos);
+       ret = kernel_write(file, data, len, &pos);
        kunmap(page);
        fput(file);
        if (ret != len)
index fc98b97..53588d7 100644 (file)
@@ -399,6 +399,10 @@ skip_rdma:
                        if (ses->sign)
                                seq_puts(m, " signed");
 
+                       seq_printf(m, "\n\tUser: %d Cred User: %d",
+                                  from_kuid(&init_user_ns, ses->linux_uid),
+                                  from_kuid(&init_user_ns, ses->cred_uid));
+
                        if (ses->chan_count > 1) {
                                seq_printf(m, "\n\n\tExtra Channels: %zu\n",
                                           ses->chan_count-1);
@@ -406,7 +410,7 @@ skip_rdma:
                                        cifs_dump_channel(m, j, &ses->chans[j]);
                        }
 
-                       seq_puts(m, "\n\tShares:");
+                       seq_puts(m, "\n\n\tShares:");
                        j = 0;
 
                        seq_printf(m, "\n\t%d) IPC: ", j);
index c7a311d..99b3180 100644 (file)
@@ -156,5 +156,5 @@ extern int cifs_truncate_page(struct address_space *mapping, loff_t from);
 extern const struct export_operations cifs_export_ops;
 #endif /* CONFIG_CIFS_NFSD_EXPORT */
 
-#define CIFS_VERSION   "2.27"
+#define CIFS_VERSION   "2.28"
 #endif                         /* _CIFSFS_H */
index 5fac34f..a61abde 100644 (file)
@@ -5306,9 +5306,15 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
        vol_info->nocase = master_tcon->nocase;
        vol_info->nohandlecache = master_tcon->nohandlecache;
        vol_info->local_lease = master_tcon->local_lease;
+       vol_info->no_lease = master_tcon->no_lease;
+       vol_info->resilient = master_tcon->use_resilient;
+       vol_info->persistent = master_tcon->use_persistent;
+       vol_info->handle_timeout = master_tcon->handle_timeout;
        vol_info->no_linux_ext = !master_tcon->unix_ext;
+       vol_info->linux_ext = master_tcon->posix_extensions;
        vol_info->sectype = master_tcon->ses->sectype;
        vol_info->sign = master_tcon->ses->sign;
+       vol_info->seal = master_tcon->seal;
 
        rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
        if (rc) {
@@ -5334,10 +5340,6 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
                goto out;
        }
 
-       /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
-       if (tcon->posix_extensions)
-               cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
-
        if (cap_unix(ses))
                reset_cifs_unix_caps(0, tcon, NULL, vol_info);
 
index 4fe757c..be46fab 100644 (file)
@@ -1149,20 +1149,20 @@ cifs_posix_lock_test(struct file *file, struct file_lock *flock)
 
 /*
  * Set the byte-range lock (posix style). Returns:
- * 1) 0, if we set the lock and don't need to request to the server;
- * 2) 1, if we need to request to the server;
- * 3) <0, if the error occurs while setting the lock.
+ * 1) <0, if the error occurs while setting the lock;
+ * 2) 0, if we set the lock and don't need to request to the server;
+ * 3) FILE_LOCK_DEFERRED, if we will wait for some other file_lock;
+ * 4) FILE_LOCK_DEFERRED + 1, if we need to request to the server.
  */
 static int
 cifs_posix_lock_set(struct file *file, struct file_lock *flock)
 {
        struct cifsInodeInfo *cinode = CIFS_I(file_inode(file));
-       int rc = 1;
+       int rc = FILE_LOCK_DEFERRED + 1;
 
        if ((flock->fl_flags & FL_POSIX) == 0)
                return rc;
 
-try_again:
        cifs_down_write(&cinode->lock_sem);
        if (!cinode->can_cache_brlcks) {
                up_write(&cinode->lock_sem);
@@ -1171,13 +1171,6 @@ try_again:
 
        rc = posix_lock_file(file, flock, NULL);
        up_write(&cinode->lock_sem);
-       if (rc == FILE_LOCK_DEFERRED) {
-               rc = wait_event_interruptible(flock->fl_wait,
-                                       list_empty(&flock->fl_blocked_member));
-               if (!rc)
-                       goto try_again;
-               locks_delete_block(flock);
-       }
        return rc;
 }
 
@@ -1652,7 +1645,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
                int posix_lock_type;
 
                rc = cifs_posix_lock_set(file, flock);
-               if (!rc || rc < 0)
+               if (rc <= FILE_LOCK_DEFERRED)
                        return rc;
 
                if (type & server->vals->shared_lock_type)
@@ -4336,7 +4329,8 @@ readpages_get_pages(struct address_space *mapping, struct list_head *page_list,
                        break;
 
                __SetPageLocked(page);
-               if (add_to_page_cache_locked(page, mapping, page->index, gfp)) {
+               rc = add_to_page_cache_locked(page, mapping, page->index, gfp);
+               if (rc) {
                        __ClearPageLocked(page);
                        break;
                }
@@ -4352,6 +4346,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
        struct list_head *page_list, unsigned num_pages)
 {
        int rc;
+       int err = 0;
        struct list_head tmplist;
        struct cifsFileInfo *open_file = file->private_data;
        struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
@@ -4396,7 +4391,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
         * the order of declining indexes. When we put the pages in
         * the rdata->pages, then we want them in increasing order.
         */
-       while (!list_empty(page_list)) {
+       while (!list_empty(page_list) && !err) {
                unsigned int i, nr_pages, bytes, rsize;
                loff_t offset;
                struct page *page, *tpage;
@@ -4429,9 +4424,10 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
                        return 0;
                }
 
-               rc = readpages_get_pages(mapping, page_list, rsize, &tmplist,
+               nr_pages = 0;
+               err = readpages_get_pages(mapping, page_list, rsize, &tmplist,
                                         &nr_pages, &offset, &bytes);
-               if (rc) {
+               if (!nr_pages) {
                        add_credits_and_wake_if(server, credits, 0);
                        break;
                }
index 583f5e4..ce95801 100644 (file)
@@ -2535,6 +2535,15 @@ set_size_out:
        if (rc == 0) {
                cifsInode->server_eof = attrs->ia_size;
                cifs_setsize(inode, attrs->ia_size);
+
+               /*
+                * The man page of truncate says if the size changed,
+                * then the st_ctime and st_mtime fields for the file
+                * are updated.
+                */
+               attrs->ia_ctime = attrs->ia_mtime = current_time(inode);
+               attrs->ia_valid |= ATTR_CTIME | ATTR_MTIME;
+
                cifs_truncate_page(inode->i_mapping, inode->i_size);
        }
 
index 4a73e63..dcde44f 100644 (file)
@@ -169,6 +169,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
        unsigned int xid;
        struct cifsFileInfo *pSMBFile = filep->private_data;
        struct cifs_tcon *tcon;
+       struct tcon_link *tlink;
        struct cifs_sb_info *cifs_sb;
        __u64   ExtAttrBits = 0;
        __u64   caps;
@@ -307,13 +308,19 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
                                break;
                        }
                        cifs_sb = CIFS_SB(inode->i_sb);
-                       tcon = tlink_tcon(cifs_sb_tlink(cifs_sb));
+                       tlink = cifs_sb_tlink(cifs_sb);
+                       if (IS_ERR(tlink)) {
+                               rc = PTR_ERR(tlink);
+                               break;
+                       }
+                       tcon = tlink_tcon(tlink);
                        if (tcon && tcon->ses->server->ops->notify) {
                                rc = tcon->ses->server->ops->notify(xid,
                                                filep, (void __user *)arg);
                                cifs_dbg(FYI, "ioctl notify rc %d\n", rc);
                        } else
                                rc = -EOPNOTSUPP;
+                       cifs_put_tlink(tlink);
                        break;
                default:
                        cifs_dbg(FYI, "unsupported ioctl\n");
index 56791a6..e44d049 100644 (file)
@@ -844,28 +844,26 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw)
        struct bio_vec *bv = NULL;
 
        if (iov_iter_is_kvec(iter)) {
-               memcpy(&ctx->iter, iter, sizeof(struct iov_iter));
+               memcpy(&ctx->iter, iter, sizeof(*iter));
                ctx->len = count;
                iov_iter_advance(iter, count);
                return 0;
        }
 
-       if (max_pages * sizeof(struct bio_vec) <= CIFS_AIO_KMALLOC_LIMIT)
-               bv = kmalloc_array(max_pages, sizeof(struct bio_vec),
-                                  GFP_KERNEL);
+       if (array_size(max_pages, sizeof(*bv)) <= CIFS_AIO_KMALLOC_LIMIT)
+               bv = kmalloc_array(max_pages, sizeof(*bv), GFP_KERNEL);
 
        if (!bv) {
-               bv = vmalloc(array_size(max_pages, sizeof(struct bio_vec)));
+               bv = vmalloc(array_size(max_pages, sizeof(*bv)));
                if (!bv)
                        return -ENOMEM;
        }
 
-       if (max_pages * sizeof(struct page *) <= CIFS_AIO_KMALLOC_LIMIT)
-               pages = kmalloc_array(max_pages, sizeof(struct page *),
-                                     GFP_KERNEL);
+       if (array_size(max_pages, sizeof(*pages)) <= CIFS_AIO_KMALLOC_LIMIT)
+               pages = kmalloc_array(max_pages, sizeof(*pages), GFP_KERNEL);
 
        if (!pages) {
-               pages = vmalloc(array_size(max_pages, sizeof(struct page *)));
+               pages = vmalloc(array_size(max_pages, sizeof(*pages)));
                if (!pages) {
                        kvfree(bv);
                        return -ENOMEM;
index 6a39451..1579928 100644 (file)
@@ -354,9 +354,13 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_sync_hdr *shdr)
                  ((struct smb2_ioctl_rsp *)shdr)->OutputCount);
                break;
        case SMB2_CHANGE_NOTIFY:
+               *off = le16_to_cpu(
+                 ((struct smb2_change_notify_rsp *)shdr)->OutputBufferOffset);
+               *len = le32_to_cpu(
+                 ((struct smb2_change_notify_rsp *)shdr)->OutputBufferLength);
+               break;
        default:
-               /* BB FIXME for unimplemented cases above */
-               cifs_dbg(VFS, "no length check for command\n");
+               cifs_dbg(VFS, "no length check for command %d\n", le16_to_cpu(shdr->Command));
                break;
        }
 
index 736d86b..32f90dc 100644 (file)
@@ -763,6 +763,7 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon,
                        /* close extra handle outside of crit sec */
                        SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
                }
+               rc = 0;
                goto oshr_free;
        }
 
@@ -2147,7 +2148,7 @@ smb3_notify(const unsigned int xid, struct file *pfile,
 
        tcon = cifs_sb_master_tcon(cifs_sb);
        oparms.tcon = tcon;
-       oparms.desired_access = FILE_READ_ATTRIBUTES;
+       oparms.desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA;
        oparms.disposition = FILE_OPEN;
        oparms.create_options = cifs_create_options(cifs_sb, 0);
        oparms.fid = &fid;
@@ -3187,6 +3188,11 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
        trace_smb3_zero_enter(xid, cfile->fid.persistent_fid, tcon->tid,
                              ses->Suid, offset, len);
 
+       /*
+        * We zero the range through ioctl, so we need remove the page caches
+        * first, otherwise the data may be inconsistent with the server.
+        */
+       truncate_pagecache_range(inode, offset, offset + len - 1);
 
        /* if file not oplocked can't be sure whether asking to extend size */
        if (!CIFS_CACHE_READ(cifsi))
@@ -3253,6 +3259,12 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
                return rc;
        }
 
+       /*
+        * We implement the punch hole through ioctl, so we need remove the page
+        * caches first, otherwise the data may be inconsistent with the server.
+        */
+       truncate_pagecache_range(inode, offset, offset + len - 1);
+
        cifs_dbg(FYI, "Offset %lld len %lld\n", offset, len);
 
        fsctl_buf.FileOffset = cpu_to_le64(offset);
index d11e310..84433d0 100644 (file)
@@ -523,7 +523,7 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
                      const int timeout, const int flags,
                      unsigned int *instance)
 {
-       int rc;
+       long rc;
        int *credits;
        int optype;
        long int t;
index e9e27a2..feaa5e1 100644 (file)
@@ -51,6 +51,7 @@ static ssize_t efivarfs_file_write(struct file *file,
        } else {
                inode_lock(inode);
                i_size_write(inode, datasize + sizeof(attributes));
+               inode->i_mtime = current_time(inode);
                inode_unlock(inode);
        }
 
@@ -72,10 +73,8 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
        ssize_t size = 0;
        int err;
 
-       while (!__ratelimit(&file->f_cred->user->ratelimit)) {
-               if (!msleep_interruptible(50))
-                       return -EINTR;
-       }
+       while (!__ratelimit(&file->f_cred->user->ratelimit))
+               msleep(50);
 
        err = efivar_entry_size(var, &datasize);
 
index 12c66f5..28bb568 100644 (file)
@@ -201,6 +201,9 @@ static int efivarfs_fill_super(struct super_block *sb, struct fs_context *fc)
        sb->s_d_op              = &efivarfs_d_ops;
        sb->s_time_gran         = 1;
 
+       if (!efivar_supports_writes())
+               sb->s_flags |= SB_RDONLY;
+
        inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0, true);
        if (!inode)
                return -ENOMEM;
@@ -252,9 +255,6 @@ static struct file_system_type efivarfs_type = {
 
 static __init int efivarfs_init(void)
 {
-       if (!efi_rt_services_supported(EFI_RT_SUPPORTED_VARIABLE_SERVICES))
-               return -ENODEV;
-
        if (!efivars_kobject())
                return -ENODEV;
 
index 7824f55..9b66c28 100644 (file)
@@ -144,22 +144,22 @@ static inline void z_erofs_onlinepage_init(struct page *page)
 static inline void z_erofs_onlinepage_fixup(struct page *page,
        uintptr_t index, bool down)
 {
-       unsigned long *p, o, v, id;
-repeat:
-       p = &page_private(page);
-       o = READ_ONCE(*p);
+       union z_erofs_onlinepage_converter u = { .v = &page_private(page) };
+       int orig, orig_index, val;
 
-       id = o >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT;
-       if (id) {
+repeat:
+       orig = atomic_read(u.o);
+       orig_index = orig >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT;
+       if (orig_index) {
                if (!index)
                        return;
 
-               DBG_BUGON(id != index);
+               DBG_BUGON(orig_index != index);
        }
 
-       v = (index << Z_EROFS_ONLINEPAGE_INDEX_SHIFT) |
-               ((o & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned int)down);
-       if (cmpxchg(p, o, v) != o)
+       val = (index << Z_EROFS_ONLINEPAGE_INDEX_SHIFT) |
+               ((orig & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned int)down);
+       if (atomic_cmpxchg(u.o, orig, val) != orig)
                goto repeat;
 }
 
index de43534..119abf0 100644 (file)
@@ -309,7 +309,7 @@ const struct file_operations exfat_dir_operations = {
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
        .iterate        = exfat_iterate,
-       .fsync          = generic_file_fsync,
+       .fsync          = exfat_file_fsync,
 };
 
 int exfat_alloc_new_dir(struct inode *inode, struct exfat_chain *clu)
@@ -425,10 +425,12 @@ static void exfat_init_name_entry(struct exfat_dentry *ep,
        ep->dentry.name.flags = 0x0;
 
        for (i = 0; i < EXFAT_FILE_NAME_LEN; i++) {
-               ep->dentry.name.unicode_0_14[i] = cpu_to_le16(*uniname);
-               if (*uniname == 0x0)
-                       break;
-               uniname++;
+               if (*uniname != 0x0) {
+                       ep->dentry.name.unicode_0_14[i] = cpu_to_le16(*uniname);
+                       uniname++;
+               } else {
+                       ep->dentry.name.unicode_0_14[i] = 0x0;
+               }
        }
 }
 
@@ -1110,7 +1112,7 @@ found:
                        ret = exfat_get_next_cluster(sb, &clu.dir);
                }
 
-               if (ret || clu.dir != EXFAT_EOF_CLUSTER) {
+               if (ret || clu.dir == EXFAT_EOF_CLUSTER) {
                        /* just initialized hint_stat */
                        hint_stat->clu = p_dir->dir;
                        hint_stat->eidx = 0;
index 595f311..75c7bdb 100644 (file)
@@ -371,7 +371,7 @@ static inline bool exfat_is_last_sector_in_cluster(struct exfat_sb_info *sbi,
 static inline sector_t exfat_cluster_to_sector(struct exfat_sb_info *sbi,
                unsigned int clus)
 {
-       return ((clus - EXFAT_RESERVED_CLUSTERS) << sbi->sect_per_clus_bits) +
+       return ((sector_t)(clus - EXFAT_RESERVED_CLUSTERS) << sbi->sect_per_clus_bits) +
                sbi->data_start_sector;
 }
 
@@ -420,6 +420,7 @@ void exfat_truncate(struct inode *inode, loff_t size);
 int exfat_setattr(struct dentry *dentry, struct iattr *attr);
 int exfat_getattr(const struct path *path, struct kstat *stat,
                unsigned int request_mask, unsigned int query_flags);
+int exfat_file_fsync(struct file *file, loff_t start, loff_t end, int datasync);
 
 /* namei.c */
 extern const struct dentry_operations exfat_dentry_ops;
index fce03f3..a6a0638 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/slab.h>
 #include <linux/cred.h>
 #include <linux/buffer_head.h>
+#include <linux/blkdev.h>
 
 #include "exfat_raw.h"
 #include "exfat_fs.h"
@@ -175,7 +176,7 @@ int __exfat_truncate(struct inode *inode, loff_t new_size)
                        ep2->dentry.stream.size = 0;
                } else {
                        ep2->dentry.stream.valid_size = cpu_to_le64(new_size);
-                       ep2->dentry.stream.size = ep->dentry.stream.valid_size;
+                       ep2->dentry.stream.size = ep2->dentry.stream.valid_size;
                }
 
                if (new_size == 0) {
@@ -346,12 +347,28 @@ out:
        return error;
 }
 
+int exfat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
+{
+       struct inode *inode = filp->f_mapping->host;
+       int err;
+
+       err = __generic_file_fsync(filp, start, end, datasync);
+       if (err)
+               return err;
+
+       err = sync_blockdev(inode->i_sb->s_bdev);
+       if (err)
+               return err;
+
+       return blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL);
+}
+
 const struct file_operations exfat_file_operations = {
        .llseek         = generic_file_llseek,
        .read_iter      = generic_file_read_iter,
        .write_iter     = generic_file_write_iter,
        .mmap           = generic_file_mmap,
-       .fsync          = generic_file_fsync,
+       .fsync          = exfat_file_fsync,
        .splice_read    = generic_file_splice_read,
        .splice_write   = iter_file_splice_write,
 };
index 5b0f353..2b9e210 100644 (file)
@@ -975,7 +975,6 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
                goto unlock;
        }
 
-       exfat_set_vol_flags(sb, VOL_DIRTY);
        exfat_chain_set(&clu_to_free, ei->start_clu,
                EXFAT_B_TO_CLU_ROUND_UP(i_size_read(inode), sbi), ei->flags);
 
@@ -1002,6 +1001,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
        num_entries++;
        brelse(bh);
 
+       exfat_set_vol_flags(sb, VOL_DIRTY);
        err = exfat_remove_entries(dir, &cdir, entry, 0, num_entries);
        if (err) {
                exfat_err(sb, "failed to exfat_remove_entries : err(%d)", err);
@@ -1077,10 +1077,14 @@ static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir,
 
                epold = exfat_get_dentry(sb, p_dir, oldentry + 1, &old_bh,
                        &sector_old);
+               if (!epold)
+                       return -EIO;
                epnew = exfat_get_dentry(sb, p_dir, newentry + 1, &new_bh,
                        &sector_new);
-               if (!epold || !epnew)
+               if (!epnew) {
+                       brelse(old_bh);
                        return -EIO;
+               }
 
                memcpy(epnew, epold, DENTRY_SIZE);
                exfat_update_bh(sb, new_bh, sync);
@@ -1161,10 +1165,14 @@ static int exfat_move_file(struct inode *inode, struct exfat_chain *p_olddir,
 
        epmov = exfat_get_dentry(sb, p_olddir, oldentry + 1, &mov_bh,
                &sector_mov);
+       if (!epmov)
+               return -EIO;
        epnew = exfat_get_dentry(sb, p_newdir, newentry + 1, &new_bh,
                &sector_new);
-       if (!epmov || !epnew)
+       if (!epnew) {
+               brelse(mov_bh);
                return -EIO;
+       }
 
        memcpy(epnew, epmov, DENTRY_SIZE);
        exfat_update_bh(sb, new_bh, IS_DIRSYNC(inode));
index 57b5a7a..a3c9275 100644 (file)
@@ -495,7 +495,7 @@ static int exfat_utf8_to_utf16(struct super_block *sb,
                struct exfat_uni_name *p_uniname, int *p_lossy)
 {
        int i, unilen, lossy = NLS_NAME_NO_LOSSY;
-       unsigned short upname[MAX_NAME_LENGTH + 1];
+       __le16 upname[MAX_NAME_LENGTH + 1];
        unsigned short *uniname = p_uniname->name;
 
        WARN_ON(!len);
@@ -519,7 +519,7 @@ static int exfat_utf8_to_utf16(struct super_block *sb,
                    exfat_wstrchr(bad_uni_chars, *uniname))
                        lossy |= NLS_NAME_LOSSY;
 
-               upname[i] = exfat_toupper(sb, *uniname);
+               upname[i] = cpu_to_le16(exfat_toupper(sb, *uniname));
                uniname++;
        }
 
@@ -597,7 +597,7 @@ static int exfat_nls_to_ucs2(struct super_block *sb,
                struct exfat_uni_name *p_uniname, int *p_lossy)
 {
        int i = 0, unilen = 0, lossy = NLS_NAME_NO_LOSSY;
-       unsigned short upname[MAX_NAME_LENGTH + 1];
+       __le16 upname[MAX_NAME_LENGTH + 1];
        unsigned short *uniname = p_uniname->name;
        struct nls_table *nls = EXFAT_SB(sb)->nls_io;
 
@@ -611,7 +611,7 @@ static int exfat_nls_to_ucs2(struct super_block *sb,
                    exfat_wstrchr(bad_uni_chars, *uniname))
                        lossy |= NLS_NAME_LOSSY;
 
-               upname[unilen] = exfat_toupper(sb, *uniname);
+               upname[unilen] = cpu_to_le16(exfat_toupper(sb, *uniname));
                uniname++;
                unilen++;
        }
index e650e65..253a924 100644 (file)
@@ -693,10 +693,20 @@ static void exfat_free(struct fs_context *fc)
        }
 }
 
+static int exfat_reconfigure(struct fs_context *fc)
+{
+       fc->sb_flags |= SB_NODIRATIME;
+
+       /* volume flag will be updated in exfat_sync_fs */
+       sync_filesystem(fc->root->d_sb);
+       return 0;
+}
+
 static const struct fs_context_operations exfat_context_ops = {
        .parse_param    = exfat_parse_param,
        .get_tree       = exfat_get_tree,
        .free           = exfat_free,
+       .reconfigure    = exfat_reconfigure,
 };
 
 static int exfat_init_fs_context(struct fs_context *fc)
index 4ccb3c9..2e42f47 100644 (file)
@@ -9,7 +9,8 @@ ext4-y  := balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \
                extents_status.o file.o fsmap.o fsync.o hash.o ialloc.o \
                indirect.o inline.o inode.o ioctl.o mballoc.o migrate.o \
                mmp.o move_extent.o namei.o page-io.o readpage.o resize.o \
-               super.o symlink.o sysfs.o xattr.o xattr_trusted.o xattr_user.o
+               super.o symlink.o sysfs.o xattr.o xattr_hurd.o xattr_trusted.o \
+               xattr_user.o
 
 ext4-$(CONFIG_EXT4_FS_POSIX_ACL)       += acl.o
 ext4-$(CONFIG_EXT4_FS_SECURITY)                += xattr_security.o
index c654205..1d82336 100644 (file)
@@ -675,6 +675,7 @@ static int ext4_d_compare(const struct dentry *dentry, unsigned int len,
        struct qstr qstr = {.name = str, .len = len };
        const struct dentry *parent = READ_ONCE(dentry->d_parent);
        const struct inode *inode = READ_ONCE(parent->d_inode);
+       char strbuf[DNAME_INLINE_LEN];
 
        if (!inode || !IS_CASEFOLDED(inode) ||
            !EXT4_SB(inode->i_sb)->s_encoding) {
@@ -683,6 +684,21 @@ static int ext4_d_compare(const struct dentry *dentry, unsigned int len,
                return memcmp(str, name->name, len);
        }
 
+       /*
+        * If the dentry name is stored in-line, then it may be concurrently
+        * modified by a rename.  If this happens, the VFS will eventually retry
+        * the lookup, so it doesn't matter what ->d_compare() returns.
+        * However, it's unsafe to call utf8_strncasecmp() with an unstable
+        * string.  Therefore, we have to copy the name into a temporary buffer.
+        */
+       if (len <= DNAME_INLINE_LEN - 1) {
+               memcpy(strbuf, str, len);
+               strbuf[len] = 0;
+               qstr.name = strbuf;
+               /* prevent compiler from optimizing out the temporary buffer */
+               barrier();
+       }
+
        return ext4_ci_compare(inode, name, &qstr, false);
 }
 
index b08841f..42f5060 100644 (file)
@@ -426,13 +426,16 @@ struct flex_groups {
 #define EXT4_VERITY_FL                 0x00100000 /* Verity protected inode */
 #define EXT4_EA_INODE_FL               0x00200000 /* Inode used for large EA */
 /* 0x00400000 was formerly EXT4_EOFBLOCKS_FL */
+
+#define EXT4_DAX_FL                    0x02000000 /* Inode is DAX */
+
 #define EXT4_INLINE_DATA_FL            0x10000000 /* Inode has inline data. */
 #define EXT4_PROJINHERIT_FL            0x20000000 /* Create with parents projid */
 #define EXT4_CASEFOLD_FL               0x40000000 /* Casefolded directory */
 #define EXT4_RESERVED_FL               0x80000000 /* reserved for ext4 lib */
 
-#define EXT4_FL_USER_VISIBLE           0x705BDFFF /* User visible flags */
-#define EXT4_FL_USER_MODIFIABLE                0x604BC0FF /* User modifiable flags */
+#define EXT4_FL_USER_VISIBLE           0x725BDFFF /* User visible flags */
+#define EXT4_FL_USER_MODIFIABLE                0x624BC0FF /* User modifiable flags */
 
 /* Flags we can manipulate with through EXT4_IOC_FSSETXATTR */
 #define EXT4_FL_XFLAG_VISIBLE          (EXT4_SYNC_FL | \
@@ -440,14 +443,16 @@ struct flex_groups {
                                         EXT4_APPEND_FL | \
                                         EXT4_NODUMP_FL | \
                                         EXT4_NOATIME_FL | \
-                                        EXT4_PROJINHERIT_FL)
+                                        EXT4_PROJINHERIT_FL | \
+                                        EXT4_DAX_FL)
 
 /* Flags that should be inherited by new inodes from their parent. */
 #define EXT4_FL_INHERITED (EXT4_SECRM_FL | EXT4_UNRM_FL | EXT4_COMPR_FL |\
                           EXT4_SYNC_FL | EXT4_NODUMP_FL | EXT4_NOATIME_FL |\
                           EXT4_NOCOMPR_FL | EXT4_JOURNAL_DATA_FL |\
                           EXT4_NOTAIL_FL | EXT4_DIRSYNC_FL |\
-                          EXT4_PROJINHERIT_FL | EXT4_CASEFOLD_FL)
+                          EXT4_PROJINHERIT_FL | EXT4_CASEFOLD_FL |\
+                          EXT4_DAX_FL)
 
 /* Flags that are appropriate for regular files (all but dir-specific ones). */
 #define EXT4_REG_FLMASK (~(EXT4_DIRSYNC_FL | EXT4_TOPDIR_FL | EXT4_CASEFOLD_FL |\
@@ -459,6 +464,10 @@ struct flex_groups {
 /* The only flags that should be swapped */
 #define EXT4_FL_SHOULD_SWAP (EXT4_HUGE_FILE_FL | EXT4_EXTENTS_FL)
 
+/* Flags which are mutually exclusive to DAX */
+#define EXT4_DAX_MUT_EXCL (EXT4_VERITY_FL | EXT4_ENCRYPT_FL |\
+                          EXT4_JOURNAL_DATA_FL)
+
 /* Mask out flags that are inappropriate for the given type of inode. */
 static inline __u32 ext4_mask_flags(umode_t mode, __u32 flags)
 {
@@ -499,6 +508,7 @@ enum {
        EXT4_INODE_VERITY       = 20,   /* Verity protected inode */
        EXT4_INODE_EA_INODE     = 21,   /* Inode used for large EA */
 /* 22 was formerly EXT4_INODE_EOFBLOCKS */
+       EXT4_INODE_DAX          = 25,   /* Inode is DAX */
        EXT4_INODE_INLINE_DATA  = 28,   /* Data in inode. */
        EXT4_INODE_PROJINHERIT  = 29,   /* Create with parents projid */
        EXT4_INODE_CASEFOLD     = 30,   /* Casefolded directory */
@@ -1135,9 +1145,9 @@ struct ext4_inode_info {
 #define EXT4_MOUNT_MINIX_DF            0x00080 /* Mimics the Minix statfs */
 #define EXT4_MOUNT_NOLOAD              0x00100 /* Don't use existing journal*/
 #ifdef CONFIG_FS_DAX
-#define EXT4_MOUNT_DAX                 0x00200 /* Direct Access */
+#define EXT4_MOUNT_DAX_ALWAYS          0x00200 /* Direct Access */
 #else
-#define EXT4_MOUNT_DAX                 0
+#define EXT4_MOUNT_DAX_ALWAYS          0
 #endif
 #define EXT4_MOUNT_DATA_FLAGS          0x00C00 /* Mode for data writes: */
 #define EXT4_MOUNT_JOURNAL_DATA                0x00400 /* Write data to journal */
@@ -1180,6 +1190,8 @@ struct ext4_inode_info {
                                                      blocks */
 #define EXT4_MOUNT2_HURD_COMPAT                0x00000004 /* Support HURD-castrated
                                                      file systems */
+#define EXT4_MOUNT2_DAX_NEVER          0x00000008 /* Do not allow Direct Access */
+#define EXT4_MOUNT2_DAX_INODE          0x00000010 /* For printing options only */
 
 #define EXT4_MOUNT2_EXPLICIT_JOURNAL_CHECKSUM  0x00000008 /* User explicitly
                                                specified journal checksum */
@@ -1992,6 +2004,7 @@ static inline bool ext4_has_incompat_features(struct super_block *sb)
  */
 #define EXT4_FLAGS_RESIZING    0
 #define EXT4_FLAGS_SHUTDOWN    1
+#define EXT4_FLAGS_BDEV_IS_DAX 2
 
 static inline int ext4_forced_shutdown(struct ext4_sb_info *sbi)
 {
@@ -2705,7 +2718,7 @@ extern int ext4_can_truncate(struct inode *inode);
 extern int ext4_truncate(struct inode *);
 extern int ext4_break_layouts(struct inode *);
 extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length);
-extern void ext4_set_inode_flags(struct inode *);
+extern void ext4_set_inode_flags(struct inode *, bool init);
 extern int ext4_alloc_da_blocks(struct inode *inode);
 extern void ext4_set_aops(struct inode *inode);
 extern int ext4_writepage_trans_blocks(struct inode *);
index 7d088ff..221f240 100644 (file)
@@ -2844,7 +2844,7 @@ again:
                         * in use to avoid freeing it when removing blocks.
                         */
                        if (sbi->s_cluster_ratio > 1) {
-                               pblk = ext4_ext_pblock(ex) + end - ee_block + 2;
+                               pblk = ext4_ext_pblock(ex) + end - ee_block + 1;
                                partial.pclu = EXT4_B2C(sbi, pblk);
                                partial.state = nofree;
                        }
index 54d324e..df25d38 100644 (file)
@@ -1116,7 +1116,7 @@ got:
        ei->i_block_group = group;
        ei->i_last_alloc_group = ~0;
 
-       ext4_set_inode_flags(inode);
+       ext4_set_inode_flags(inode, true);
        if (IS_DIRSYNC(inode))
                ext4_handle_sync(handle);
        if (insert_inode_locked(inode) < 0) {
index 40ec5c7..10dd470 100644 (file)
@@ -4403,9 +4403,11 @@ int ext4_get_inode_loc(struct inode *inode, struct ext4_iloc *iloc)
                !ext4_test_inode_state(inode, EXT4_STATE_XATTR));
 }
 
-static bool ext4_should_use_dax(struct inode *inode)
+static bool ext4_should_enable_dax(struct inode *inode)
 {
-       if (!test_opt(inode->i_sb, DAX))
+       struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+
+       if (test_opt2(inode->i_sb, DAX_NEVER))
                return false;
        if (!S_ISREG(inode->i_mode))
                return false;
@@ -4417,14 +4419,21 @@ static bool ext4_should_use_dax(struct inode *inode)
                return false;
        if (ext4_test_inode_flag(inode, EXT4_INODE_VERITY))
                return false;
-       return true;
+       if (!test_bit(EXT4_FLAGS_BDEV_IS_DAX, &sbi->s_ext4_flags))
+               return false;
+       if (test_opt(inode->i_sb, DAX_ALWAYS))
+               return true;
+
+       return ext4_test_inode_flag(inode, EXT4_INODE_DAX);
 }
 
-void ext4_set_inode_flags(struct inode *inode)
+void ext4_set_inode_flags(struct inode *inode, bool init)
 {
        unsigned int flags = EXT4_I(inode)->i_flags;
        unsigned int new_fl = 0;
 
+       WARN_ON_ONCE(IS_DAX(inode) && init);
+
        if (flags & EXT4_SYNC_FL)
                new_fl |= S_SYNC;
        if (flags & EXT4_APPEND_FL)
@@ -4435,8 +4444,13 @@ void ext4_set_inode_flags(struct inode *inode)
                new_fl |= S_NOATIME;
        if (flags & EXT4_DIRSYNC_FL)
                new_fl |= S_DIRSYNC;
-       if (ext4_should_use_dax(inode))
+
+       /* Because of the way inode_set_flags() works we must preserve S_DAX
+        * here if already set. */
+       new_fl |= (inode->i_flags & S_DAX);
+       if (init && ext4_should_enable_dax(inode))
                new_fl |= S_DAX;
+
        if (flags & EXT4_ENCRYPT_FL)
                new_fl |= S_ENCRYPTED;
        if (flags & EXT4_CASEFOLD_FL)
@@ -4650,7 +4664,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
                 * not initialized on a new filesystem. */
        }
        ei->i_flags = le32_to_cpu(raw_inode->i_flags);
-       ext4_set_inode_flags(inode);
+       ext4_set_inode_flags(inode, true);
        inode->i_blocks = ext4_inode_blocks(raw_inode, ei);
        ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl_lo);
        if (ext4_has_feature_64bit(sb))
index 2162db0..999cf6a 100644 (file)
@@ -292,6 +292,38 @@ static int ext4_ioctl_check_immutable(struct inode *inode, __u32 new_projid,
        return 0;
 }
 
+static void ext4_dax_dontcache(struct inode *inode, unsigned int flags)
+{
+       struct ext4_inode_info *ei = EXT4_I(inode);
+
+       if (S_ISDIR(inode->i_mode))
+               return;
+
+       if (test_opt2(inode->i_sb, DAX_NEVER) ||
+           test_opt(inode->i_sb, DAX_ALWAYS))
+               return;
+
+       if ((ei->i_flags ^ flags) & EXT4_DAX_FL)
+               d_mark_dontcache(inode);
+}
+
+static bool dax_compatible(struct inode *inode, unsigned int oldflags,
+                          unsigned int flags)
+{
+       if (flags & EXT4_DAX_FL) {
+               if ((oldflags & EXT4_DAX_MUT_EXCL) ||
+                    ext4_test_inode_state(inode,
+                                         EXT4_STATE_VERITY_IN_PROGRESS)) {
+                       return false;
+               }
+       }
+
+       if ((flags & EXT4_DAX_MUT_EXCL) && (oldflags & EXT4_DAX_FL))
+                       return false;
+
+       return true;
+}
+
 static int ext4_ioctl_setflags(struct inode *inode,
                               unsigned int flags)
 {
@@ -300,7 +332,6 @@ static int ext4_ioctl_setflags(struct inode *inode,
        int err = -EPERM, migrate = 0;
        struct ext4_iloc iloc;
        unsigned int oldflags, mask, i;
-       unsigned int jflag;
        struct super_block *sb = inode->i_sb;
 
        /* Is it quota file? Do not allow user to mess with it */
@@ -309,9 +340,6 @@ static int ext4_ioctl_setflags(struct inode *inode,
 
        oldflags = ei->i_flags;
 
-       /* The JOURNAL_DATA flag is modifiable only by root */
-       jflag = flags & EXT4_JOURNAL_DATA_FL;
-
        err = vfs_ioc_setflags_prepare(inode, oldflags, flags);
        if (err)
                goto flags_out;
@@ -320,10 +348,16 @@ static int ext4_ioctl_setflags(struct inode *inode,
         * The JOURNAL_DATA flag can only be changed by
         * the relevant capability.
         */
-       if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
+       if ((flags ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
                if (!capable(CAP_SYS_RESOURCE))
                        goto flags_out;
        }
+
+       if (!dax_compatible(inode, oldflags, flags)) {
+               err = -EOPNOTSUPP;
+               goto flags_out;
+       }
+
        if ((flags ^ oldflags) & EXT4_EXTENTS_FL)
                migrate = 1;
 
@@ -369,6 +403,8 @@ static int ext4_ioctl_setflags(struct inode *inode,
        if (err)
                goto flags_err;
 
+       ext4_dax_dontcache(inode, flags);
+
        for (i = 0, mask = 1; i < 32; i++, mask <<= 1) {
                if (!(mask & EXT4_FL_USER_MODIFIABLE))
                        continue;
@@ -381,7 +417,8 @@ static int ext4_ioctl_setflags(struct inode *inode,
                        ext4_clear_inode_flag(inode, i);
        }
 
-       ext4_set_inode_flags(inode);
+       ext4_set_inode_flags(inode, false);
+
        inode->i_ctime = current_time(inode);
 
        err = ext4_mark_iloc_dirty(handle, inode, &iloc);
@@ -390,17 +427,18 @@ flags_err:
        if (err)
                goto flags_out;
 
-       if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
+       if ((flags ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
                /*
                 * Changes to the journaling mode can cause unsafe changes to
-                * S_DAX if we are using the DAX mount option.
+                * S_DAX if the inode is DAX
                 */
-               if (test_opt(inode->i_sb, DAX)) {
+               if (IS_DAX(inode)) {
                        err = -EBUSY;
                        goto flags_out;
                }
 
-               err = ext4_change_inode_journal_flag(inode, jflag);
+               err = ext4_change_inode_journal_flag(inode,
+                                                    flags & EXT4_JOURNAL_DATA_FL);
                if (err)
                        goto flags_out;
        }
@@ -527,12 +565,15 @@ static inline __u32 ext4_iflags_to_xflags(unsigned long iflags)
                xflags |= FS_XFLAG_NOATIME;
        if (iflags & EXT4_PROJINHERIT_FL)
                xflags |= FS_XFLAG_PROJINHERIT;
+       if (iflags & EXT4_DAX_FL)
+               xflags |= FS_XFLAG_DAX;
        return xflags;
 }
 
 #define EXT4_SUPPORTED_FS_XFLAGS (FS_XFLAG_SYNC | FS_XFLAG_IMMUTABLE | \
                                  FS_XFLAG_APPEND | FS_XFLAG_NODUMP | \
-                                 FS_XFLAG_NOATIME | FS_XFLAG_PROJINHERIT)
+                                 FS_XFLAG_NOATIME | FS_XFLAG_PROJINHERIT | \
+                                 FS_XFLAG_DAX)
 
 /* Transfer xflags flags to internal */
 static inline unsigned long ext4_xflags_to_iflags(__u32 xflags)
@@ -551,6 +592,8 @@ static inline unsigned long ext4_xflags_to_iflags(__u32 xflags)
                iflags |= EXT4_NOATIME_FL;
        if (xflags & FS_XFLAG_PROJINHERIT)
                iflags |= EXT4_PROJINHERIT_FL;
+       if (xflags & FS_XFLAG_DAX)
+               iflags |= EXT4_DAX_FL;
 
        return iflags;
 }
index a908311..c0a331e 100644 (file)
@@ -4708,7 +4708,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
        }
 
        ac->ac_op = EXT4_MB_HISTORY_PREALLOC;
-       seq = *this_cpu_ptr(&discard_pa_seq);
+       seq = this_cpu_read(discard_pa_seq);
        if (!ext4_mb_use_preallocated(ac)) {
                ac->ac_op = EXT4_MB_HISTORY_ALLOC;
                ext4_mb_normalize_request(ac, ar);
index c668f6b..330957e 100644 (file)
@@ -522,9 +522,6 @@ static void ext4_handle_error(struct super_block *sb)
                smp_wmb();
                sb->s_flags |= SB_RDONLY;
        } else if (test_opt(sb, ERRORS_PANIC)) {
-               if (EXT4_SB(sb)->s_journal &&
-                 !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR))
-                       return;
                panic("EXT4-fs (device %s): panic forced after error\n",
                        sb->s_id);
        }
@@ -725,23 +722,20 @@ void __ext4_abort(struct super_block *sb, const char *function,
        va_end(args);
 
        if (sb_rdonly(sb) == 0) {
-               ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
                EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED;
+               if (EXT4_SB(sb)->s_journal)
+                       jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
+
+               ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
                /*
                 * Make sure updated value of ->s_mount_flags will be visible
                 * before ->s_flags update
                 */
                smp_wmb();
                sb->s_flags |= SB_RDONLY;
-               if (EXT4_SB(sb)->s_journal)
-                       jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
        }
-       if (test_opt(sb, ERRORS_PANIC) && !system_going_down()) {
-               if (EXT4_SB(sb)->s_journal &&
-                 !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR))
-                       return;
+       if (test_opt(sb, ERRORS_PANIC) && !system_going_down())
                panic("EXT4-fs panic from previous error\n");
-       }
 }
 
 void __ext4_msg(struct super_block *sb,
@@ -1324,6 +1318,9 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
        if (WARN_ON_ONCE(IS_DAX(inode) && i_size_read(inode)))
                return -EINVAL;
 
+       if (ext4_test_inode_flag(inode, EXT4_INODE_DAX))
+               return -EOPNOTSUPP;
+
        res = ext4_convert_inline_data(inode);
        if (res)
                return res;
@@ -1349,7 +1346,7 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
                         * Update inode->i_flags - S_ENCRYPTED will be enabled,
                         * S_DAX may be disabled
                         */
-                       ext4_set_inode_flags(inode);
+                       ext4_set_inode_flags(inode, false);
                }
                return res;
        }
@@ -1376,7 +1373,7 @@ retry:
                 * Update inode->i_flags - S_ENCRYPTED will be enabled,
                 * S_DAX may be disabled
                 */
-               ext4_set_inode_flags(inode);
+               ext4_set_inode_flags(inode, false);
                res = ext4_mark_inode_dirty(handle, inode);
                if (res)
                        EXT4_ERROR_INODE(inode, "Failed to mark inode dirty");
@@ -1514,7 +1511,8 @@ enum {
        Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
        Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
        Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err,
-       Opt_usrquota, Opt_grpquota, Opt_prjquota, Opt_i_version, Opt_dax,
+       Opt_usrquota, Opt_grpquota, Opt_prjquota, Opt_i_version,
+       Opt_dax, Opt_dax_always, Opt_dax_inode, Opt_dax_never,
        Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_warn_on_error,
        Opt_nowarn_on_error, Opt_mblk_io_submit,
        Opt_lazytime, Opt_nolazytime, Opt_debug_want_extra_isize,
@@ -1581,6 +1579,9 @@ static const match_table_t tokens = {
        {Opt_nobarrier, "nobarrier"},
        {Opt_i_version, "i_version"},
        {Opt_dax, "dax"},
+       {Opt_dax_always, "dax=always"},
+       {Opt_dax_inode, "dax=inode"},
+       {Opt_dax_never, "dax=never"},
        {Opt_stripe, "stripe=%u"},
        {Opt_delalloc, "delalloc"},
        {Opt_warn_on_error, "warn_on_error"},
@@ -1729,6 +1730,7 @@ static int clear_qf_name(struct super_block *sb, int qtype)
 #define MOPT_NO_EXT3   0x0200
 #define MOPT_EXT4_ONLY (MOPT_NO_EXT2 | MOPT_NO_EXT3)
 #define MOPT_STRING    0x0400
+#define MOPT_SKIP      0x0800
 
 static const struct mount_opts {
        int     token;
@@ -1778,7 +1780,13 @@ static const struct mount_opts {
        {Opt_min_batch_time, 0, MOPT_GTE0},
        {Opt_inode_readahead_blks, 0, MOPT_GTE0},
        {Opt_init_itable, 0, MOPT_GTE0},
-       {Opt_dax, EXT4_MOUNT_DAX, MOPT_SET},
+       {Opt_dax, EXT4_MOUNT_DAX_ALWAYS, MOPT_SET | MOPT_SKIP},
+       {Opt_dax_always, EXT4_MOUNT_DAX_ALWAYS,
+               MOPT_EXT4_ONLY | MOPT_SET | MOPT_SKIP},
+       {Opt_dax_inode, EXT4_MOUNT2_DAX_INODE,
+               MOPT_EXT4_ONLY | MOPT_SET | MOPT_SKIP},
+       {Opt_dax_never, EXT4_MOUNT2_DAX_NEVER,
+               MOPT_EXT4_ONLY | MOPT_SET | MOPT_SKIP},
        {Opt_stripe, 0, MOPT_GTE0},
        {Opt_resuid, 0, MOPT_GTE0},
        {Opt_resgid, 0, MOPT_GTE0},
@@ -2123,13 +2131,56 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
                }
                sbi->s_jquota_fmt = m->mount_opt;
 #endif
-       } else if (token == Opt_dax) {
+       } else if (token == Opt_dax || token == Opt_dax_always ||
+                  token == Opt_dax_inode || token == Opt_dax_never) {
 #ifdef CONFIG_FS_DAX
-               ext4_msg(sb, KERN_WARNING,
-               "DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
-               sbi->s_mount_opt |= m->mount_opt;
+               switch (token) {
+               case Opt_dax:
+               case Opt_dax_always:
+                       if (is_remount &&
+                           (!(sbi->s_mount_opt & EXT4_MOUNT_DAX_ALWAYS) ||
+                            (sbi->s_mount_opt2 & EXT4_MOUNT2_DAX_NEVER))) {
+                       fail_dax_change_remount:
+                               ext4_msg(sb, KERN_ERR, "can't change "
+                                        "dax mount option while remounting");
+                               return -1;
+                       }
+                       if (is_remount &&
+                           (test_opt(sb, DATA_FLAGS) ==
+                            EXT4_MOUNT_JOURNAL_DATA)) {
+                                   ext4_msg(sb, KERN_ERR, "can't mount with "
+                                            "both data=journal and dax");
+                                   return -1;
+                       }
+                       ext4_msg(sb, KERN_WARNING,
+                               "DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
+                       sbi->s_mount_opt |= EXT4_MOUNT_DAX_ALWAYS;
+                       sbi->s_mount_opt2 &= ~EXT4_MOUNT2_DAX_NEVER;
+                       break;
+               case Opt_dax_never:
+                       if (is_remount &&
+                           (!(sbi->s_mount_opt2 & EXT4_MOUNT2_DAX_NEVER) ||
+                            (sbi->s_mount_opt & EXT4_MOUNT_DAX_ALWAYS)))
+                               goto fail_dax_change_remount;
+                       sbi->s_mount_opt2 |= EXT4_MOUNT2_DAX_NEVER;
+                       sbi->s_mount_opt &= ~EXT4_MOUNT_DAX_ALWAYS;
+                       break;
+               case Opt_dax_inode:
+                       if (is_remount &&
+                           ((sbi->s_mount_opt & EXT4_MOUNT_DAX_ALWAYS) ||
+                            (sbi->s_mount_opt2 & EXT4_MOUNT2_DAX_NEVER) ||
+                            !(sbi->s_mount_opt2 & EXT4_MOUNT2_DAX_INODE)))
+                               goto fail_dax_change_remount;
+                       sbi->s_mount_opt &= ~EXT4_MOUNT_DAX_ALWAYS;
+                       sbi->s_mount_opt2 &= ~EXT4_MOUNT2_DAX_NEVER;
+                       /* Strictly for printing options */
+                       sbi->s_mount_opt2 |= EXT4_MOUNT2_DAX_INODE;
+                       break;
+               }
 #else
                ext4_msg(sb, KERN_INFO, "dax option not supported");
+               sbi->s_mount_opt2 |= EXT4_MOUNT2_DAX_NEVER;
+               sbi->s_mount_opt &= ~EXT4_MOUNT_DAX_ALWAYS;
                return -1;
 #endif
        } else if (token == Opt_data_err_abort) {
@@ -2293,7 +2344,7 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
        for (m = ext4_mount_opts; m->token != Opt_err; m++) {
                int want_set = m->flags & MOPT_SET;
                if (((m->flags & (MOPT_SET|MOPT_CLEAR)) == 0) ||
-                   (m->flags & MOPT_CLEAR_ERR))
+                   (m->flags & MOPT_CLEAR_ERR) || m->flags & MOPT_SKIP)
                        continue;
                if (!nodefs && !(m->mount_opt & (sbi->s_mount_opt ^ def_mount_opt)))
                        continue; /* skip if same as the default */
@@ -2353,6 +2404,17 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
 
        fscrypt_show_test_dummy_encryption(seq, sep, sb);
 
+       if (test_opt(sb, DAX_ALWAYS)) {
+               if (IS_EXT2_SB(sb))
+                       SEQ_OPTS_PUTS("dax");
+               else
+                       SEQ_OPTS_PUTS("dax=always");
+       } else if (test_opt2(sb, DAX_NEVER)) {
+               SEQ_OPTS_PUTS("dax=never");
+       } else if (test_opt2(sb, DAX_INODE)) {
+               SEQ_OPTS_PUTS("dax=inode");
+       }
+
        ext4_show_quota_options(seq, sb);
        return 0;
 }
@@ -2383,6 +2445,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
                ext4_msg(sb, KERN_ERR, "revision level too high, "
                         "forcing read-only mode");
                err = -EROFS;
+               goto done;
        }
        if (read_only)
                goto done;
@@ -4017,7 +4080,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                                 "both data=journal and delalloc");
                        goto failed_mount;
                }
-               if (test_opt(sb, DAX)) {
+               if (test_opt(sb, DAX_ALWAYS)) {
                        ext4_msg(sb, KERN_ERR, "can't mount with "
                                 "both data=journal and dax");
                        goto failed_mount;
@@ -4127,13 +4190,16 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                goto failed_mount;
        }
 
-       if (sbi->s_mount_opt & EXT4_MOUNT_DAX) {
+       if (bdev_dax_supported(sb->s_bdev, blocksize))
+               set_bit(EXT4_FLAGS_BDEV_IS_DAX, &sbi->s_ext4_flags);
+
+       if (sbi->s_mount_opt & EXT4_MOUNT_DAX_ALWAYS) {
                if (ext4_has_feature_inline_data(sb)) {
                        ext4_msg(sb, KERN_ERR, "Cannot use DAX on a filesystem"
                                        " that may contain inline data");
                        goto failed_mount;
                }
-               if (!bdev_dax_supported(sb->s_bdev, blocksize)) {
+               if (!test_bit(EXT4_FLAGS_BDEV_IS_DAX, &sbi->s_ext4_flags)) {
                        ext4_msg(sb, KERN_ERR,
                                "DAX unsupported by block device.");
                        goto failed_mount;
@@ -5447,12 +5513,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
                        err = -EINVAL;
                        goto restore_opts;
                }
-               if (test_opt(sb, DAX)) {
-                       ext4_msg(sb, KERN_ERR, "can't mount with "
-                                "both data=journal and dax");
-                       err = -EINVAL;
-                       goto restore_opts;
-               }
        } else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA) {
                if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) {
                        ext4_msg(sb, KERN_ERR, "can't mount with "
@@ -5468,12 +5528,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
                goto restore_opts;
        }
 
-       if ((sbi->s_mount_opt ^ old_opts.s_mount_opt) & EXT4_MOUNT_DAX) {
-               ext4_msg(sb, KERN_WARNING, "warning: refusing change of "
-                       "dax flag with busy inodes while remounting");
-               sbi->s_mount_opt ^= EXT4_MOUNT_DAX;
-       }
-
        if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED)
                ext4_abort(sb, EXT4_ERR_ESHUTDOWN, "Abort forced by user");
 
index dec1244..bbd5e7e 100644 (file)
@@ -113,6 +113,9 @@ static int ext4_begin_enable_verity(struct file *filp)
        handle_t *handle;
        int err;
 
+       if (IS_DAX(inode) || ext4_test_inode_flag(inode, EXT4_INODE_DAX))
+               return -EINVAL;
+
        if (ext4_verity_in_progress(inode))
                return -EBUSY;
 
@@ -241,7 +244,7 @@ static int ext4_end_enable_verity(struct file *filp, const void *desc,
                if (err)
                        goto out_stop;
                ext4_set_inode_flag(inode, EXT4_INODE_VERITY);
-               ext4_set_inode_flags(inode);
+               ext4_set_inode_flags(inode, false);
                err = ext4_mark_iloc_dirty(handle, inode, &iloc);
        }
 out_stop:
index 9b29a40..7d2f657 100644 (file)
@@ -93,6 +93,7 @@ static const struct xattr_handler * const ext4_xattr_handler_map[] = {
 #ifdef CONFIG_EXT4_FS_SECURITY
        [EXT4_XATTR_INDEX_SECURITY]          = &ext4_xattr_security_handler,
 #endif
+       [EXT4_XATTR_INDEX_HURD]              = &ext4_xattr_hurd_handler,
 };
 
 const struct xattr_handler *ext4_xattr_handlers[] = {
@@ -105,6 +106,7 @@ const struct xattr_handler *ext4_xattr_handlers[] = {
 #ifdef CONFIG_EXT4_FS_SECURITY
        &ext4_xattr_security_handler,
 #endif
+       &ext4_xattr_hurd_handler,
        NULL
 };
 
index ffe21ac..730b91f 100644 (file)
@@ -124,6 +124,7 @@ struct ext4_xattr_inode_array {
 extern const struct xattr_handler ext4_xattr_user_handler;
 extern const struct xattr_handler ext4_xattr_trusted_handler;
 extern const struct xattr_handler ext4_xattr_security_handler;
+extern const struct xattr_handler ext4_xattr_hurd_handler;
 
 #define EXT4_XATTR_NAME_ENCRYPTION_CONTEXT "c"
 
diff --git a/fs/ext4/xattr_hurd.c b/fs/ext4/xattr_hurd.c
new file mode 100644 (file)
index 0000000..8cfa74a
--- /dev/null
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * linux/fs/ext4/xattr_hurd.c
+ * Handler for extended gnu attributes for the Hurd.
+ *
+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ * Copyright (C) 2020 by Jan (janneke) Nieuwenhuizen, <janneke@gnu.org>
+ */
+
+#include <linux/init.h>
+#include <linux/string.h>
+#include "ext4.h"
+#include "xattr.h"
+
+static bool
+ext4_xattr_hurd_list(struct dentry *dentry)
+{
+       return test_opt(dentry->d_sb, XATTR_USER);
+}
+
+static int
+ext4_xattr_hurd_get(const struct xattr_handler *handler,
+                   struct dentry *unused, struct inode *inode,
+                   const char *name, void *buffer, size_t size)
+{
+       if (!test_opt(inode->i_sb, XATTR_USER))
+               return -EOPNOTSUPP;
+
+       return ext4_xattr_get(inode, EXT4_XATTR_INDEX_HURD,
+                             name, buffer, size);
+}
+
+static int
+ext4_xattr_hurd_set(const struct xattr_handler *handler,
+                   struct dentry *unused, struct inode *inode,
+                   const char *name, const void *value,
+                   size_t size, int flags)
+{
+       if (!test_opt(inode->i_sb, XATTR_USER))
+               return -EOPNOTSUPP;
+
+       return ext4_xattr_set(inode, EXT4_XATTR_INDEX_HURD,
+                             name, value, size, flags);
+}
+
+const struct xattr_handler ext4_xattr_hurd_handler = {
+       .prefix = XATTR_HURD_PREFIX,
+       .list   = ext4_xattr_hurd_list,
+       .get    = ext4_xattr_hurd_get,
+       .set    = ext4_xattr_hurd_set,
+};
index e573b0c..83d917f 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/swap.h>
 #include <linux/falloc.h>
 #include <linux/uio.h>
+#include <linux/fs.h>
 
 static struct page **fuse_pages_alloc(unsigned int npages, gfp_t flags,
                                      struct fuse_page_desc **desc)
@@ -1586,7 +1587,6 @@ static void fuse_writepage_finish(struct fuse_conn *fc,
        struct backing_dev_info *bdi = inode_to_bdi(inode);
        int i;
 
-       rb_erase(&wpa->writepages_entry, &fi->writepages);
        for (i = 0; i < ap->num_pages; i++) {
                dec_wb_stat(&bdi->wb, WB_WRITEBACK);
                dec_node_page_state(ap->pages[i], NR_WRITEBACK_TEMP);
@@ -1637,6 +1637,7 @@ __acquires(fi->lock)
 
  out_free:
        fi->writectr--;
+       rb_erase(&wpa->writepages_entry, &fi->writepages);
        fuse_writepage_finish(fc, wpa);
        spin_unlock(&fi->lock);
 
@@ -1674,7 +1675,8 @@ __acquires(fi->lock)
        }
 }
 
-static void tree_insert(struct rb_root *root, struct fuse_writepage_args *wpa)
+static struct fuse_writepage_args *fuse_insert_writeback(struct rb_root *root,
+                                               struct fuse_writepage_args *wpa)
 {
        pgoff_t idx_from = wpa->ia.write.in.offset >> PAGE_SHIFT;
        pgoff_t idx_to = idx_from + wpa->ia.ap.num_pages - 1;
@@ -1697,11 +1699,17 @@ static void tree_insert(struct rb_root *root, struct fuse_writepage_args *wpa)
                else if (idx_to < curr_index)
                        p = &(*p)->rb_left;
                else
-                       return (void) WARN_ON(true);
+                       return curr;
        }
 
        rb_link_node(&wpa->writepages_entry, parent, p);
        rb_insert_color(&wpa->writepages_entry, root);
+       return NULL;
+}
+
+static void tree_insert(struct rb_root *root, struct fuse_writepage_args *wpa)
+{
+       WARN_ON(fuse_insert_writeback(root, wpa));
 }
 
 static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_args *args,
@@ -1714,6 +1722,7 @@ static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_args *args,
 
        mapping_set_error(inode->i_mapping, error);
        spin_lock(&fi->lock);
+       rb_erase(&wpa->writepages_entry, &fi->writepages);
        while (wpa->next) {
                struct fuse_conn *fc = get_fuse_conn(inode);
                struct fuse_write_in *inarg = &wpa->ia.write.in;
@@ -1952,14 +1961,14 @@ static void fuse_writepages_send(struct fuse_fill_wb_data *data)
 }
 
 /*
- * First recheck under fi->lock if the offending offset is still under
- * writeback.  If yes, then iterate auxiliary write requests, to see if there's
+ * Check under fi->lock if the page is under writeback, and insert it onto the
+ * rb_tree if not. Otherwise iterate auxiliary write requests, to see if there's
  * one already added for a page at this offset.  If there's none, then insert
  * this new request onto the auxiliary list, otherwise reuse the existing one by
- * copying the new page contents over to the old temporary page.
+ * swapping the new temp page with the old one.
  */
-static bool fuse_writepage_in_flight(struct fuse_writepage_args *new_wpa,
-                                    struct page *page)
+static bool fuse_writepage_add(struct fuse_writepage_args *new_wpa,
+                              struct page *page)
 {
        struct fuse_inode *fi = get_fuse_inode(new_wpa->inode);
        struct fuse_writepage_args *tmp;
@@ -1967,17 +1976,15 @@ static bool fuse_writepage_in_flight(struct fuse_writepage_args *new_wpa,
        struct fuse_args_pages *new_ap = &new_wpa->ia.ap;
 
        WARN_ON(new_ap->num_pages != 0);
+       new_ap->num_pages = 1;
 
        spin_lock(&fi->lock);
-       rb_erase(&new_wpa->writepages_entry, &fi->writepages);
-       old_wpa = fuse_find_writeback(fi, page->index, page->index);
+       old_wpa = fuse_insert_writeback(&fi->writepages, new_wpa);
        if (!old_wpa) {
-               tree_insert(&fi->writepages, new_wpa);
                spin_unlock(&fi->lock);
-               return false;
+               return true;
        }
 
-       new_ap->num_pages = 1;
        for (tmp = old_wpa->next; tmp; tmp = tmp->next) {
                pgoff_t curr_index;
 
@@ -2006,7 +2013,41 @@ static bool fuse_writepage_in_flight(struct fuse_writepage_args *new_wpa,
                fuse_writepage_free(new_wpa);
        }
 
-       return true;
+       return false;
+}
+
+static bool fuse_writepage_need_send(struct fuse_conn *fc, struct page *page,
+                                    struct fuse_args_pages *ap,
+                                    struct fuse_fill_wb_data *data)
+{
+       WARN_ON(!ap->num_pages);
+
+       /*
+        * Being under writeback is unlikely but possible.  For example direct
+        * read to an mmaped fuse file will set the page dirty twice; once when
+        * the pages are faulted with get_user_pages(), and then after the read
+        * completed.
+        */
+       if (fuse_page_is_writeback(data->inode, page->index))
+               return true;
+
+       /* Reached max pages */
+       if (ap->num_pages == fc->max_pages)
+               return true;
+
+       /* Reached max write bytes */
+       if ((ap->num_pages + 1) * PAGE_SIZE > fc->max_write)
+               return true;
+
+       /* Discontinuity */
+       if (data->orig_pages[ap->num_pages - 1]->index + 1 != page->index)
+               return true;
+
+       /* Need to grow the pages array?  If so, did the expansion fail? */
+       if (ap->num_pages == data->max_pages && !fuse_pages_realloc(data))
+               return true;
+
+       return false;
 }
 
 static int fuse_writepages_fill(struct page *page,
@@ -2019,7 +2060,6 @@ static int fuse_writepages_fill(struct page *page,
        struct fuse_inode *fi = get_fuse_inode(inode);
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct page *tmp_page;
-       bool is_writeback;
        int err;
 
        if (!data->ff) {
@@ -2029,25 +2069,9 @@ static int fuse_writepages_fill(struct page *page,
                        goto out_unlock;
        }
 
-       /*
-        * Being under writeback is unlikely but possible.  For example direct
-        * read to an mmaped fuse file will set the page dirty twice; once when
-        * the pages are faulted with get_user_pages(), and then after the read
-        * completed.
-        */
-       is_writeback = fuse_page_is_writeback(inode, page->index);
-
-       if (wpa && ap->num_pages &&
-           (is_writeback || ap->num_pages == fc->max_pages ||
-            (ap->num_pages + 1) * PAGE_SIZE > fc->max_write ||
-            data->orig_pages[ap->num_pages - 1]->index + 1 != page->index)) {
+       if (wpa && fuse_writepage_need_send(fc, page, ap, data)) {
                fuse_writepages_send(data);
                data->wpa = NULL;
-       } else if (wpa && ap->num_pages == data->max_pages) {
-               if (!fuse_pages_realloc(data)) {
-                       fuse_writepages_send(data);
-                       data->wpa = NULL;
-               }
        }
 
        err = -ENOMEM;
@@ -2085,12 +2109,6 @@ static int fuse_writepages_fill(struct page *page,
                ap->args.end = fuse_writepage_end;
                ap->num_pages = 0;
                wpa->inode = inode;
-
-               spin_lock(&fi->lock);
-               tree_insert(&fi->writepages, wpa);
-               spin_unlock(&fi->lock);
-
-               data->wpa = wpa;
        }
        set_page_writeback(page);
 
@@ -2098,26 +2116,25 @@ static int fuse_writepages_fill(struct page *page,
        ap->pages[ap->num_pages] = tmp_page;
        ap->descs[ap->num_pages].offset = 0;
        ap->descs[ap->num_pages].length = PAGE_SIZE;
+       data->orig_pages[ap->num_pages] = page;
 
        inc_wb_stat(&inode_to_bdi(inode)->wb, WB_WRITEBACK);
        inc_node_page_state(tmp_page, NR_WRITEBACK_TEMP);
 
        err = 0;
-       if (is_writeback && fuse_writepage_in_flight(wpa, page)) {
+       if (data->wpa) {
+               /*
+                * Protected by fi->lock against concurrent access by
+                * fuse_page_is_writeback().
+                */
+               spin_lock(&fi->lock);
+               ap->num_pages++;
+               spin_unlock(&fi->lock);
+       } else if (fuse_writepage_add(wpa, page)) {
+               data->wpa = wpa;
+       } else {
                end_page_writeback(page);
-               data->wpa = NULL;
-               goto out_unlock;
        }
-       data->orig_pages[ap->num_pages] = page;
-
-       /*
-        * Protected by fi->lock against concurrent access by
-        * fuse_page_is_writeback().
-        */
-       spin_lock(&fi->lock);
-       ap->num_pages++;
-       spin_unlock(&fi->lock);
-
 out_unlock:
        unlock_page(page);
 
@@ -2149,10 +2166,8 @@ static int fuse_writepages(struct address_space *mapping,
 
        err = write_cache_pages(mapping, wbc, fuse_writepages_fill, &data);
        if (data.wpa) {
-               /* Ignore errors if we can write at least one page */
                WARN_ON(!data.wpa->ia.ap.num_pages);
                fuse_writepages_send(&data);
-               err = 0;
        }
        if (data.ff)
                fuse_file_put(data.ff, false, false);
@@ -2761,7 +2776,16 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
                struct iovec *iov = iov_page;
 
                iov->iov_base = (void __user *)arg;
-               iov->iov_len = _IOC_SIZE(cmd);
+
+               switch (cmd) {
+               case FS_IOC_GETFLAGS:
+               case FS_IOC_SETFLAGS:
+                       iov->iov_len = sizeof(int);
+                       break;
+               default:
+                       iov->iov_len = _IOC_SIZE(cmd);
+                       break;
+               }
 
                if (_IOC_DIR(cmd) & _IOC_WRITE) {
                        in_iov = iov;
index 5b4aebf..bba7475 100644 (file)
@@ -121,10 +121,12 @@ static void fuse_evict_inode(struct inode *inode)
        }
 }
 
-static int fuse_remount_fs(struct super_block *sb, int *flags, char *data)
+static int fuse_reconfigure(struct fs_context *fc)
 {
+       struct super_block *sb = fc->root->d_sb;
+
        sync_filesystem(sb);
-       if (*flags & SB_MANDLOCK)
+       if (fc->sb_flags & SB_MANDLOCK)
                return -EINVAL;
 
        return 0;
@@ -475,6 +477,17 @@ static int fuse_parse_param(struct fs_context *fc, struct fs_parameter *param)
        struct fuse_fs_context *ctx = fc->fs_private;
        int opt;
 
+       if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) {
+               /*
+                * Ignore options coming from mount(MS_REMOUNT) for backward
+                * compatibility.
+                */
+               if (fc->oldapi)
+                       return 0;
+
+               return invalfc(fc, "No changes allowed in reconfigure");
+       }
+
        opt = fs_parse(fc, fuse_fs_parameters, param, &result);
        if (opt < 0)
                return opt;
@@ -817,7 +830,6 @@ static const struct super_operations fuse_super_operations = {
        .evict_inode    = fuse_evict_inode,
        .write_inode    = fuse_write_inode,
        .drop_inode     = generic_delete_inode,
-       .remount_fs     = fuse_remount_fs,
        .put_super      = fuse_put_super,
        .umount_begin   = fuse_umount_begin,
        .statfs         = fuse_statfs,
@@ -1296,6 +1308,7 @@ static int fuse_get_tree(struct fs_context *fc)
 static const struct fs_context_operations fuse_context_ops = {
        .free           = fuse_free_fc,
        .parse_param    = fuse_parse_param,
+       .reconfigure    = fuse_reconfigure,
        .get_tree       = fuse_get_tree,
 };
 
index 72c9560..68cd700 100644 (file)
@@ -468,21 +468,10 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
 }
 
 
-/**
- * __gfs2_readpage - readpage
- * @file: The file to read a page for
- * @page: The page to read
- *
- * This is the core of gfs2's readpage. It's used by the internal file
- * reading code as in that case we already hold the glock. Also it's
- * called by gfs2_readpage() once the required lock has been granted.
- */
-
 static int __gfs2_readpage(void *file, struct page *page)
 {
        struct gfs2_inode *ip = GFS2_I(page->mapping->host);
        struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host);
-
        int error;
 
        if (i_blocksize(page->mapping->host) == PAGE_SIZE &&
@@ -505,36 +494,11 @@ static int __gfs2_readpage(void *file, struct page *page)
  * gfs2_readpage - read a page of a file
  * @file: The file to read
  * @page: The page of the file
- *
- * This deals with the locking required. We have to unlock and
- * relock the page in order to get the locking in the right
- * order.
  */
 
 static int gfs2_readpage(struct file *file, struct page *page)
 {
-       struct address_space *mapping = page->mapping;
-       struct gfs2_inode *ip = GFS2_I(mapping->host);
-       struct gfs2_holder gh;
-       int error;
-
-       unlock_page(page);
-       gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
-       error = gfs2_glock_nq(&gh);
-       if (unlikely(error))
-               goto out;
-       error = AOP_TRUNCATED_PAGE;
-       lock_page(page);
-       if (page->mapping == mapping && !PageUptodate(page))
-               error = __gfs2_readpage(file, page);
-       else
-               unlock_page(page);
-       gfs2_glock_dq(&gh);
-out:
-       gfs2_holder_uninit(&gh);
-       if (error && error != AOP_TRUNCATED_PAGE)
-               lock_page(page);
-       return error;
+       return __gfs2_readpage(file, page);
 }
 
 /**
@@ -598,16 +562,9 @@ static void gfs2_readahead(struct readahead_control *rac)
 {
        struct inode *inode = rac->mapping->host;
        struct gfs2_inode *ip = GFS2_I(inode);
-       struct gfs2_holder gh;
 
-       gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
-       if (gfs2_glock_nq(&gh))
-               goto out_uninit;
        if (!gfs2_is_stuffed(ip))
                mpage_readahead(rac, gfs2_block_map);
-       gfs2_glock_dq(&gh);
-out_uninit:
-       gfs2_holder_uninit(&gh);
 }
 
 /**
index fe305e4..bebde53 100644 (file)
@@ -558,8 +558,29 @@ out_uninit:
        return block_page_mkwrite_return(ret);
 }
 
+static vm_fault_t gfs2_fault(struct vm_fault *vmf)
+{
+       struct inode *inode = file_inode(vmf->vma->vm_file);
+       struct gfs2_inode *ip = GFS2_I(inode);
+       struct gfs2_holder gh;
+       vm_fault_t ret;
+       int err;
+
+       gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
+       err = gfs2_glock_nq(&gh);
+       if (err) {
+               ret = block_page_mkwrite_return(err);
+               goto out_uninit;
+       }
+       ret = filemap_fault(vmf);
+       gfs2_glock_dq(&gh);
+out_uninit:
+       gfs2_holder_uninit(&gh);
+       return ret;
+}
+
 static const struct vm_operations_struct gfs2_vm_ops = {
-       .fault = filemap_fault,
+       .fault = gfs2_fault,
        .map_pages = filemap_map_pages,
        .page_mkwrite = gfs2_page_mkwrite,
 };
@@ -824,6 +845,9 @@ out_uninit:
 
 static ssize_t gfs2_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
 {
+       struct gfs2_inode *ip;
+       struct gfs2_holder gh;
+       size_t written = 0;
        ssize_t ret;
 
        if (iocb->ki_flags & IOCB_DIRECT) {
@@ -832,7 +856,31 @@ static ssize_t gfs2_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
                        return ret;
                iocb->ki_flags &= ~IOCB_DIRECT;
        }
-       return generic_file_read_iter(iocb, to);
+       iocb->ki_flags |= IOCB_NOIO;
+       ret = generic_file_read_iter(iocb, to);
+       iocb->ki_flags &= ~IOCB_NOIO;
+       if (ret >= 0) {
+               if (!iov_iter_count(to))
+                       return ret;
+               written = ret;
+       } else {
+               if (ret != -EAGAIN)
+                       return ret;
+               if (iocb->ki_flags & IOCB_NOWAIT)
+                       return ret;
+       }
+       ip = GFS2_I(iocb->ki_filp->f_mapping->host);
+       gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
+       ret = gfs2_glock_nq(&gh);
+       if (ret)
+               goto out_uninit;
+       ret = generic_file_read_iter(iocb, to);
+       if (ret > 0)
+               written += ret;
+       gfs2_glock_dq(&gh);
+out_uninit:
+       gfs2_holder_uninit(&gh);
+       return written ? written : ret;
 }
 
 /**
index 2299dcc..8545024 100644 (file)
@@ -1899,7 +1899,10 @@ bool gfs2_delete_work_queued(const struct gfs2_glock *gl)
 
 static void flush_delete_work(struct gfs2_glock *gl)
 {
-       flush_delayed_work(&gl->gl_delete);
+       if (cancel_delayed_work(&gl->gl_delete)) {
+               queue_delayed_work(gfs2_delete_workqueue,
+                                  &gl->gl_delete, 0);
+       }
        gfs2_glock_queue_work(gl, 0);
 }
 
index c848877..de1d5f1 100644 (file)
@@ -531,8 +531,7 @@ static int freeze_go_sync(struct gfs2_glock *gl)
        int error = 0;
        struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 
-       if (gl->gl_state == LM_ST_SHARED && !gfs2_withdrawn(sdp) &&
-           test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
+       if (gl->gl_req == LM_ST_EXCLUSIVE && !gfs2_withdrawn(sdp)) {
                atomic_set(&sdp->sd_freeze_state, SFS_STARTING_FREEZE);
                error = freeze_super(sdp->sd_vfs);
                if (error) {
@@ -545,8 +544,11 @@ static int freeze_go_sync(struct gfs2_glock *gl)
                        gfs2_assert_withdraw(sdp, 0);
                }
                queue_work(gfs2_freeze_wq, &sdp->sd_freeze_work);
-               gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_FREEZE |
-                              GFS2_LFC_FREEZE_GO_SYNC);
+               if (test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))
+                       gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_FREEZE |
+                                      GFS2_LFC_FREEZE_GO_SYNC);
+               else /* read-only mounts */
+                       atomic_set(&sdp->sd_freeze_state, SFS_FROZEN);
        }
        return 0;
 }
index 03ab11f..ca2ec02 100644 (file)
@@ -399,7 +399,6 @@ enum {
        GIF_QD_LOCKED           = 1,
        GIF_ALLOC_FAILED        = 2,
        GIF_SW_PAGED            = 3,
-       GIF_ORDERED             = 4,
        GIF_FREE_VFS_INODE      = 5,
        GIF_GLOP_PENDING        = 6,
        GIF_DEFERRED_DELETE     = 7,
index 370c3a4..6774865 100644 (file)
@@ -207,10 +207,11 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
 
        if (no_formal_ino && ip->i_no_formal_ino &&
            no_formal_ino != ip->i_no_formal_ino) {
+               error = -ESTALE;
                if (inode->i_state & I_NEW)
                        goto fail;
                iput(inode);
-               return ERR_PTR(-ESTALE);
+               return ERR_PTR(error);
        }
 
        if (inode->i_state & I_NEW)
index 3e47344..a76e55b 100644 (file)
@@ -613,6 +613,12 @@ static int ip_cmp(void *priv, struct list_head *a, struct list_head *b)
        return 0;
 }
 
+static void __ordered_del_inode(struct gfs2_inode *ip)
+{
+       if (!list_empty(&ip->i_ordered))
+               list_del_init(&ip->i_ordered);
+}
+
 static void gfs2_ordered_write(struct gfs2_sbd *sdp)
 {
        struct gfs2_inode *ip;
@@ -623,8 +629,7 @@ static void gfs2_ordered_write(struct gfs2_sbd *sdp)
        while (!list_empty(&sdp->sd_log_ordered)) {
                ip = list_first_entry(&sdp->sd_log_ordered, struct gfs2_inode, i_ordered);
                if (ip->i_inode.i_mapping->nrpages == 0) {
-                       test_and_clear_bit(GIF_ORDERED, &ip->i_flags);
-                       list_del(&ip->i_ordered);
+                       __ordered_del_inode(ip);
                        continue;
                }
                list_move(&ip->i_ordered, &written);
@@ -643,8 +648,7 @@ static void gfs2_ordered_wait(struct gfs2_sbd *sdp)
        spin_lock(&sdp->sd_ordered_lock);
        while (!list_empty(&sdp->sd_log_ordered)) {
                ip = list_first_entry(&sdp->sd_log_ordered, struct gfs2_inode, i_ordered);
-               list_del(&ip->i_ordered);
-               WARN_ON(!test_and_clear_bit(GIF_ORDERED, &ip->i_flags));
+               __ordered_del_inode(ip);
                if (ip->i_inode.i_mapping->nrpages == 0)
                        continue;
                spin_unlock(&sdp->sd_ordered_lock);
@@ -659,8 +663,7 @@ void gfs2_ordered_del_inode(struct gfs2_inode *ip)
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 
        spin_lock(&sdp->sd_ordered_lock);
-       if (test_and_clear_bit(GIF_ORDERED, &ip->i_flags))
-               list_del(&ip->i_ordered);
+       __ordered_del_inode(ip);
        spin_unlock(&sdp->sd_ordered_lock);
 }
 
@@ -1002,6 +1005,16 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
 
 out:
        if (gfs2_withdrawn(sdp)) {
+               /**
+                * If the tr_list is empty, we're withdrawing during a log
+                * flush that targets a transaction, but the transaction was
+                * never queued onto any of the ail lists. Here we add it to
+                * ail1 just so that ail_drain() will find and free it.
+                */
+               spin_lock(&sdp->sd_ail_lock);
+               if (tr && list_empty(&tr->tr_list))
+                       list_add(&tr->tr_list, &sdp->sd_ail1_list);
+               spin_unlock(&sdp->sd_ail_lock);
                ail_drain(sdp); /* frees all transactions */
                tr = NULL;
        }
index c1cd6ae..8965c75 100644 (file)
@@ -53,9 +53,9 @@ static inline void gfs2_ordered_add_inode(struct gfs2_inode *ip)
        if (gfs2_is_jdata(ip) || !gfs2_is_ordered(sdp))
                return;
 
-       if (!test_bit(GIF_ORDERED, &ip->i_flags)) {
+       if (list_empty(&ip->i_ordered)) {
                spin_lock(&sdp->sd_ordered_lock);
-               if (!test_and_set_bit(GIF_ORDERED, &ip->i_flags))
+               if (list_empty(&ip->i_ordered))
                        list_add(&ip->i_ordered, &sdp->sd_log_ordered);
                spin_unlock(&sdp->sd_ordered_lock);
        }
index 733470c..c7393ee 100644 (file)
@@ -39,6 +39,7 @@ static void gfs2_init_inode_once(void *foo)
        atomic_set(&ip->i_sizehint, 0);
        init_rwsem(&ip->i_rw_mutex);
        INIT_LIST_HEAD(&ip->i_trunc_list);
+       INIT_LIST_HEAD(&ip->i_ordered);
        ip->i_qadata = NULL;
        gfs2_holder_mark_uninitialized(&ip->i_rgd_gh);
        memset(&ip->i_res, 0, sizeof(ip->i_res));
index 094f5fe..6d18d2c 100644 (file)
@@ -1136,7 +1136,18 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
                goto fail_per_node;
        }
 
-       if (!sb_rdonly(sb)) {
+       if (sb_rdonly(sb)) {
+               struct gfs2_holder freeze_gh;
+
+               error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED,
+                                          LM_FLAG_NOEXP | GL_EXACT,
+                                          &freeze_gh);
+               if (error) {
+                       fs_err(sdp, "can't make FS RO: %d\n", error);
+                       goto fail_per_node;
+               }
+               gfs2_glock_dq_uninit(&freeze_gh);
+       } else {
                error = gfs2_make_fs_rw(sdp);
                if (error) {
                        fs_err(sdp, "can't make FS RW: %d\n", error);
index 96c345f..390ea79 100644 (file)
@@ -364,8 +364,8 @@ void gfs2_recover_func(struct work_struct *work)
                /* Acquire a shared hold on the freeze lock */
 
                error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED,
-                                          LM_FLAG_NOEXP | LM_FLAG_PRIORITY,
-                                          &thaw_gh);
+                                          LM_FLAG_NOEXP | LM_FLAG_PRIORITY |
+                                          GL_EXACT, &thaw_gh);
                if (error)
                        goto fail_gunlock_ji;
 
index 32d8d26..47d0ae1 100644 (file)
@@ -167,7 +167,8 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp)
        if (error)
                return error;
 
-       error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, 0,
+       error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED,
+                                  LM_FLAG_NOEXP | GL_EXACT,
                                   &freeze_gh);
        if (error)
                goto fail_threads;
@@ -203,7 +204,6 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp)
        return 0;
 
 fail:
-       freeze_gh.gh_flags |= GL_NOCACHE;
        gfs2_glock_dq_uninit(&freeze_gh);
 fail_threads:
        if (sdp->sd_quotad_process)
@@ -430,7 +430,7 @@ static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp)
        }
 
        error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_EXCLUSIVE,
-                                  GL_NOCACHE, &sdp->sd_freeze_gh);
+                                  LM_FLAG_NOEXP, &sdp->sd_freeze_gh);
        if (error)
                goto out;
 
@@ -613,13 +613,15 @@ int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
            !gfs2_glock_is_locked_by_me(sdp->sd_freeze_gl)) {
                if (!log_write_allowed) {
                        error = gfs2_glock_nq_init(sdp->sd_freeze_gl,
-                                                  LM_ST_SHARED, GL_NOCACHE |
-                                                  LM_FLAG_TRY, &freeze_gh);
+                                                  LM_ST_SHARED, LM_FLAG_TRY |
+                                                  LM_FLAG_NOEXP | GL_EXACT,
+                                                  &freeze_gh);
                        if (error == GLR_TRYFAILED)
                                error = 0;
                } else {
                        error = gfs2_glock_nq_init(sdp->sd_freeze_gl,
-                                                  LM_ST_SHARED, GL_NOCACHE,
+                                                  LM_ST_SHARED,
+                                                  LM_FLAG_NOEXP | GL_EXACT,
                                                   &freeze_gh);
                        if (error && !gfs2_withdrawn(sdp))
                                return error;
@@ -761,8 +763,8 @@ void gfs2_freeze_func(struct work_struct *work)
        struct super_block *sb = sdp->sd_vfs;
 
        atomic_inc(&sb->s_active);
-       error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, 0,
-                                  &freeze_gh);
+       error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED,
+                                  LM_FLAG_NOEXP | GL_EXACT, &freeze_gh);
        if (error) {
                fs_info(sdp, "GFS2: couldn't get freeze lock : %d\n", error);
                gfs2_assert_withdraw(sdp, 0);
@@ -774,8 +776,6 @@ void gfs2_freeze_func(struct work_struct *work)
                                error);
                        gfs2_assert_withdraw(sdp, 0);
                }
-               if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))
-                       freeze_gh.gh_flags |= GL_NOCACHE;
                gfs2_glock_dq_uninit(&freeze_gh);
        }
        deactivate_super(sb);
index 0b65a91..47c5f3a 100644 (file)
@@ -903,13 +903,15 @@ void io_wq_cancel_all(struct io_wq *wq)
 struct io_cb_cancel_data {
        work_cancel_fn *fn;
        void *data;
+       int nr_running;
+       int nr_pending;
+       bool cancel_all;
 };
 
 static bool io_wq_worker_cancel(struct io_worker *worker, void *data)
 {
        struct io_cb_cancel_data *match = data;
        unsigned long flags;
-       bool ret = false;
 
        /*
         * Hold the lock to avoid ->cur_work going out of scope, caller
@@ -920,74 +922,90 @@ static bool io_wq_worker_cancel(struct io_worker *worker, void *data)
            !(worker->cur_work->flags & IO_WQ_WORK_NO_CANCEL) &&
            match->fn(worker->cur_work, match->data)) {
                send_sig(SIGINT, worker->task, 1);
-               ret = true;
+               match->nr_running++;
        }
        spin_unlock_irqrestore(&worker->lock, flags);
 
-       return ret;
+       return match->nr_running && !match->cancel_all;
 }
 
-static enum io_wq_cancel io_wqe_cancel_work(struct io_wqe *wqe,
-                                           struct io_cb_cancel_data *match)
+static void io_wqe_cancel_pending_work(struct io_wqe *wqe,
+                                      struct io_cb_cancel_data *match)
 {
        struct io_wq_work_node *node, *prev;
        struct io_wq_work *work;
        unsigned long flags;
-       bool found = false;
 
-       /*
-        * First check pending list, if we're lucky we can just remove it
-        * from there. CANCEL_OK means that the work is returned as-new,
-        * no completion will be posted for it.
-        */
+retry:
        spin_lock_irqsave(&wqe->lock, flags);
        wq_list_for_each(node, prev, &wqe->work_list) {
                work = container_of(node, struct io_wq_work, list);
+               if (!match->fn(work, match->data))
+                       continue;
 
-               if (match->fn(work, match->data)) {
-                       wq_list_del(&wqe->work_list, node, prev);
-                       found = true;
-                       break;
-               }
-       }
-       spin_unlock_irqrestore(&wqe->lock, flags);
-
-       if (found) {
+               wq_list_del(&wqe->work_list, node, prev);
+               spin_unlock_irqrestore(&wqe->lock, flags);
                io_run_cancel(work, wqe);
-               return IO_WQ_CANCEL_OK;
+               match->nr_pending++;
+               if (!match->cancel_all)
+                       return;
+
+               /* not safe to continue after unlock */
+               goto retry;
        }
+       spin_unlock_irqrestore(&wqe->lock, flags);
+}
 
-       /*
-        * Now check if a free (going busy) or busy worker has the work
-        * currently running. If we find it there, we'll return CANCEL_RUNNING
-        * as an indication that we attempt to signal cancellation. The
-        * completion will run normally in this case.
-        */
+static void io_wqe_cancel_running_work(struct io_wqe *wqe,
+                                      struct io_cb_cancel_data *match)
+{
        rcu_read_lock();
-       found = io_wq_for_each_worker(wqe, io_wq_worker_cancel, match);
+       io_wq_for_each_worker(wqe, io_wq_worker_cancel, match);
        rcu_read_unlock();
-       return found ? IO_WQ_CANCEL_RUNNING : IO_WQ_CANCEL_NOTFOUND;
 }
 
 enum io_wq_cancel io_wq_cancel_cb(struct io_wq *wq, work_cancel_fn *cancel,
-                                 void *data)
+                                 void *data, bool cancel_all)
 {
        struct io_cb_cancel_data match = {
-               .fn     = cancel,
-               .data   = data,
+               .fn             = cancel,
+               .data           = data,
+               .cancel_all     = cancel_all,
        };
-       enum io_wq_cancel ret = IO_WQ_CANCEL_NOTFOUND;
        int node;
 
+       /*
+        * First check pending list, if we're lucky we can just remove it
+        * from there. CANCEL_OK means that the work is returned as-new,
+        * no completion will be posted for it.
+        */
        for_each_node(node) {
                struct io_wqe *wqe = wq->wqes[node];
 
-               ret = io_wqe_cancel_work(wqe, &match);
-               if (ret != IO_WQ_CANCEL_NOTFOUND)
-                       break;
+               io_wqe_cancel_pending_work(wqe, &match);
+               if (match.nr_pending && !match.cancel_all)
+                       return IO_WQ_CANCEL_OK;
        }
 
-       return ret;
+       /*
+        * Now check if a free (going busy) or busy worker has the work
+        * currently running. If we find it there, we'll return CANCEL_RUNNING
+        * as an indication that we attempt to signal cancellation. The
+        * completion will run normally in this case.
+        */
+       for_each_node(node) {
+               struct io_wqe *wqe = wq->wqes[node];
+
+               io_wqe_cancel_running_work(wqe, &match);
+               if (match.nr_running && !match.cancel_all)
+                       return IO_WQ_CANCEL_RUNNING;
+       }
+
+       if (match.nr_running)
+               return IO_WQ_CANCEL_RUNNING;
+       if (match.nr_pending)
+               return IO_WQ_CANCEL_OK;
+       return IO_WQ_CANCEL_NOTFOUND;
 }
 
 static bool io_wq_io_cb_cancel_data(struct io_wq_work *work, void *data)
@@ -997,21 +1015,7 @@ static bool io_wq_io_cb_cancel_data(struct io_wq_work *work, void *data)
 
 enum io_wq_cancel io_wq_cancel_work(struct io_wq *wq, struct io_wq_work *cwork)
 {
-       return io_wq_cancel_cb(wq, io_wq_io_cb_cancel_data, (void *)cwork);
-}
-
-static bool io_wq_pid_match(struct io_wq_work *work, void *data)
-{
-       pid_t pid = (pid_t) (unsigned long) data;
-
-       return work->task_pid == pid;
-}
-
-enum io_wq_cancel io_wq_cancel_pid(struct io_wq *wq, pid_t pid)
-{
-       void *data = (void *) (unsigned long) pid;
-
-       return io_wq_cancel_cb(wq, io_wq_pid_match, data);
+       return io_wq_cancel_cb(wq, io_wq_io_cb_cancel_data, (void *)cwork, false);
 }
 
 struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data)
index 8e138fa..071f1a9 100644 (file)
@@ -90,7 +90,6 @@ struct io_wq_work {
        const struct cred *creds;
        struct fs_struct *fs;
        unsigned flags;
-       pid_t task_pid;
 };
 
 static inline struct io_wq_work *wq_next_work(struct io_wq_work *work)
@@ -125,12 +124,11 @@ static inline bool io_wq_is_hashed(struct io_wq_work *work)
 
 void io_wq_cancel_all(struct io_wq *wq);
 enum io_wq_cancel io_wq_cancel_work(struct io_wq *wq, struct io_wq_work *cwork);
-enum io_wq_cancel io_wq_cancel_pid(struct io_wq *wq, pid_t pid);
 
 typedef bool (work_cancel_fn)(struct io_wq_work *, void *);
 
 enum io_wq_cancel io_wq_cancel_cb(struct io_wq *wq, work_cancel_fn *cancel,
-                                       void *data);
+                                       void *data, bool cancel_all);
 
 struct task_struct *io_wq_get_task(struct io_wq *wq);
 
index 155f3d8..493e504 100644 (file)
@@ -541,6 +541,7 @@ enum {
        REQ_F_NO_FILE_TABLE_BIT,
        REQ_F_QUEUE_TIMEOUT_BIT,
        REQ_F_WORK_INITIALIZED_BIT,
+       REQ_F_TASK_PINNED_BIT,
 
        /* not a real bit, just to check we're not overflowing the space */
        __REQ_F_LAST_BIT,
@@ -598,10 +599,13 @@ enum {
        REQ_F_QUEUE_TIMEOUT     = BIT(REQ_F_QUEUE_TIMEOUT_BIT),
        /* io_wq_work is initialized */
        REQ_F_WORK_INITIALIZED  = BIT(REQ_F_WORK_INITIALIZED_BIT),
+       /* req->task is refcounted */
+       REQ_F_TASK_PINNED       = BIT(REQ_F_TASK_PINNED_BIT),
 };
 
 struct async_poll {
        struct io_poll_iocb     poll;
+       struct io_poll_iocb     *double_poll;
        struct io_wq_work       work;
 };
 
@@ -887,6 +891,7 @@ static int __io_sqe_files_update(struct io_ring_ctx *ctx,
                                 struct io_uring_files_update *ip,
                                 unsigned nr_args);
 static int io_grab_files(struct io_kiocb *req);
+static void io_complete_rw_common(struct kiocb *kiocb, long res);
 static void io_cleanup_req(struct io_kiocb *req);
 static int io_file_get(struct io_submit_state *state, struct io_kiocb *req,
                       int fd, struct file **out_file, bool fixed);
@@ -910,6 +915,21 @@ struct sock *io_uring_get_socket(struct file *file)
 }
 EXPORT_SYMBOL(io_uring_get_socket);
 
+static void io_get_req_task(struct io_kiocb *req)
+{
+       if (req->flags & REQ_F_TASK_PINNED)
+               return;
+       get_task_struct(req->task);
+       req->flags |= REQ_F_TASK_PINNED;
+}
+
+/* not idempotent -- it doesn't clear REQ_F_TASK_PINNED */
+static void __io_put_req_task(struct io_kiocb *req)
+{
+       if (req->flags & REQ_F_TASK_PINNED)
+               put_task_struct(req->task);
+}
+
 static void io_file_put_work(struct work_struct *work);
 
 /*
@@ -1045,8 +1065,6 @@ static inline void io_req_work_grab_env(struct io_kiocb *req,
                }
                spin_unlock(&current->fs->lock);
        }
-       if (!req->work.task_pid)
-               req->work.task_pid = task_pid_vnr(current);
 }
 
 static inline void io_req_work_drop_env(struct io_kiocb *req)
@@ -1079,6 +1097,8 @@ static inline void io_prep_async_work(struct io_kiocb *req,
 {
        const struct io_op_def *def = &io_op_defs[req->opcode];
 
+       io_req_init_async(req);
+
        if (req->flags & REQ_F_ISREG) {
                if (def->hash_reg_file)
                        io_wq_hash_work(&req->work, file_inode(req->file));
@@ -1256,6 +1276,7 @@ static bool io_cqring_overflow_flush(struct io_ring_ctx *ctx, bool force)
        if (cqe) {
                clear_bit(0, &ctx->sq_check_overflow);
                clear_bit(0, &ctx->cq_check_overflow);
+               ctx->rings->sq_flags &= ~IORING_SQ_CQ_OVERFLOW;
        }
        spin_unlock_irqrestore(&ctx->completion_lock, flags);
        io_cqring_ev_posted(ctx);
@@ -1293,6 +1314,7 @@ static void __io_cqring_fill_event(struct io_kiocb *req, long res, long cflags)
                if (list_empty(&ctx->cq_overflow_list)) {
                        set_bit(0, &ctx->sq_check_overflow);
                        set_bit(0, &ctx->cq_check_overflow);
+                       ctx->rings->sq_flags |= IORING_SQ_CQ_OVERFLOW;
                }
                req->flags |= REQ_F_OVERFLOW;
                refcount_inc(&req->refs);
@@ -1398,9 +1420,7 @@ static void __io_req_aux_free(struct io_kiocb *req)
        kfree(req->io);
        if (req->file)
                io_put_file(req, req->file, (req->flags & REQ_F_FIXED_FILE));
-       if (req->task)
-               put_task_struct(req->task);
-
+       __io_put_req_task(req);
        io_req_work_drop_env(req);
 }
 
@@ -1727,6 +1747,26 @@ static int io_put_kbuf(struct io_kiocb *req)
        return cflags;
 }
 
+static void io_iopoll_queue(struct list_head *again)
+{
+       struct io_kiocb *req;
+
+       do {
+               req = list_first_entry(again, struct io_kiocb, list);
+               list_del(&req->list);
+
+               /* shouldn't happen unless io_uring is dying, cancel reqs */
+               if (unlikely(!current->mm)) {
+                       io_complete_rw_common(&req->rw.kiocb, -EAGAIN);
+                       io_put_req(req);
+                       continue;
+               }
+
+               refcount_inc(&req->refs);
+               io_queue_async_work(req);
+       } while (!list_empty(again));
+}
+
 /*
  * Find and free completed poll iocbs
  */
@@ -1735,12 +1775,21 @@ static void io_iopoll_complete(struct io_ring_ctx *ctx, unsigned int *nr_events,
 {
        struct req_batch rb;
        struct io_kiocb *req;
+       LIST_HEAD(again);
+
+       /* order with ->result store in io_complete_rw_iopoll() */
+       smp_rmb();
 
        rb.to_free = rb.need_iter = 0;
        while (!list_empty(done)) {
                int cflags = 0;
 
                req = list_first_entry(done, struct io_kiocb, list);
+               if (READ_ONCE(req->result) == -EAGAIN) {
+                       req->iopoll_completed = 0;
+                       list_move_tail(&req->list, &again);
+                       continue;
+               }
                list_del(&req->list);
 
                if (req->flags & REQ_F_BUFFER_SELECTED)
@@ -1758,18 +1807,9 @@ static void io_iopoll_complete(struct io_ring_ctx *ctx, unsigned int *nr_events,
        if (ctx->flags & IORING_SETUP_SQPOLL)
                io_cqring_ev_posted(ctx);
        io_free_req_many(ctx, &rb);
-}
 
-static void io_iopoll_queue(struct list_head *again)
-{
-       struct io_kiocb *req;
-
-       do {
-               req = list_first_entry(again, struct io_kiocb, list);
-               list_del(&req->list);
-               refcount_inc(&req->refs);
-               io_queue_async_work(req);
-       } while (!list_empty(again));
+       if (!list_empty(&again))
+               io_iopoll_queue(&again);
 }
 
 static int io_do_iopoll(struct io_ring_ctx *ctx, unsigned int *nr_events,
@@ -1777,7 +1817,6 @@ static int io_do_iopoll(struct io_ring_ctx *ctx, unsigned int *nr_events,
 {
        struct io_kiocb *req, *tmp;
        LIST_HEAD(done);
-       LIST_HEAD(again);
        bool spin;
        int ret;
 
@@ -1803,13 +1842,6 @@ static int io_do_iopoll(struct io_ring_ctx *ctx, unsigned int *nr_events,
                if (!list_empty(&done))
                        break;
 
-               if (req->result == -EAGAIN) {
-                       list_move_tail(&req->list, &again);
-                       continue;
-               }
-               if (!list_empty(&again))
-                       break;
-
                ret = kiocb->ki_filp->f_op->iopoll(kiocb, spin);
                if (ret < 0)
                        break;
@@ -1822,9 +1854,6 @@ static int io_do_iopoll(struct io_ring_ctx *ctx, unsigned int *nr_events,
        if (!list_empty(&done))
                io_iopoll_complete(ctx, nr_events, &done);
 
-       if (!list_empty(&again))
-               io_iopoll_queue(&again);
-
        return ret;
 }
 
@@ -1973,11 +2002,13 @@ static void io_complete_rw_iopoll(struct kiocb *kiocb, long res, long res2)
        if (kiocb->ki_flags & IOCB_WRITE)
                kiocb_end_write(req);
 
-       if (res != req->result)
+       if (res != -EAGAIN && res != req->result)
                req_set_fail_links(req);
-       req->result = res;
-       if (res != -EAGAIN)
-               WRITE_ONCE(req->iopoll_completed, 1);
+
+       WRITE_ONCE(req->result, res);
+       /* order with io_poll_complete() checking ->result */
+       smp_wmb();
+       WRITE_ONCE(req->iopoll_completed, 1);
 }
 
 /*
@@ -2650,8 +2681,8 @@ copy_iov:
                }
        }
 out_free:
-       kfree(iovec);
-       req->flags &= ~REQ_F_NEED_CLEANUP;
+       if (!(req->flags & REQ_F_NEED_CLEANUP))
+               kfree(iovec);
        return ret;
 }
 
@@ -2773,8 +2804,8 @@ copy_iov:
                }
        }
 out_free:
-       req->flags &= ~REQ_F_NEED_CLEANUP;
-       kfree(iovec);
+       if (!(req->flags & REQ_F_NEED_CLEANUP))
+               kfree(iovec);
        return ret;
 }
 
@@ -3524,6 +3555,7 @@ static int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        if (req->flags & REQ_F_NEED_CLEANUP)
                return 0;
 
+       io->msg.msg.msg_name = &io->msg.addr;
        io->msg.iov = io->msg.fast_iov;
        ret = sendmsg_copy_msghdr(&io->msg.msg, sr->msg, sr->msg_flags,
                                        &io->msg.iov);
@@ -3705,6 +3737,7 @@ static int __io_compat_recvmsg_copy_hdr(struct io_kiocb *req,
 
 static int io_recvmsg_copy_hdr(struct io_kiocb *req, struct io_async_ctx *io)
 {
+       io->msg.msg.msg_name = &io->msg.addr;
        io->msg.iov = io->msg.fast_iov;
 
 #ifdef CONFIG_COMPAT
@@ -3813,10 +3846,16 @@ static int io_recvmsg(struct io_kiocb *req, bool force_nonblock)
 
                ret = __sys_recvmsg_sock(sock, &kmsg->msg, req->sr_msg.msg,
                                                kmsg->uaddr, flags);
-               if (force_nonblock && ret == -EAGAIN)
-                       return io_setup_async_msg(req, kmsg);
+               if (force_nonblock && ret == -EAGAIN) {
+                       ret = io_setup_async_msg(req, kmsg);
+                       if (ret != -EAGAIN)
+                               kfree(kbuf);
+                       return ret;
+               }
                if (ret == -ERESTARTSYS)
                        ret = -EINTR;
+               if (kbuf)
+                       kfree(kbuf);
        }
 
        if (kmsg && kmsg->iov != kmsg->fast_iov)
@@ -4045,6 +4084,29 @@ struct io_poll_table {
        int error;
 };
 
+static int io_req_task_work_add(struct io_kiocb *req, struct callback_head *cb)
+{
+       struct task_struct *tsk = req->task;
+       struct io_ring_ctx *ctx = req->ctx;
+       int ret, notify = TWA_RESUME;
+
+       /*
+        * SQPOLL kernel thread doesn't need notification, just a wakeup.
+        * If we're not using an eventfd, then TWA_RESUME is always fine,
+        * as we won't have dependencies between request completions for
+        * other kernel wait conditions.
+        */
+       if (ctx->flags & IORING_SETUP_SQPOLL)
+               notify = 0;
+       else if (ctx->cq_ev_fd)
+               notify = TWA_SIGNAL;
+
+       ret = task_work_add(tsk, cb, notify);
+       if (!ret)
+               wake_up_process(tsk);
+       return ret;
+}
+
 static int __io_async_wake(struct io_kiocb *req, struct io_poll_iocb *poll,
                           __poll_t mask, task_work_func_t func)
 {
@@ -4068,13 +4130,13 @@ static int __io_async_wake(struct io_kiocb *req, struct io_poll_iocb *poll,
         * of executing it. We can't safely execute it anyway, as we may not
         * have the needed state needed for it anyway.
         */
-       ret = task_work_add(tsk, &req->task_work, true);
+       ret = io_req_task_work_add(req, &req->task_work);
        if (unlikely(ret)) {
                WRITE_ONCE(poll->canceled, true);
                tsk = io_wq_get_task(req->ctx->io_wq);
-               task_work_add(tsk, &req->task_work, true);
+               task_work_add(tsk, &req->task_work, 0);
+               wake_up_process(tsk);
        }
-       wake_up_process(tsk);
        return 1;
 }
 
@@ -4098,9 +4160,9 @@ static bool io_poll_rewait(struct io_kiocb *req, struct io_poll_iocb *poll)
        return false;
 }
 
-static void io_poll_remove_double(struct io_kiocb *req)
+static void io_poll_remove_double(struct io_kiocb *req, void *data)
 {
-       struct io_poll_iocb *poll = (struct io_poll_iocb *) req->io;
+       struct io_poll_iocb *poll = data;
 
        lockdep_assert_held(&req->ctx->completion_lock);
 
@@ -4120,7 +4182,7 @@ static void io_poll_complete(struct io_kiocb *req, __poll_t mask, int error)
 {
        struct io_ring_ctx *ctx = req->ctx;
 
-       io_poll_remove_double(req);
+       io_poll_remove_double(req, req->io);
        req->poll.done = true;
        io_cqring_fill_event(req, error ? error : mangle_poll(mask));
        io_commit_cqring(ctx);
@@ -4137,10 +4199,9 @@ static void io_poll_task_handler(struct io_kiocb *req, struct io_kiocb **nxt)
 
        hash_del(&req->hash_node);
        io_poll_complete(req, req->result, 0);
-       req->flags |= REQ_F_COMP_LOCKED;
-       io_put_req_find_next(req, nxt);
        spin_unlock_irq(&ctx->completion_lock);
 
+       io_put_req_find_next(req, nxt);
        io_cqring_ev_posted(ctx);
 }
 
@@ -4163,21 +4224,21 @@ static int io_poll_double_wake(struct wait_queue_entry *wait, unsigned mode,
                               int sync, void *key)
 {
        struct io_kiocb *req = wait->private;
-       struct io_poll_iocb *poll = (struct io_poll_iocb *) req->io;
+       struct io_poll_iocb *poll = req->apoll->double_poll;
        __poll_t mask = key_to_poll(key);
 
        /* for instances that support it check for an event match first: */
        if (mask && !(mask & poll->events))
                return 0;
 
-       if (req->poll.head) {
+       if (poll && poll->head) {
                bool done;
 
-               spin_lock(&req->poll.head->lock);
-               done = list_empty(&req->poll.wait.entry);
+               spin_lock(&poll->head->lock);
+               done = list_empty(&poll->wait.entry);
                if (!done)
-                       list_del_init(&req->poll.wait.entry);
-               spin_unlock(&req->poll.head->lock);
+                       list_del_init(&poll->wait.entry);
+               spin_unlock(&poll->head->lock);
                if (!done)
                        __io_async_wake(req, poll, mask, io_poll_task_func);
        }
@@ -4197,7 +4258,8 @@ static void io_init_poll_iocb(struct io_poll_iocb *poll, __poll_t events,
 }
 
 static void __io_queue_proc(struct io_poll_iocb *poll, struct io_poll_table *pt,
-                           struct wait_queue_head *head)
+                           struct wait_queue_head *head,
+                           struct io_poll_iocb **poll_ptr)
 {
        struct io_kiocb *req = pt->req;
 
@@ -4208,7 +4270,7 @@ static void __io_queue_proc(struct io_poll_iocb *poll, struct io_poll_table *pt,
         */
        if (unlikely(poll->head)) {
                /* already have a 2nd entry, fail a third attempt */
-               if (req->io) {
+               if (*poll_ptr) {
                        pt->error = -EINVAL;
                        return;
                }
@@ -4220,7 +4282,7 @@ static void __io_queue_proc(struct io_poll_iocb *poll, struct io_poll_table *pt,
                io_init_poll_iocb(poll, req->poll.events, io_poll_double_wake);
                refcount_inc(&req->refs);
                poll->wait.private = req;
-               req->io = (void *) poll;
+               *poll_ptr = poll;
        }
 
        pt->error = 0;
@@ -4232,8 +4294,31 @@ static void io_async_queue_proc(struct file *file, struct wait_queue_head *head,
                               struct poll_table_struct *p)
 {
        struct io_poll_table *pt = container_of(p, struct io_poll_table, pt);
+       struct async_poll *apoll = pt->req->apoll;
 
-       __io_queue_proc(&pt->req->apoll->poll, pt, head);
+       __io_queue_proc(&apoll->poll, pt, head, &apoll->double_poll);
+}
+
+static void io_sq_thread_drop_mm(struct io_ring_ctx *ctx)
+{
+       struct mm_struct *mm = current->mm;
+
+       if (mm) {
+               kthread_unuse_mm(mm);
+               mmput(mm);
+       }
+}
+
+static int io_sq_thread_acquire_mm(struct io_ring_ctx *ctx,
+                                  struct io_kiocb *req)
+{
+       if (io_op_defs[req->opcode].needs_mm && !current->mm) {
+               if (unlikely(!mmget_not_zero(ctx->sqo_mm)))
+                       return -EFAULT;
+               kthread_use_mm(ctx->sqo_mm);
+       }
+
+       return 0;
 }
 
 static void io_async_task_func(struct callback_head *cb)
@@ -4261,20 +4346,27 @@ static void io_async_task_func(struct callback_head *cb)
                }
        }
 
+       io_poll_remove_double(req, apoll->double_poll);
        spin_unlock_irq(&ctx->completion_lock);
 
        /* restore ->work in case we need to retry again */
        if (req->flags & REQ_F_WORK_INITIALIZED)
                memcpy(&req->work, &apoll->work, sizeof(req->work));
+       kfree(apoll->double_poll);
        kfree(apoll);
 
        if (!canceled) {
                __set_current_state(TASK_RUNNING);
+               if (io_sq_thread_acquire_mm(ctx, req)) {
+                       io_cqring_add_event(req, -EFAULT);
+                       goto end_req;
+               }
                mutex_lock(&ctx->uring_lock);
                __io_queue_sqe(req, NULL);
                mutex_unlock(&ctx->uring_lock);
        } else {
                io_cqring_ev_posted(ctx);
+end_req:
                req_set_fail_links(req);
                io_double_put_req(req);
        }
@@ -4348,7 +4440,6 @@ static bool io_arm_poll_handler(struct io_kiocb *req)
        struct async_poll *apoll;
        struct io_poll_table ipt;
        __poll_t mask, ret;
-       bool had_io;
 
        if (!req->file || !file_can_poll(req->file))
                return false;
@@ -4360,14 +4451,13 @@ static bool io_arm_poll_handler(struct io_kiocb *req)
        apoll = kmalloc(sizeof(*apoll), GFP_ATOMIC);
        if (unlikely(!apoll))
                return false;
+       apoll->double_poll = NULL;
 
        req->flags |= REQ_F_POLLED;
        if (req->flags & REQ_F_WORK_INITIALIZED)
                memcpy(&apoll->work, &req->work, sizeof(req->work));
-       had_io = req->io != NULL;
 
-       get_task_struct(current);
-       req->task = current;
+       io_get_req_task(req);
        req->apoll = apoll;
        INIT_HLIST_NODE(&req->hash_node);
 
@@ -4383,13 +4473,11 @@ static bool io_arm_poll_handler(struct io_kiocb *req)
        ret = __io_arm_poll_handler(req, &apoll->poll, &ipt, mask,
                                        io_async_wake);
        if (ret) {
-               ipt.error = 0;
-               /* only remove double add if we did it here */
-               if (!had_io)
-                       io_poll_remove_double(req);
+               io_poll_remove_double(req, apoll->double_poll);
                spin_unlock_irq(&ctx->completion_lock);
                if (req->flags & REQ_F_WORK_INITIALIZED)
                        memcpy(&req->work, &apoll->work, sizeof(req->work));
+               kfree(apoll->double_poll);
                kfree(apoll);
                return false;
        }
@@ -4420,11 +4508,13 @@ static bool io_poll_remove_one(struct io_kiocb *req)
        bool do_complete;
 
        if (req->opcode == IORING_OP_POLL_ADD) {
-               io_poll_remove_double(req);
+               io_poll_remove_double(req, req->io);
                do_complete = __io_poll_remove_one(req, &req->poll);
        } else {
                struct async_poll *apoll = req->apoll;
 
+               io_poll_remove_double(req, apoll->double_poll);
+
                /* non-poll requests have submit ref still */
                do_complete = __io_poll_remove_one(req, &apoll->poll);
                if (do_complete) {
@@ -4437,6 +4527,7 @@ static bool io_poll_remove_one(struct io_kiocb *req)
                        if (req->flags & REQ_F_WORK_INITIALIZED)
                                memcpy(&req->work, &apoll->work,
                                       sizeof(req->work));
+                       kfree(apoll->double_poll);
                        kfree(apoll);
                }
        }
@@ -4537,7 +4628,7 @@ static void io_poll_queue_proc(struct file *file, struct wait_queue_head *head,
 {
        struct io_poll_table *pt = container_of(p, struct io_poll_table, pt);
 
-       __io_queue_proc(&pt->req->poll, pt, head);
+       __io_queue_proc(&pt->req->poll, pt, head, (struct io_poll_iocb **) &pt->req->io);
 }
 
 static int io_poll_add_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
@@ -4555,8 +4646,7 @@ static int io_poll_add_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
        events = READ_ONCE(sqe->poll_events);
        poll->events = demangle_poll(events) | EPOLLERR | EPOLLHUP;
 
-       get_task_struct(current);
-       req->task = current;
+       io_get_req_task(req);
        return 0;
 }
 
@@ -4567,6 +4657,10 @@ static int io_poll_add(struct io_kiocb *req)
        struct io_poll_table ipt;
        __poll_t mask;
 
+       /* ->work is in union with hash_node and others */
+       io_req_work_drop_env(req);
+       req->flags &= ~REQ_F_WORK_INITIALIZED;
+
        INIT_HLIST_NODE(&req->hash_node);
        INIT_LIST_HEAD(&req->list);
        ipt.pt._qproc = io_poll_queue_proc;
@@ -4646,7 +4740,9 @@ static int io_timeout_remove_prep(struct io_kiocb *req,
 {
        if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
                return -EINVAL;
-       if (sqe->flags || sqe->ioprio || sqe->buf_index || sqe->len)
+       if (unlikely(req->flags & (REQ_F_FIXED_FILE | REQ_F_BUFFER_SELECT)))
+               return -EINVAL;
+       if (sqe->ioprio || sqe->buf_index || sqe->len)
                return -EINVAL;
 
        req->timeout.addr = READ_ONCE(sqe->addr);
@@ -4772,7 +4868,7 @@ static int io_async_cancel_one(struct io_ring_ctx *ctx, void *sqe_addr)
        enum io_wq_cancel cancel_ret;
        int ret = 0;
 
-       cancel_ret = io_wq_cancel_cb(ctx->io_wq, io_cancel_cb, sqe_addr);
+       cancel_ret = io_wq_cancel_cb(ctx->io_wq, io_cancel_cb, sqe_addr, false);
        switch (cancel_ret) {
        case IO_WQ_CANCEL_OK:
                ret = 0;
@@ -4824,8 +4920,9 @@ static int io_async_cancel_prep(struct io_kiocb *req,
 {
        if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
                return -EINVAL;
-       if (sqe->flags || sqe->ioprio || sqe->off || sqe->len ||
-           sqe->cancel_flags)
+       if (unlikely(req->flags & (REQ_F_FIXED_FILE | REQ_F_BUFFER_SELECT)))
+               return -EINVAL;
+       if (sqe->ioprio || sqe->off || sqe->len || sqe->cancel_flags)
                return -EINVAL;
 
        req->cancel.addr = READ_ONCE(sqe->addr);
@@ -4843,7 +4940,9 @@ static int io_async_cancel(struct io_kiocb *req)
 static int io_files_update_prep(struct io_kiocb *req,
                                const struct io_uring_sqe *sqe)
 {
-       if (sqe->flags || sqe->ioprio || sqe->rw_flags)
+       if (unlikely(req->flags & (REQ_F_FIXED_FILE | REQ_F_BUFFER_SELECT)))
+               return -EINVAL;
+       if (sqe->ioprio || sqe->rw_flags)
                return -EINVAL;
 
        req->files_update.offset = READ_ONCE(sqe->off);
@@ -5308,9 +5407,6 @@ static int io_issue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe,
        if ((ctx->flags & IORING_SETUP_IOPOLL) && req->file) {
                const bool in_async = io_wq_current_is_worker();
 
-               if (req->result == -EAGAIN)
-                       return -EAGAIN;
-
                /* workqueue context doesn't hold uring_lock, grab it now */
                if (in_async)
                        mutex_lock(&ctx->uring_lock);
@@ -5637,6 +5733,7 @@ fail_req:
                 * Never try inline submit of IOSQE_ASYNC is set, go straight
                 * to async execution.
                 */
+               io_req_init_async(req);
                req->work.flags |= IO_WQ_WORK_CONCURRENT;
                io_queue_async_work(req);
        } else {
@@ -5817,17 +5914,14 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
        req->flags = 0;
        /* one is dropped after submission, the other at completion */
        refcount_set(&req->refs, 2);
-       req->task = NULL;
+       req->task = current;
        req->result = 0;
 
        if (unlikely(req->opcode >= IORING_OP_LAST))
                return -EINVAL;
 
-       if (io_op_defs[req->opcode].needs_mm && !current->mm) {
-               if (unlikely(!mmget_not_zero(ctx->sqo_mm)))
-                       return -EFAULT;
-               kthread_use_mm(ctx->sqo_mm);
-       }
+       if (unlikely(io_sq_thread_acquire_mm(ctx, req)))
+               return -EFAULT;
 
        sqe_flags = READ_ONCE(sqe->flags);
        /* enforce forwards compatibility on users */
@@ -5936,16 +6030,6 @@ fail_req:
        return submitted;
 }
 
-static inline void io_sq_thread_drop_mm(struct io_ring_ctx *ctx)
-{
-       struct mm_struct *mm = current->mm;
-
-       if (mm) {
-               kthread_unuse_mm(mm);
-               mmput(mm);
-       }
-}
-
 static int io_sq_thread(void *data)
 {
        struct io_ring_ctx *ctx = data;
@@ -5979,7 +6063,7 @@ static int io_sq_thread(void *data)
                 * If submit got -EBUSY, flag us as needing the application
                 * to enter the kernel to reap and flush events.
                 */
-               if (!to_submit || ret == -EBUSY) {
+               if (!to_submit || ret == -EBUSY || need_resched()) {
                        /*
                         * Drop cur_mm before scheduling, we can't hold it for
                         * long periods (or over schedule()). Do this before
@@ -5995,7 +6079,7 @@ static int io_sq_thread(void *data)
                         * more IO, we should wait for the application to
                         * reap events and wake us up.
                         */
-                       if (!list_empty(&ctx->poll_list) ||
+                       if (!list_empty(&ctx->poll_list) || need_resched() ||
                            (!time_after(jiffies, timeout) && ret != -EBUSY &&
                            !percpu_ref_is_dying(&ctx->refs))) {
                                if (current->task_works)
@@ -6021,9 +6105,9 @@ static int io_sq_thread(void *data)
                        }
 
                        /* Tell userspace we may need a wakeup call */
+                       spin_lock_irq(&ctx->completion_lock);
                        ctx->rings->sq_flags |= IORING_SQ_NEED_WAKEUP;
-                       /* make sure to read SQ tail after writing flags */
-                       smp_mb();
+                       spin_unlock_irq(&ctx->completion_lock);
 
                        to_submit = io_sqring_entries(ctx);
                        if (!to_submit || ret == -EBUSY) {
@@ -6041,13 +6125,17 @@ static int io_sq_thread(void *data)
                                schedule();
                                finish_wait(&ctx->sqo_wait, &wait);
 
+                               spin_lock_irq(&ctx->completion_lock);
                                ctx->rings->sq_flags &= ~IORING_SQ_NEED_WAKEUP;
+                               spin_unlock_irq(&ctx->completion_lock);
                                ret = 0;
                                continue;
                        }
                        finish_wait(&ctx->sqo_wait, &wait);
 
+                       spin_lock_irq(&ctx->completion_lock);
                        ctx->rings->sq_flags &= ~IORING_SQ_NEED_WAKEUP;
+                       spin_unlock_irq(&ctx->completion_lock);
                }
 
                mutex_lock(&ctx->uring_lock);
@@ -6146,15 +6234,23 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
        do {
                prepare_to_wait_exclusive(&ctx->wait, &iowq.wq,
                                                TASK_INTERRUPTIBLE);
+               /* make sure we run task_work before checking for signals */
                if (current->task_works)
                        task_work_run();
-               if (io_should_wake(&iowq, false))
-                       break;
-               schedule();
                if (signal_pending(current)) {
+                       if (current->jobctl & JOBCTL_TASK_WORK) {
+                               spin_lock_irq(&current->sighand->siglock);
+                               current->jobctl &= ~JOBCTL_TASK_WORK;
+                               recalc_sigpending();
+                               spin_unlock_irq(&current->sighand->siglock);
+                               continue;
+                       }
                        ret = -EINTR;
                        break;
                }
+               if (io_should_wake(&iowq, false))
+                       break;
+               schedule();
        } while (1);
        finish_wait(&ctx->wait, &iowq.wq);
 
@@ -6626,6 +6722,7 @@ static int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg,
                for (i = 0; i < nr_tables; i++)
                        kfree(ctx->file_data->table[i].files);
 
+               percpu_ref_exit(&ctx->file_data->refs);
                kfree(ctx->file_data->table);
                kfree(ctx->file_data);
                ctx->file_data = NULL;
@@ -6778,8 +6875,10 @@ static int __io_sqe_files_update(struct io_ring_ctx *ctx,
                        }
                        table->files[index] = file;
                        err = io_sqe_file_register(ctx, file, i);
-                       if (err)
+                       if (err) {
+                               fput(file);
                                break;
+                       }
                }
                nr_args--;
                done++;
@@ -7275,9 +7374,6 @@ static void io_ring_ctx_free(struct io_ring_ctx *ctx)
        io_mem_free(ctx->sq_sqes);
 
        percpu_ref_exit(&ctx->refs);
-       if (ctx->account_mem)
-               io_unaccount_mem(ctx->user,
-                               ring_pages(ctx->sq_entries, ctx->cq_entries));
        free_uid(ctx->user);
        put_cred(ctx->creds);
        kfree(ctx->cancel_hash);
@@ -7331,7 +7427,17 @@ static void io_ring_exit_work(struct work_struct *work)
        if (ctx->rings)
                io_cqring_overflow_flush(ctx, true);
 
-       wait_for_completion(&ctx->ref_comp);
+       /*
+        * If we're doing polled IO and end up having requests being
+        * submitted async (out-of-line), then completions can come in while
+        * we're waiting for refs to drop. We need to reap these manually,
+        * as nobody else will be looking for them.
+        */
+       while (!wait_for_completion_timeout(&ctx->ref_comp, HZ/20)) {
+               io_iopoll_reap_events(ctx);
+               if (ctx->rings)
+                       io_cqring_overflow_flush(ctx, true);
+       }
        io_ring_ctx_free(ctx);
 }
 
@@ -7352,6 +7458,16 @@ static void io_ring_ctx_wait_and_kill(struct io_ring_ctx *ctx)
        if (ctx->rings)
                io_cqring_overflow_flush(ctx, true);
        idr_for_each(&ctx->personality_idr, io_remove_personalities, ctx);
+
+       /*
+        * Do this upfront, so we won't have a grace period where the ring
+        * is closed but resources aren't reaped yet. This can cause
+        * spurious failure in setting up a new ring.
+        */
+       if (ctx->account_mem)
+               io_unaccount_mem(ctx->user,
+                               ring_pages(ctx->sq_entries, ctx->cq_entries));
+
        INIT_WORK(&ctx->exit_work, io_ring_exit_work);
        queue_work(system_wq, &ctx->exit_work);
 }
@@ -7365,9 +7481,22 @@ static int io_uring_release(struct inode *inode, struct file *file)
        return 0;
 }
 
+static bool io_wq_files_match(struct io_wq_work *work, void *data)
+{
+       struct files_struct *files = data;
+
+       return work->files == files;
+}
+
 static void io_uring_cancel_files(struct io_ring_ctx *ctx,
                                  struct files_struct *files)
 {
+       if (list_empty_careful(&ctx->inflight_list))
+               return;
+
+       /* cancel all at once, should be faster than doing it one by one*/
+       io_wq_cancel_cb(ctx->io_wq, io_wq_files_match, files, true);
+
        while (!list_empty_careful(&ctx->inflight_list)) {
                struct io_kiocb *cancel_req = NULL, *req;
                DEFINE_WAIT(wait);
@@ -7398,6 +7527,7 @@ static void io_uring_cancel_files(struct io_ring_ctx *ctx,
                        if (list_empty(&ctx->cq_overflow_list)) {
                                clear_bit(0, &ctx->sq_check_overflow);
                                clear_bit(0, &ctx->cq_check_overflow);
+                               ctx->rings->sq_flags &= ~IORING_SQ_CQ_OVERFLOW;
                        }
                        spin_unlock_irq(&ctx->completion_lock);
 
@@ -7423,6 +7553,14 @@ static void io_uring_cancel_files(struct io_ring_ctx *ctx,
        }
 }
 
+static bool io_cancel_task_cb(struct io_wq_work *work, void *data)
+{
+       struct io_kiocb *req = container_of(work, struct io_kiocb, work);
+       struct task_struct *task = data;
+
+       return req->task == task;
+}
+
 static int io_uring_flush(struct file *file, void *data)
 {
        struct io_ring_ctx *ctx = file->private_data;
@@ -7433,7 +7571,7 @@ static int io_uring_flush(struct file *file, void *data)
         * If the task is going away, cancel work it may have pending
         */
        if (fatal_signal_pending(current) || (current->flags & PF_EXITING))
-               io_wq_cancel_pid(ctx->io_wq, task_pid_vnr(current));
+               io_wq_cancel_cb(ctx->io_wq, io_cancel_task_cb, current, true);
 
        return 0;
 }
index a49d0e6..e494443 100644 (file)
@@ -1140,6 +1140,7 @@ static journal_t *journal_init_common(struct block_device *bdev,
        init_waitqueue_head(&journal->j_wait_commit);
        init_waitqueue_head(&journal->j_wait_updates);
        init_waitqueue_head(&journal->j_wait_reserved);
+       mutex_init(&journal->j_abort_mutex);
        mutex_init(&journal->j_barrier);
        mutex_init(&journal->j_checkpoint_mutex);
        spin_lock_init(&journal->j_revoke_lock);
@@ -1402,7 +1403,8 @@ static int jbd2_write_superblock(journal_t *journal, int write_flags)
                printk(KERN_ERR "JBD2: Error %d detected when updating "
                       "journal superblock for %s.\n", ret,
                       journal->j_devname);
-               jbd2_journal_abort(journal, ret);
+               if (!is_journal_aborted(journal))
+                       jbd2_journal_abort(journal, ret);
        }
 
        return ret;
@@ -2153,6 +2155,13 @@ void jbd2_journal_abort(journal_t *journal, int errno)
 {
        transaction_t *transaction;
 
+       /*
+        * Lock the aborting procedure until everything is done, this avoid
+        * races between filesystem's error handling flow (e.g. ext4_abort()),
+        * ensure panic after the error info is written into journal's
+        * superblock.
+        */
+       mutex_lock(&journal->j_abort_mutex);
        /*
         * ESHUTDOWN always takes precedence because a file system check
         * caused by any other journal abort error is not required after
@@ -2167,6 +2176,7 @@ void jbd2_journal_abort(journal_t *journal, int errno)
                        journal->j_errno = errno;
                        jbd2_journal_update_sb_errno(journal);
                }
+               mutex_unlock(&journal->j_abort_mutex);
                return;
        }
 
@@ -2188,10 +2198,7 @@ void jbd2_journal_abort(journal_t *journal, int errno)
         * layer could realise that a filesystem check is needed.
         */
        jbd2_journal_update_sb_errno(journal);
-
-       write_lock(&journal->j_state_lock);
-       journal->j_flags |= JBD2_REC_ERR;
-       write_unlock(&journal->j_state_lock);
+       mutex_unlock(&journal->j_abort_mutex);
 }
 
 /**
index 0637271..8ff4d1a 100644 (file)
@@ -259,7 +259,7 @@ struct jffs2_full_dirent
        uint32_t ino; /* == zero for unlink */
        unsigned int nhash;
        unsigned char type;
-       unsigned char name[0];
+       unsigned char name[];
 };
 
 /*
index 60207a2..e4131cb 100644 (file)
@@ -61,7 +61,7 @@ struct jffs2_sum_dirent_flash
        jint32_t ino;           /* == zero for unlink */
        uint8_t nsize;          /* dirent name size */
        uint8_t type;           /* dirent type */
-       uint8_t name[0];        /* dirent name */
+       uint8_t name[]; /* dirent name */
 } __attribute__((packed));
 
 struct jffs2_sum_xattr_flash
@@ -117,7 +117,7 @@ struct jffs2_sum_dirent_mem
        jint32_t ino;           /* == zero for unlink */
        uint8_t nsize;          /* dirent name size */
        uint8_t type;           /* dirent type */
-       uint8_t name[0];        /* dirent name */
+       uint8_t name[]; /* dirent name */
 } __attribute__((packed));
 
 struct jffs2_sum_xattr_mem
index f30ed40..4a0f600 100644 (file)
@@ -2603,6 +2603,7 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags,
        if (IS_ERR(fc))
                return PTR_ERR(fc);
 
+       fc->oldapi = true;
        err = parse_monolithic_mount_data(fc, data);
        if (!err) {
                down_write(&sb->s_umount);
index 7d399f7..de03e44 100644 (file)
@@ -907,9 +907,8 @@ retry:
                goto out_mds;
 
        /* Use a direct mapping of ds_idx to pgio mirror_idx */
-       if (WARN_ON_ONCE(pgio->pg_mirror_count !=
-           FF_LAYOUT_MIRROR_COUNT(pgio->pg_lseg)))
-               goto out_mds;
+       if (pgio->pg_mirror_count != FF_LAYOUT_MIRROR_COUNT(pgio->pg_lseg))
+               goto out_eagain;
 
        for (i = 0; i < pgio->pg_mirror_count; i++) {
                mirror = FF_LAYOUT_COMP(pgio->pg_lseg, i);
@@ -931,7 +930,10 @@ retry:
                        (NFS_MOUNT_SOFT|NFS_MOUNT_SOFTERR))
                pgio->pg_maxretrans = io_maxretrans;
        return;
-
+out_eagain:
+       pnfs_generic_pg_cleanup(pgio);
+       pgio->pg_error = -EAGAIN;
+       return;
 out_mds:
        trace_pnfs_mds_fallback_pg_init_write(pgio->pg_inode,
                        0, NFS4_MAX_UINT64, IOMODE_RW,
@@ -941,6 +943,7 @@ out_mds:
        pgio->pg_lseg = NULL;
        pgio->pg_maxretrans = 0;
        nfs_pageio_reset_write_mds(pgio);
+       pgio->pg_error = -EAGAIN;
 }
 
 static unsigned int
index a3ab6e2..8733423 100644 (file)
@@ -308,6 +308,7 @@ static int try_location(struct fs_context *fc,
        if (IS_ERR(export_path))
                return PTR_ERR(export_path);
 
+       kfree(ctx->nfs_server.export_path);
        ctx->nfs_server.export_path = export_path;
 
        source = kmalloc(len + 1 + ctx->nfs_server.export_path_len + 1,
index e32717f..2e2dac2 100644 (file)
@@ -774,6 +774,14 @@ static void nfs4_slot_sequence_acked(struct nfs4_slot *slot,
        slot->seq_nr_last_acked = seqnr;
 }
 
+static void nfs4_probe_sequence(struct nfs_client *client, const struct cred *cred,
+                               struct nfs4_slot *slot)
+{
+       struct rpc_task *task = _nfs41_proc_sequence(client, cred, slot, true);
+       if (!IS_ERR(task))
+               rpc_put_task_async(task);
+}
+
 static int nfs41_sequence_process(struct rpc_task *task,
                struct nfs4_sequence_res *res)
 {
@@ -790,6 +798,7 @@ static int nfs41_sequence_process(struct rpc_task *task,
                goto out;
 
        session = slot->table->session;
+       clp = session->clp;
 
        trace_nfs4_sequence_done(session, res);
 
@@ -804,7 +813,6 @@ static int nfs41_sequence_process(struct rpc_task *task,
                nfs4_slot_sequence_acked(slot, slot->seq_nr);
                /* Update the slot's sequence and clientid lease timer */
                slot->seq_done = 1;
-               clp = session->clp;
                do_renew_lease(clp, res->sr_timestamp);
                /* Check sequence flags */
                nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags,
@@ -852,10 +860,18 @@ static int nfs41_sequence_process(struct rpc_task *task,
                /*
                 * Were one or more calls using this slot interrupted?
                 * If the server never received the request, then our
-                * transmitted slot sequence number may be too high.
+                * transmitted slot sequence number may be too high. However,
+                * if the server did receive the request then it might
+                * accidentally give us a reply with a mismatched operation.
+                * We can sort this out by sending a lone sequence operation
+                * to the server on the same slot.
                 */
                if ((s32)(slot->seq_nr - slot->seq_nr_last_acked) > 1) {
                        slot->seq_nr--;
+                       if (task->tk_msg.rpc_proc != &nfs4_procedures[NFSPROC4_CLNT_SEQUENCE]) {
+                               nfs4_probe_sequence(clp, task->tk_msg.rpc_cred, slot);
+                               res->sr_slot = NULL;
+                       }
                        goto retry_nowait;
                }
                /*
index bb3d2c3..c905631 100644 (file)
@@ -507,6 +507,17 @@ find_any_file(struct nfs4_file *f)
        return ret;
 }
 
+static struct nfsd_file *find_deleg_file(struct nfs4_file *f)
+{
+       struct nfsd_file *ret = NULL;
+
+       spin_lock(&f->fi_lock);
+       if (f->fi_deleg_file)
+               ret = nfsd_file_get(f->fi_deleg_file);
+       spin_unlock(&f->fi_lock);
+       return ret;
+}
+
 static atomic_long_t num_delegations;
 unsigned long max_delegations;
 
@@ -2444,6 +2455,8 @@ static int nfs4_show_open(struct seq_file *s, struct nfs4_stid *st)
        oo = ols->st_stateowner;
        nf = st->sc_file;
        file = find_any_file(nf);
+       if (!file)
+               return 0;
 
        seq_printf(s, "- ");
        nfs4_show_stateid(s, &st->sc_stateid);
@@ -2481,6 +2494,8 @@ static int nfs4_show_lock(struct seq_file *s, struct nfs4_stid *st)
        oo = ols->st_stateowner;
        nf = st->sc_file;
        file = find_any_file(nf);
+       if (!file)
+               return 0;
 
        seq_printf(s, "- ");
        nfs4_show_stateid(s, &st->sc_stateid);
@@ -2513,7 +2528,9 @@ static int nfs4_show_deleg(struct seq_file *s, struct nfs4_stid *st)
 
        ds = delegstateid(st);
        nf = st->sc_file;
-       file = nf->fi_deleg_file;
+       file = find_deleg_file(nf);
+       if (!file)
+               return 0;
 
        seq_printf(s, "- ");
        nfs4_show_stateid(s, &st->sc_stateid);
@@ -2529,6 +2546,7 @@ static int nfs4_show_deleg(struct seq_file *s, struct nfs4_stid *st)
        seq_printf(s, ", ");
        nfs4_show_fname(s, file);
        seq_printf(s, " }\n");
+       nfsd_file_put(file);
 
        return 0;
 }
@@ -7912,9 +7930,14 @@ nfs4_state_start_net(struct net *net)
        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
        int ret;
 
-       ret = nfs4_state_create_net(net);
+       ret = get_nfsdfs(net);
        if (ret)
                return ret;
+       ret = nfs4_state_create_net(net);
+       if (ret) {
+               mntput(nn->nfsd_mnt);
+               return ret;
+       }
        locks_start_grace(net, &nn->nfsd4_manager);
        nfsd4_client_tracking_init(net);
        if (nn->track_reclaim_completes && nn->reclaim_str_hashtbl_size == 0)
@@ -7984,6 +8007,7 @@ nfs4_state_shutdown_net(struct net *net)
 
        nfsd4_client_tracking_exit(net);
        nfs4_state_destroy_net(net);
+       mntput(nn->nfsd_mnt);
 }
 
 void
index b68e966..cd05732 100644 (file)
@@ -1335,6 +1335,7 @@ void nfsd_client_rmdir(struct dentry *dentry)
        WARN_ON_ONCE(ret);
        fsnotify_rmdir(dir, dentry);
        d_delete(dentry);
+       dput(dentry);
        inode_unlock(dir);
 }
 
@@ -1424,6 +1425,18 @@ static struct file_system_type nfsd_fs_type = {
 };
 MODULE_ALIAS_FS("nfsd");
 
+int get_nfsdfs(struct net *net)
+{
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+       struct vfsmount *mnt;
+
+       mnt =  vfs_kern_mount(&nfsd_fs_type, SB_KERNMOUNT, "nfsd", NULL);
+       if (IS_ERR(mnt))
+               return PTR_ERR(mnt);
+       nn->nfsd_mnt = mnt;
+       return 0;
+}
+
 #ifdef CONFIG_PROC_FS
 static int create_proc_exports_entry(void)
 {
@@ -1451,7 +1464,6 @@ unsigned int nfsd_net_id;
 static __net_init int nfsd_init_net(struct net *net)
 {
        int retval;
-       struct vfsmount *mnt;
        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
        retval = nfsd_export_init(net);
@@ -1478,16 +1490,8 @@ static __net_init int nfsd_init_net(struct net *net)
        init_waitqueue_head(&nn->ntf_wq);
        seqlock_init(&nn->boot_lock);
 
-       mnt =  vfs_kern_mount(&nfsd_fs_type, SB_KERNMOUNT, "nfsd", NULL);
-       if (IS_ERR(mnt)) {
-               retval = PTR_ERR(mnt);
-               goto out_mount_err;
-       }
-       nn->nfsd_mnt = mnt;
        return 0;
 
-out_mount_err:
-       nfsd_reply_cache_shutdown(nn);
 out_drc_error:
        nfsd_idmap_shutdown(net);
 out_idmap_error:
@@ -1500,7 +1504,6 @@ static __net_exit void nfsd_exit_net(struct net *net)
 {
        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
-       mntput(nn->nfsd_mnt);
        nfsd_reply_cache_shutdown(nn);
        nfsd_idmap_shutdown(net);
        nfsd_export_shutdown(net);
index 36cdd81..57c832d 100644 (file)
@@ -90,6 +90,8 @@ void          nfsd_destroy(struct net *net);
 
 bool           i_am_nfsd(void);
 
+int get_nfsdfs(struct net *);
+
 struct nfsdfs_client {
        struct kref cl_ref;
        void (*cl_release)(struct kref *kref);
@@ -100,6 +102,7 @@ struct dentry *nfsd_client_mkdir(struct nfsd_net *nn,
                struct nfsdfs_client *ncl, u32 id, const struct tree_descr *);
 void nfsd_client_rmdir(struct dentry *dentry);
 
+
 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
 #ifdef CONFIG_NFSD_V2_ACL
 extern const struct svc_version nfsd_acl_version2;
index c3fbab1..d22a056 100644 (file)
@@ -1226,6 +1226,9 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,
                iap->ia_mode = 0;
        iap->ia_mode = (iap->ia_mode & S_IALLUGO) | type;
 
+       if (!IS_POSIXACL(dirp))
+               iap->ia_mode &= ~current_umask();
+
        err = 0;
        host_err = 0;
        switch (type) {
@@ -1458,6 +1461,9 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
                goto out;
        }
 
+       if (!IS_POSIXACL(dirp))
+               iap->ia_mode &= ~current_umask();
+
        host_err = vfs_create(dirp, dchild, iap->ia_mode, true);
        if (host_err < 0) {
                fh_drop_write(fhp);
index 152a0fc..751bc4d 100644 (file)
@@ -689,6 +689,12 @@ static void ocfs2_nfs_sync_lock_res_init(struct ocfs2_lock_res *res,
                                   &ocfs2_nfs_sync_lops, osb);
 }
 
+static void ocfs2_nfs_sync_lock_init(struct ocfs2_super *osb)
+{
+       ocfs2_nfs_sync_lock_res_init(&osb->osb_nfs_sync_lockres, osb);
+       init_rwsem(&osb->nfs_sync_rwlock);
+}
+
 void ocfs2_trim_fs_lock_res_init(struct ocfs2_super *osb)
 {
        struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
@@ -2855,6 +2861,11 @@ int ocfs2_nfs_sync_lock(struct ocfs2_super *osb, int ex)
        if (ocfs2_is_hard_readonly(osb))
                return -EROFS;
 
+       if (ex)
+               down_write(&osb->nfs_sync_rwlock);
+       else
+               down_read(&osb->nfs_sync_rwlock);
+
        if (ocfs2_mount_local(osb))
                return 0;
 
@@ -2873,6 +2884,10 @@ void ocfs2_nfs_sync_unlock(struct ocfs2_super *osb, int ex)
        if (!ocfs2_mount_local(osb))
                ocfs2_cluster_unlock(osb, lockres,
                                     ex ? LKM_EXMODE : LKM_PRMODE);
+       if (ex)
+               up_write(&osb->nfs_sync_rwlock);
+       else
+               up_read(&osb->nfs_sync_rwlock);
 }
 
 int ocfs2_trim_fs_lock(struct ocfs2_super *osb,
@@ -3340,7 +3355,7 @@ int ocfs2_dlm_init(struct ocfs2_super *osb)
 local:
        ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb);
        ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb);
-       ocfs2_nfs_sync_lock_res_init(&osb->osb_nfs_sync_lockres, osb);
+       ocfs2_nfs_sync_lock_init(osb);
        ocfs2_orphan_scan_lock_res_init(&osb->osb_orphan_scan.os_lockres, osb);
 
        osb->cconn = conn;
index ee5d985..2dd71d6 100644 (file)
@@ -395,6 +395,7 @@ struct ocfs2_super
        struct ocfs2_lock_res osb_super_lockres;
        struct ocfs2_lock_res osb_rename_lockres;
        struct ocfs2_lock_res osb_nfs_sync_lockres;
+       struct rw_semaphore nfs_sync_rwlock;
        struct ocfs2_lock_res osb_trim_fs_lockres;
        struct mutex obs_trim_fs_mutex;
        struct ocfs2_dlm_debug *osb_dlm_debug;
index 0dd8c41..19137c6 100644 (file)
 #define OCFS2_MAX_SLOTS                        255
 
 /* Slot map indicator for an empty slot */
-#define OCFS2_INVALID_SLOT             -1
+#define OCFS2_INVALID_SLOT             ((u16)-1)
 
 #define OCFS2_VOL_UUID_LEN             16
 #define OCFS2_MAX_VOL_LABEL_LEN                64
@@ -326,8 +326,8 @@ struct ocfs2_system_inode_info {
 enum {
        BAD_BLOCK_SYSTEM_INODE = 0,
        GLOBAL_INODE_ALLOC_SYSTEM_INODE,
+#define OCFS2_FIRST_ONLINE_SYSTEM_INODE GLOBAL_INODE_ALLOC_SYSTEM_INODE
        SLOT_MAP_SYSTEM_INODE,
-#define OCFS2_FIRST_ONLINE_SYSTEM_INODE SLOT_MAP_SYSTEM_INODE
        HEARTBEAT_SYSTEM_INODE,
        GLOBAL_BITMAP_SYSTEM_INODE,
        USER_QUOTA_SYSTEM_INODE,
index 4836bec..45745cc 100644 (file)
@@ -2825,9 +2825,12 @@ int ocfs2_test_inode_bit(struct ocfs2_super *osb, u64 blkno, int *res)
                goto bail;
        }
 
-       inode_alloc_inode =
-               ocfs2_get_system_file_inode(osb, INODE_ALLOC_SYSTEM_INODE,
-                                           suballoc_slot);
+       if (suballoc_slot == (u16)OCFS2_INVALID_SLOT)
+               inode_alloc_inode = ocfs2_get_system_file_inode(osb,
+                       GLOBAL_INODE_ALLOC_SYSTEM_INODE, suballoc_slot);
+       else
+               inode_alloc_inode = ocfs2_get_system_file_inode(osb,
+                       INODE_ALLOC_SYSTEM_INODE, suballoc_slot);
        if (!inode_alloc_inode) {
                /* the error code could be inaccurate, but we are not able to
                 * get the correct one. */
index 79dd052..5e0cde8 100644 (file)
@@ -895,7 +895,7 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
        return err;
 }
 
-int ovl_copy_up_flags(struct dentry *dentry, int flags)
+static int ovl_copy_up_flags(struct dentry *dentry, int flags)
 {
        int err = 0;
        const struct cred *old_cred = ovl_override_creds(dentry->d_sb);
index 8f42864..0e696f7 100644 (file)
@@ -476,7 +476,7 @@ static struct dentry *ovl_lookup_real_inode(struct super_block *sb,
        if (IS_ERR_OR_NULL(this))
                return this;
 
-       if (WARN_ON(ovl_dentry_real_at(this, layer->idx) != real)) {
+       if (ovl_dentry_real_at(this, layer->idx) != real) {
                dput(this);
                this = ERR_PTR(-EIO);
        }
index 01820e6..0d940e2 100644 (file)
@@ -33,13 +33,16 @@ static char ovl_whatisit(struct inode *inode, struct inode *realinode)
                return 'm';
 }
 
+/* No atime modificaton nor notify on underlying */
+#define OVL_OPEN_FLAGS (O_NOATIME | FMODE_NONOTIFY)
+
 static struct file *ovl_open_realfile(const struct file *file,
                                      struct inode *realinode)
 {
        struct inode *inode = file_inode(file);
        struct file *realfile;
        const struct cred *old_cred;
-       int flags = file->f_flags | O_NOATIME | FMODE_NONOTIFY;
+       int flags = file->f_flags | OVL_OPEN_FLAGS;
        int acc_mode = ACC_MODE(flags);
        int err;
 
@@ -72,8 +75,7 @@ static int ovl_change_flags(struct file *file, unsigned int flags)
        struct inode *inode = file_inode(file);
        int err;
 
-       /* No atime modificaton on underlying */
-       flags |= O_NOATIME | FMODE_NONOTIFY;
+       flags |= OVL_OPEN_FLAGS;
 
        /* If some flag changed that cannot be changed then something's amiss */
        if (WARN_ON((file->f_flags ^ flags) & ~OVL_SETFL_MASK))
@@ -126,7 +128,7 @@ static int ovl_real_fdget_meta(const struct file *file, struct fd *real,
        }
 
        /* Did the flags change since open? */
-       if (unlikely((file->f_flags ^ real->file->f_flags) & ~O_NOATIME))
+       if (unlikely((file->f_flags ^ real->file->f_flags) & ~OVL_OPEN_FLAGS))
                return ovl_change_flags(real->file, file->f_flags);
 
        return 0;
index 3566282..f7d4358 100644 (file)
@@ -389,7 +389,7 @@ invalid:
 }
 
 static int ovl_check_origin(struct ovl_fs *ofs, struct dentry *upperdentry,
-                           struct ovl_path **stackp, unsigned int *ctrp)
+                           struct ovl_path **stackp)
 {
        struct ovl_fh *fh = ovl_get_fh(upperdentry, OVL_XATTR_ORIGIN);
        int err;
@@ -406,10 +406,6 @@ static int ovl_check_origin(struct ovl_fs *ofs, struct dentry *upperdentry,
                return err;
        }
 
-       if (WARN_ON(*ctrp))
-               return -EIO;
-
-       *ctrp = 1;
        return 0;
 }
 
@@ -861,8 +857,6 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
                        goto out;
                }
                if (upperdentry && !d.is_dir) {
-                       unsigned int origin_ctr = 0;
-
                        /*
                         * Lookup copy up origin by decoding origin file handle.
                         * We may get a disconnected dentry, which is fine,
@@ -873,8 +867,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
                         * number - it's the same as if we held a reference
                         * to a dentry in lower layer that was moved under us.
                         */
-                       err = ovl_check_origin(ofs, upperdentry, &origin_path,
-                                              &origin_ctr);
+                       err = ovl_check_origin(ofs, upperdentry, &origin_path);
                        if (err)
                                goto out_put_upper;
 
@@ -1073,6 +1066,10 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
                        upperredirect = NULL;
                        goto out_free_oe;
                }
+               err = ovl_check_metacopy_xattr(upperdentry);
+               if (err < 0)
+                       goto out_free_oe;
+               uppermetacopy = err;
        }
 
        if (upperdentry || ctr) {
index b725c7f..29bc1ec 100644 (file)
@@ -483,7 +483,6 @@ void ovl_aio_request_cache_destroy(void);
 /* copy_up.c */
 int ovl_copy_up(struct dentry *dentry);
 int ovl_copy_up_with_data(struct dentry *dentry);
-int ovl_copy_up_flags(struct dentry *dentry, int flags);
 int ovl_maybe_copy_up(struct dentry *dentry, int flags);
 int ovl_copy_xattr(struct dentry *old, struct dentry *new);
 int ovl_set_attr(struct dentry *upper, struct kstat *stat);
index 91476bc..4b38141 100644 (file)
@@ -580,12 +580,19 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
                }
        }
 
-       /* Workdir is useless in non-upper mount */
-       if (!config->upperdir && config->workdir) {
-               pr_info("option \"workdir=%s\" is useless in a non-upper mount, ignore\n",
-                       config->workdir);
-               kfree(config->workdir);
-               config->workdir = NULL;
+       /* Workdir/index are useless in non-upper mount */
+       if (!config->upperdir) {
+               if (config->workdir) {
+                       pr_info("option \"workdir=%s\" is useless in a non-upper mount, ignore\n",
+                               config->workdir);
+                       kfree(config->workdir);
+                       config->workdir = NULL;
+               }
+               if (config->index && index_opt) {
+                       pr_info("option \"index=on\" is useless in a non-upper mount, ignore\n");
+                       index_opt = false;
+               }
+               config->index = false;
        }
 
        err = ovl_parse_redirect_mode(config, config->redirect_mode);
@@ -622,11 +629,13 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
 
        /* Resolve nfs_export -> index dependency */
        if (config->nfs_export && !config->index) {
-               if (nfs_export_opt && index_opt) {
+               if (!config->upperdir && config->redirect_follow) {
+                       pr_info("NFS export requires \"redirect_dir=nofollow\" on non-upper mount, falling back to nfs_export=off.\n");
+                       config->nfs_export = false;
+               } else if (nfs_export_opt && index_opt) {
                        pr_err("conflicting options: nfs_export=on,index=off\n");
                        return -EINVAL;
-               }
-               if (index_opt) {
+               } else if (index_opt) {
                        /*
                         * There was an explicit index=off that resulted
                         * in this conflict.
@@ -1352,8 +1361,15 @@ static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs,
                goto out;
        }
 
+       /* index dir will act also as workdir */
+       iput(ofs->workdir_trap);
+       ofs->workdir_trap = NULL;
+       dput(ofs->workdir);
+       ofs->workdir = NULL;
        ofs->indexdir = ovl_workdir_create(ofs, OVL_INDEXDIR_NAME, true);
        if (ofs->indexdir) {
+               ofs->workdir = dget(ofs->indexdir);
+
                err = ovl_setup_trap(sb, ofs->indexdir, &ofs->indexdir_trap,
                                     "indexdir");
                if (err)
@@ -1396,6 +1412,18 @@ static bool ovl_lower_uuid_ok(struct ovl_fs *ofs, const uuid_t *uuid)
        if (!ofs->config.nfs_export && !ovl_upper_mnt(ofs))
                return true;
 
+       /*
+        * We allow using single lower with null uuid for index and nfs_export
+        * for example to support those features with single lower squashfs.
+        * To avoid regressions in setups of overlay with re-formatted lower
+        * squashfs, do not allow decoding origin with lower null uuid unless
+        * user opted-in to one of the new features that require following the
+        * lower inode of non-dir upper.
+        */
+       if (!ofs->config.index && !ofs->config.metacopy && !ofs->config.xino &&
+           uuid_is_null(uuid))
+               return false;
+
        for (i = 0; i < ofs->numfs; i++) {
                /*
                 * We use uuid to associate an overlay lower file handle with a
@@ -1493,14 +1521,23 @@ static int ovl_get_layers(struct super_block *sb, struct ovl_fs *ofs,
                if (err < 0)
                        goto out;
 
+               /*
+                * Check if lower root conflicts with this overlay layers before
+                * checking if it is in-use as upperdir/workdir of "another"
+                * mount, because we do not bother to check in ovl_is_inuse() if
+                * the upperdir/workdir is in fact in-use by our
+                * upperdir/workdir.
+                */
                err = ovl_setup_trap(sb, stack[i].dentry, &trap, "lowerdir");
                if (err)
                        goto out;
 
                if (ovl_is_inuse(stack[i].dentry)) {
                        err = ovl_report_in_use(ofs, "lowerdir");
-                       if (err)
+                       if (err) {
+                               iput(trap);
                                goto out;
+                       }
                }
 
                mnt = clone_private_mount(&stack[i]);
@@ -1575,10 +1612,6 @@ static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb,
        if (!ofs->config.upperdir && numlower == 1) {
                pr_err("at least 2 lowerdir are needed while upperdir nonexistent\n");
                return ERR_PTR(-EINVAL);
-       } else if (!ofs->config.upperdir && ofs->config.nfs_export &&
-                  ofs->config.redirect_follow) {
-               pr_warn("NFS export requires \"redirect_dir=nofollow\" on non-upper mount, falling back to nfs_export=off.\n");
-               ofs->config.nfs_export = false;
        }
 
        stack = kcalloc(numlower, sizeof(struct path), GFP_KERNEL);
@@ -1842,21 +1875,13 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
        if (!ovl_upper_mnt(ofs))
                sb->s_flags |= SB_RDONLY;
 
-       if (!(ovl_force_readonly(ofs)) && ofs->config.index) {
-               /* index dir will act also as workdir */
-               dput(ofs->workdir);
-               ofs->workdir = NULL;
-               iput(ofs->workdir_trap);
-               ofs->workdir_trap = NULL;
-
+       if (!ovl_force_readonly(ofs) && ofs->config.index) {
                err = ovl_get_indexdir(sb, ofs, oe, &upperpath);
                if (err)
                        goto out_free_oe;
 
                /* Force r/o mount with no index dir */
-               if (ofs->indexdir)
-                       ofs->workdir = dget(ofs->indexdir);
-               else
+               if (!ofs->indexdir)
                        sb->s_flags |= SB_RDONLY;
        }
 
index 9955d75..ad31ec4 100644 (file)
@@ -26,8 +26,9 @@ static int boot_config_proc_show(struct seq_file *m, void *v)
 static int __init copy_xbc_key_value_list(char *dst, size_t size)
 {
        struct xbc_node *leaf, *vnode;
-       const char *val;
        char *key, *end = dst + size;
+       const char *val;
+       char q;
        int ret = 0;
 
        key = kzalloc(XBC_KEYLEN_MAX, GFP_KERNEL);
@@ -41,16 +42,20 @@ static int __init copy_xbc_key_value_list(char *dst, size_t size)
                        break;
                dst += ret;
                vnode = xbc_node_get_child(leaf);
-               if (vnode && xbc_node_is_array(vnode)) {
+               if (vnode) {
                        xbc_array_for_each_value(vnode, val) {
-                               ret = snprintf(dst, rest(dst, end), "\"%s\"%s",
-                                       val, vnode->next ? ", " : "\n");
+                               if (strchr(val, '"'))
+                                       q = '\'';
+                               else
+                                       q = '"';
+                               ret = snprintf(dst, rest(dst, end), "%c%s%c%s",
+                                       q, val, q, vnode->next ? ", " : "\n");
                                if (ret < 0)
                                        goto out;
                                dst += ret;
                        }
                } else {
-                       ret = snprintf(dst, rest(dst, end), "\"%s\"\n", val);
+                       ret = snprintf(dst, rest(dst, end), "\"\"\n");
                        if (ret < 0)
                                break;
                        dst += ret;
index 8ba492d..e502414 100644 (file)
@@ -512,7 +512,8 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
                                 * Using bounce buffer to bypass the
                                 * hardened user copy kernel text checks.
                                 */
-                               if (probe_kernel_read(buf, (void *) start, tsz)) {
+                               if (copy_from_kernel_nofault(buf, (void *)start,
+                                               tsz)) {
                                        if (clear_user(buffer, tsz)) {
                                                ret = -EFAULT;
                                                goto out;
index 42c5128..6c1166c 100644 (file)
@@ -566,8 +566,9 @@ static ssize_t proc_sys_call_handler(struct file *filp, void __user *ubuf,
                goto out;
 
        /* don't even try if the size is too large */
-       if (count > KMALLOC_MAX_SIZE)
-               return -ENOMEM;
+       error = -ENOMEM;
+       if (count >= KMALLOC_MAX_SIZE)
+               goto out;
 
        if (write) {
                kbuf = memdup_user_nul(ubuf, count);
@@ -576,7 +577,6 @@ static ssize_t proc_sys_call_handler(struct file *filp, void __user *ubuf,
                        goto out;
                }
        } else {
-               error = -ENOMEM;
                kbuf = kzalloc(count, GFP_KERNEL);
                if (!kbuf)
                        goto out;
index bbfa9b1..4fb7978 100644 (file)
@@ -419,28 +419,42 @@ static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, lo
        return ret;
 }
 
-ssize_t __vfs_read(struct file *file, char __user *buf, size_t count,
-                  loff_t *pos)
+ssize_t __kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
 {
+       mm_segment_t old_fs = get_fs();
+       ssize_t ret;
+
+       if (WARN_ON_ONCE(!(file->f_mode & FMODE_READ)))
+               return -EINVAL;
+       if (!(file->f_mode & FMODE_CAN_READ))
+               return -EINVAL;
+
+       if (count > MAX_RW_COUNT)
+               count =  MAX_RW_COUNT;
+       set_fs(KERNEL_DS);
        if (file->f_op->read)
-               return file->f_op->read(file, buf, count, pos);
+               ret = file->f_op->read(file, (void __user *)buf, count, pos);
        else if (file->f_op->read_iter)
-               return new_sync_read(file, buf, count, pos);
+               ret = new_sync_read(file, (void __user *)buf, count, pos);
        else
-               return -EINVAL;
+               ret = -EINVAL;
+       set_fs(old_fs);
+       if (ret > 0) {
+               fsnotify_access(file);
+               add_rchar(current, ret);
+       }
+       inc_syscr(current);
+       return ret;
 }
 
 ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
 {
-       mm_segment_t old_fs;
-       ssize_t result;
+       ssize_t ret;
 
-       old_fs = get_fs();
-       set_fs(KERNEL_DS);
-       /* The cast to a user pointer is valid due to the set_fs() */
-       result = vfs_read(file, (void __user *)buf, count, pos);
-       set_fs(old_fs);
-       return result;
+       ret = rw_verify_area(READ, file, pos, count);
+       if (ret)
+               return ret;
+       return __kernel_read(file, buf, count, pos);
 }
 EXPORT_SYMBOL(kernel_read);
 
@@ -456,17 +470,22 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
                return -EFAULT;
 
        ret = rw_verify_area(READ, file, pos, count);
-       if (!ret) {
-               if (count > MAX_RW_COUNT)
-                       count =  MAX_RW_COUNT;
-               ret = __vfs_read(file, buf, count, pos);
-               if (ret > 0) {
-                       fsnotify_access(file);
-                       add_rchar(current, ret);
-               }
-               inc_syscr(current);
-       }
+       if (ret)
+               return ret;
+       if (count > MAX_RW_COUNT)
+               count =  MAX_RW_COUNT;
 
+       if (file->f_op->read)
+               ret = file->f_op->read(file, buf, count, pos);
+       else if (file->f_op->read_iter)
+               ret = new_sync_read(file, buf, count, pos);
+       else
+               ret = -EINVAL;
+       if (ret > 0) {
+               fsnotify_access(file);
+               add_rchar(current, ret);
+       }
+       inc_syscr(current);
        return ret;
 }
 
@@ -488,23 +507,15 @@ static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t
        return ret;
 }
 
-static ssize_t __vfs_write(struct file *file, const char __user *p,
-                          size_t count, loff_t *pos)
-{
-       if (file->f_op->write)
-               return file->f_op->write(file, p, count, pos);
-       else if (file->f_op->write_iter)
-               return new_sync_write(file, p, count, pos);
-       else
-               return -EINVAL;
-}
-
+/* caller is responsible for file_start_write/file_end_write */
 ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
 {
        mm_segment_t old_fs;
        const char __user *p;
        ssize_t ret;
 
+       if (WARN_ON_ONCE(!(file->f_mode & FMODE_WRITE)))
+               return -EBADF;
        if (!(file->f_mode & FMODE_CAN_WRITE))
                return -EINVAL;
 
@@ -513,7 +524,12 @@ ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t
        p = (__force const char __user *)buf;
        if (count > MAX_RW_COUNT)
                count =  MAX_RW_COUNT;
-       ret = __vfs_write(file, p, count, pos);
+       if (file->f_op->write)
+               ret = file->f_op->write(file, p, count, pos);
+       else if (file->f_op->write_iter)
+               ret = new_sync_write(file, p, count, pos);
+       else
+               ret = -EINVAL;
        set_fs(old_fs);
        if (ret > 0) {
                fsnotify_modify(file);
@@ -522,21 +538,20 @@ ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t
        inc_syscw(current);
        return ret;
 }
-EXPORT_SYMBOL(__kernel_write);
 
 ssize_t kernel_write(struct file *file, const void *buf, size_t count,
                            loff_t *pos)
 {
-       mm_segment_t old_fs;
-       ssize_t res;
+       ssize_t ret;
 
-       old_fs = get_fs();
-       set_fs(KERNEL_DS);
-       /* The cast to a user pointer is valid due to the set_fs() */
-       res = vfs_write(file, (__force const char __user *)buf, count, pos);
-       set_fs(old_fs);
+       ret = rw_verify_area(WRITE, file, pos, count);
+       if (ret)
+               return ret;
 
-       return res;
+       file_start_write(file);
+       ret =  __kernel_write(file, buf, count, pos);
+       file_end_write(file);
+       return ret;
 }
 EXPORT_SYMBOL(kernel_write);
 
@@ -552,19 +567,23 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
                return -EFAULT;
 
        ret = rw_verify_area(WRITE, file, pos, count);
-       if (!ret) {
-               if (count > MAX_RW_COUNT)
-                       count =  MAX_RW_COUNT;
-               file_start_write(file);
-               ret = __vfs_write(file, buf, count, pos);
-               if (ret > 0) {
-                       fsnotify_modify(file);
-                       add_wchar(current, ret);
-               }
-               inc_syscw(current);
-               file_end_write(file);
+       if (ret)
+               return ret;
+       if (count > MAX_RW_COUNT)
+               count =  MAX_RW_COUNT;
+       file_start_write(file);
+       if (file->f_op->write)
+               ret = file->f_op->write(file, buf, count, pos);
+       else if (file->f_op->write_iter)
+               ret = new_sync_write(file, buf, count, pos);
+       else
+               ret = -EINVAL;
+       if (ret > 0) {
+               fsnotify_modify(file);
+               add_wchar(current, ret);
        }
-
+       inc_syscw(current);
+       file_end_write(file);
        return ret;
 }
 
index 64f6133..76bb1c8 100644 (file)
@@ -175,7 +175,7 @@ int squashfs_read_data(struct super_block *sb, u64 index, int length,
                /* Extract the length of the metadata block */
                data = page_address(bvec->bv_page) + bvec->bv_offset;
                length = data[offset];
-               if (offset <= bvec->bv_len - 1) {
+               if (offset < bvec->bv_len - 1) {
                        length |= data[offset + 1] << 8;
                } else {
                        if (WARN_ON_ONCE(!bio_next_segment(bio, &iter_all))) {
index 7187bd1..8d64edb 100644 (file)
@@ -262,7 +262,7 @@ struct squashfs_dir_index {
        __le32                  index;
        __le32                  start_block;
        __le32                  size;
-       unsigned char           name[0];
+       unsigned char           name[];
 };
 
 struct squashfs_base_inode {
@@ -327,7 +327,7 @@ struct squashfs_symlink_inode {
        __le32                  inode_number;
        __le32                  nlink;
        __le32                  symlink_size;
-       char                    symlink[0];
+       char                    symlink[];
 };
 
 struct squashfs_reg_inode {
@@ -341,7 +341,7 @@ struct squashfs_reg_inode {
        __le32                  fragment;
        __le32                  offset;
        __le32                  file_size;
-       __le16                  block_list[0];
+       __le16                  block_list[];
 };
 
 struct squashfs_lreg_inode {
@@ -358,7 +358,7 @@ struct squashfs_lreg_inode {
        __le32                  fragment;
        __le32                  offset;
        __le32                  xattr;
-       __le16                  block_list[0];
+       __le16                  block_list[];
 };
 
 struct squashfs_dir_inode {
@@ -389,7 +389,7 @@ struct squashfs_ldir_inode {
        __le16                  i_count;
        __le16                  offset;
        __le32                  xattr;
-       struct squashfs_dir_index       index[0];
+       struct squashfs_dir_index       index[];
 };
 
 union squashfs_inode {
@@ -410,7 +410,7 @@ struct squashfs_dir_entry {
        __le16                  inode_number;
        __le16                  type;
        __le16                  size;
-       char                    name[0];
+       char                    name[];
 };
 
 struct squashfs_dir_header {
@@ -428,12 +428,12 @@ struct squashfs_fragment_entry {
 struct squashfs_xattr_entry {
        __le16                  type;
        __le16                  size;
-       char                    data[0];
+       char                    data[];
 };
 
 struct squashfs_xattr_val {
        __le32                  vsize;
-       char                    value[0];
+       char                    value[];
 };
 
 struct squashfs_xattr_id {
index b43f0e8..9ed9036 100644 (file)
@@ -671,7 +671,8 @@ xlog_cil_push_work(
        /*
         * Wake up any background push waiters now this context is being pushed.
         */
-       wake_up_all(&ctx->push_wait);
+       if (ctx->space_used >= XLOG_CIL_BLOCKING_SPACE_LIMIT(log))
+               wake_up_all(&cil->xc_push_wait);
 
        /*
         * Check if we've anything to push. If there is nothing, then we don't
@@ -743,13 +744,12 @@ xlog_cil_push_work(
 
        /*
         * initialise the new context and attach it to the CIL. Then attach
-        * the current context to the CIL committing lsit so it can be found
+        * the current context to the CIL committing list so it can be found
         * during log forces to extract the commit lsn of the sequence that
         * needs to be forced.
         */
        INIT_LIST_HEAD(&new_ctx->committing);
        INIT_LIST_HEAD(&new_ctx->busy_extents);
-       init_waitqueue_head(&new_ctx->push_wait);
        new_ctx->sequence = ctx->sequence + 1;
        new_ctx->cil = cil;
        cil->xc_ctx = new_ctx;
@@ -937,7 +937,7 @@ xlog_cil_push_background(
        if (cil->xc_ctx->space_used >= XLOG_CIL_BLOCKING_SPACE_LIMIT(log)) {
                trace_xfs_log_cil_wait(log, cil->xc_ctx->ticket);
                ASSERT(cil->xc_ctx->space_used < log->l_logsize);
-               xlog_wait(&cil->xc_ctx->push_wait, &cil->xc_push_lock);
+               xlog_wait(&cil->xc_push_wait, &cil->xc_push_lock);
                return;
        }
 
@@ -1216,12 +1216,12 @@ xlog_cil_init(
        INIT_LIST_HEAD(&cil->xc_committing);
        spin_lock_init(&cil->xc_cil_lock);
        spin_lock_init(&cil->xc_push_lock);
+       init_waitqueue_head(&cil->xc_push_wait);
        init_rwsem(&cil->xc_ctx_lock);
        init_waitqueue_head(&cil->xc_commit_wait);
 
        INIT_LIST_HEAD(&ctx->committing);
        INIT_LIST_HEAD(&ctx->busy_extents);
-       init_waitqueue_head(&ctx->push_wait);
        ctx->sequence = 1;
        ctx->cil = cil;
        cil->xc_ctx = ctx;
index ec22c7a..75a6287 100644 (file)
@@ -240,7 +240,6 @@ struct xfs_cil_ctx {
        struct xfs_log_vec      *lv_chain;      /* logvecs being pushed */
        struct list_head        iclog_entry;
        struct list_head        committing;     /* ctx committing list */
-       wait_queue_head_t       push_wait;      /* background push throttle */
        struct work_struct      discard_endio_work;
 };
 
@@ -274,6 +273,7 @@ struct xfs_cil {
        wait_queue_head_t       xc_commit_wait;
        xfs_lsn_t               xc_current_sequence;
        struct work_struct      xc_push_work;
+       wait_queue_head_t       xc_push_wait;   /* background push throttle */
 } ____cacheline_aligned_in_smp;
 
 /*
index 07bc42d..abfb17f 100644 (file)
@@ -607,14 +607,14 @@ static ssize_t zonefs_file_dio_append(struct kiocb *iocb, struct iov_iter *from)
        int nr_pages;
        ssize_t ret;
 
-       nr_pages = iov_iter_npages(from, BIO_MAX_PAGES);
-       if (!nr_pages)
-               return 0;
-
        max = queue_max_zone_append_sectors(bdev_get_queue(bdev));
        max = ALIGN_DOWN(max << SECTOR_SHIFT, inode->i_sb->s_blocksize);
        iov_iter_truncate(from, max);
 
+       nr_pages = iov_iter_npages(from, BIO_MAX_PAGES);
+       if (!nr_pages)
+               return 0;
+
        bio = bio_alloc_bioset(GFP_NOFS, nr_pages, &fs_bio_set);
        if (!bio)
                return -ENOMEM;
@@ -1119,7 +1119,7 @@ static int zonefs_create_zgroup(struct zonefs_zone_data *zd,
        char *file_name;
        struct dentry *dir;
        unsigned int n = 0;
-       int ret = -ENOMEM;
+       int ret;
 
        /* If the group is empty, there is nothing to do */
        if (!zd->nr_zones[type])
@@ -1135,8 +1135,10 @@ static int zonefs_create_zgroup(struct zonefs_zone_data *zd,
                zgroup_name = "seq";
 
        dir = zonefs_create_inode(sb->s_root, zgroup_name, NULL, type);
-       if (!dir)
+       if (!dir) {
+               ret = -ENOMEM;
                goto free;
+       }
 
        /*
         * The first zone contains the super block: skip it.
@@ -1174,8 +1176,10 @@ static int zonefs_create_zgroup(struct zonefs_zone_data *zd,
                 * Use the file number within its group as file name.
                 */
                snprintf(file_name, ZONEFS_NAME_MAX - 1, "%u", n);
-               if (!zonefs_create_inode(dir, file_name, zone, type))
+               if (!zonefs_create_inode(dir, file_name, zone, type)) {
+                       ret = -ENOMEM;
                        goto free;
+               }
 
                n++;
        }
index 907fa5d..4a674db 100644 (file)
@@ -2,6 +2,11 @@
 #ifndef _ASM_GENERIC_CACHEFLUSH_H
 #define _ASM_GENERIC_CACHEFLUSH_H
 
+struct mm_struct;
+struct vm_area_struct;
+struct page;
+struct address_space;
+
 /*
  * The cache doesn't need to be flushed when TLB entries change when
  * the cache is mapped to physical memory, not virtual memory
index 40f85de..8e1e624 100644 (file)
@@ -122,7 +122,7 @@ static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 #ifndef __HAVE_ARCH_HUGE_PTEP_GET
 static inline pte_t huge_ptep_get(pte_t *ptep)
 {
-       return READ_ONCE(*ptep);
+       return ptep_get(ptep);
 }
 #endif
 
index 8b1e020..30a3aab 100644 (file)
@@ -456,7 +456,7 @@ static inline void writesq(volatile void __iomem *addr, const void *buffer,
 
 #if !defined(inb) && !defined(_inb)
 #define _inb _inb
-static inline u16 _inb(unsigned long addr)
+static inline u8 _inb(unsigned long addr)
 {
        u8 val;
 
@@ -482,7 +482,7 @@ static inline u16 _inw(unsigned long addr)
 
 #if !defined(inl) && !defined(_inl)
 #define _inl _inl
-static inline u16 _inl(unsigned long addr)
+static inline u32 _inl(unsigned long addr)
 {
        u32 val;
 
index 9439ff0..5698fca 100644 (file)
@@ -27,7 +27,7 @@
 #include <asm/smp.h>
 
 DECLARE_PER_CPU(struct mmiowb_state, __mmiowb_state);
-#define __mmiowb_state()       this_cpu_ptr(&__mmiowb_state)
+#define __mmiowb_state()       raw_cpu_ptr(&__mmiowb_state)
 #else
 #define __mmiowb_state()       arch_mmiowb_state()
 #endif /* arch_mmiowb_state */
@@ -35,7 +35,9 @@ DECLARE_PER_CPU(struct mmiowb_state, __mmiowb_state);
 static inline void mmiowb_set_pending(void)
 {
        struct mmiowb_state *ms = __mmiowb_state();
-       ms->mmiowb_pending = ms->nesting_count;
+
+       if (likely(ms->nesting_count))
+               ms->mmiowb_pending = ms->nesting_count;
 }
 
 static inline void mmiowb_spin_lock(void)
index db600ef..052e0f0 100644 (file)
 
 #define PAGE_ALIGNED_DATA(page_align)                                  \
        . = ALIGN(page_align);                                          \
-       *(.data..page_aligned)
+       *(.data..page_aligned)                                          \
+       . = ALIGN(page_align);
 
 #define READ_MOSTLY_DATA(align)                                                \
        . = ALIGN(align);                                               \
        . = ALIGN(bss_align);                                           \
        .bss : AT(ADDR(.bss) - LOAD_OFFSET) {                           \
                BSS_FIRST_SECTIONS                                      \
+               . = ALIGN(PAGE_SIZE);                                   \
                *(.bss..page_aligned)                                   \
+               . = ALIGN(PAGE_SIZE);                                   \
                *(.dynbss)                                              \
                *(BSS_MAIN)                                             \
                *(COMMON)                                               \
index 56527c8..088c1de 100644 (file)
@@ -29,8 +29,8 @@ struct alg_sock {
 
        struct sock *parent;
 
-       unsigned int refcnt;
-       unsigned int nokey_refcnt;
+       atomic_t refcnt;
+       atomic_t nokey_refcnt;
 
        const struct af_alg_type *type;
        void *private;
index 27bdd27..77941ef 100644 (file)
@@ -89,7 +89,7 @@ struct displayid_detailed_timings_1 {
 
 struct displayid_detailed_timing_block {
        struct displayid_block base;
-       struct displayid_detailed_timings_1 timings[0];
+       struct displayid_detailed_timings_1 timings[];
 };
 
 #define for_each_displayid_db(displayid, block, idx, length) \
index 6c3ef49..e73dea5 100644 (file)
@@ -865,6 +865,18 @@ struct drm_mode_config {
         */
        bool prefer_shadow_fbdev;
 
+       /**
+        * @fbdev_use_iomem:
+        *
+        * Set to true if framebuffer reside in iomem.
+        * When set to true memcpy_toio() is used when copying the framebuffer in
+        * drm_fb_helper.drm_fb_helper_dirty_blit_real().
+        *
+        * FIXME: This should be replaced with a per-mapping is_iomem
+        * flag (like ttm does), and then used everywhere in fbdev code.
+        */
+       bool fbdev_use_iomem;
+
        /**
         * @quirk_addfb_prefer_xbgr_30bpp:
         *
index 9e9ccb2..38afb34 100644 (file)
@@ -27,7 +27,7 @@ struct encrypted_key_payload {
        unsigned short payload_datalen;         /* payload data length */
        unsigned short encrypted_key_format;    /* encrypted key format */
        u8 *decrypted_data;     /* decrypted data */
-       u8 payload_data[0];     /* payload data + datablob + hmac */
+       u8 payload_data[];      /* payload data + datablob + hmac */
 };
 
 extern struct key_type key_type_encrypted;
index a183278..2b0b15a 100644 (file)
@@ -28,7 +28,7 @@ struct rxkad_key {
        u8      primary_flag;           /* T if key for primary cell for this user */
        u16     ticket_len;             /* length of ticket[] */
        u8      session_key[8];         /* DES session key */
-       u8      ticket[0];              /* the encrypted ticket */
+       u8      ticket[];               /* the encrypted ticket */
 };
 
 /*
@@ -100,7 +100,7 @@ struct rxrpc_key_data_v1 {
        u32             expiry;                 /* time_t */
        u32             kvno;
        u8              session_key[8];
-       u8              ticket[0];
+       u8              ticket[];
 };
 
 /*
index 2c4927b..fd525c7 100644 (file)
@@ -77,6 +77,9 @@
 
 #endif /* cmpxchg64_relaxed */
 
+#define arch_atomic_read atomic_read
+#define arch_atomic_read_acquire atomic_read_acquire
+
 #ifndef atomic_read_acquire
 static __always_inline int
 atomic_read_acquire(const atomic_t *v)
@@ -86,6 +89,9 @@ atomic_read_acquire(const atomic_t *v)
 #define atomic_read_acquire atomic_read_acquire
 #endif
 
+#define arch_atomic_set atomic_set
+#define arch_atomic_set_release atomic_set_release
+
 #ifndef atomic_set_release
 static __always_inline void
 atomic_set_release(atomic_t *v, int i)
@@ -95,6 +101,13 @@ atomic_set_release(atomic_t *v, int i)
 #define atomic_set_release atomic_set_release
 #endif
 
+#define arch_atomic_add atomic_add
+
+#define arch_atomic_add_return atomic_add_return
+#define arch_atomic_add_return_acquire atomic_add_return_acquire
+#define arch_atomic_add_return_release atomic_add_return_release
+#define arch_atomic_add_return_relaxed atomic_add_return_relaxed
+
 #ifndef atomic_add_return_relaxed
 #define atomic_add_return_acquire atomic_add_return
 #define atomic_add_return_release atomic_add_return
@@ -137,6 +150,11 @@ atomic_add_return(int i, atomic_t *v)
 
 #endif /* atomic_add_return_relaxed */
 
+#define arch_atomic_fetch_add atomic_fetch_add
+#define arch_atomic_fetch_add_acquire atomic_fetch_add_acquire
+#define arch_atomic_fetch_add_release atomic_fetch_add_release
+#define arch_atomic_fetch_add_relaxed atomic_fetch_add_relaxed
+
 #ifndef atomic_fetch_add_relaxed
 #define atomic_fetch_add_acquire atomic_fetch_add
 #define atomic_fetch_add_release atomic_fetch_add
@@ -179,6 +197,13 @@ atomic_fetch_add(int i, atomic_t *v)
 
 #endif /* atomic_fetch_add_relaxed */
 
+#define arch_atomic_sub atomic_sub
+
+#define arch_atomic_sub_return atomic_sub_return
+#define arch_atomic_sub_return_acquire atomic_sub_return_acquire
+#define arch_atomic_sub_return_release atomic_sub_return_release
+#define arch_atomic_sub_return_relaxed atomic_sub_return_relaxed
+
 #ifndef atomic_sub_return_relaxed
 #define atomic_sub_return_acquire atomic_sub_return
 #define atomic_sub_return_release atomic_sub_return
@@ -221,6 +246,11 @@ atomic_sub_return(int i, atomic_t *v)
 
 #endif /* atomic_sub_return_relaxed */
 
+#define arch_atomic_fetch_sub atomic_fetch_sub
+#define arch_atomic_fetch_sub_acquire atomic_fetch_sub_acquire
+#define arch_atomic_fetch_sub_release atomic_fetch_sub_release
+#define arch_atomic_fetch_sub_relaxed atomic_fetch_sub_relaxed
+
 #ifndef atomic_fetch_sub_relaxed
 #define atomic_fetch_sub_acquire atomic_fetch_sub
 #define atomic_fetch_sub_release atomic_fetch_sub
@@ -263,6 +293,8 @@ atomic_fetch_sub(int i, atomic_t *v)
 
 #endif /* atomic_fetch_sub_relaxed */
 
+#define arch_atomic_inc atomic_inc
+
 #ifndef atomic_inc
 static __always_inline void
 atomic_inc(atomic_t *v)
@@ -272,6 +304,11 @@ atomic_inc(atomic_t *v)
 #define atomic_inc atomic_inc
 #endif
 
+#define arch_atomic_inc_return atomic_inc_return
+#define arch_atomic_inc_return_acquire atomic_inc_return_acquire
+#define arch_atomic_inc_return_release atomic_inc_return_release
+#define arch_atomic_inc_return_relaxed atomic_inc_return_relaxed
+
 #ifndef atomic_inc_return_relaxed
 #ifdef atomic_inc_return
 #define atomic_inc_return_acquire atomic_inc_return
@@ -353,6 +390,11 @@ atomic_inc_return(atomic_t *v)
 
 #endif /* atomic_inc_return_relaxed */
 
+#define arch_atomic_fetch_inc atomic_fetch_inc
+#define arch_atomic_fetch_inc_acquire atomic_fetch_inc_acquire
+#define arch_atomic_fetch_inc_release atomic_fetch_inc_release
+#define arch_atomic_fetch_inc_relaxed atomic_fetch_inc_relaxed
+
 #ifndef atomic_fetch_inc_relaxed
 #ifdef atomic_fetch_inc
 #define atomic_fetch_inc_acquire atomic_fetch_inc
@@ -434,6 +476,8 @@ atomic_fetch_inc(atomic_t *v)
 
 #endif /* atomic_fetch_inc_relaxed */
 
+#define arch_atomic_dec atomic_dec
+
 #ifndef atomic_dec
 static __always_inline void
 atomic_dec(atomic_t *v)
@@ -443,6 +487,11 @@ atomic_dec(atomic_t *v)
 #define atomic_dec atomic_dec
 #endif
 
+#define arch_atomic_dec_return atomic_dec_return
+#define arch_atomic_dec_return_acquire atomic_dec_return_acquire
+#define arch_atomic_dec_return_release atomic_dec_return_release
+#define arch_atomic_dec_return_relaxed atomic_dec_return_relaxed
+
 #ifndef atomic_dec_return_relaxed
 #ifdef atomic_dec_return
 #define atomic_dec_return_acquire atomic_dec_return
@@ -524,6 +573,11 @@ atomic_dec_return(atomic_t *v)
 
 #endif /* atomic_dec_return_relaxed */
 
+#define arch_atomic_fetch_dec atomic_fetch_dec
+#define arch_atomic_fetch_dec_acquire atomic_fetch_dec_acquire
+#define arch_atomic_fetch_dec_release atomic_fetch_dec_release
+#define arch_atomic_fetch_dec_relaxed atomic_fetch_dec_relaxed
+
 #ifndef atomic_fetch_dec_relaxed
 #ifdef atomic_fetch_dec
 #define atomic_fetch_dec_acquire atomic_fetch_dec
@@ -605,6 +659,13 @@ atomic_fetch_dec(atomic_t *v)
 
 #endif /* atomic_fetch_dec_relaxed */
 
+#define arch_atomic_and atomic_and
+
+#define arch_atomic_fetch_and atomic_fetch_and
+#define arch_atomic_fetch_and_acquire atomic_fetch_and_acquire
+#define arch_atomic_fetch_and_release atomic_fetch_and_release
+#define arch_atomic_fetch_and_relaxed atomic_fetch_and_relaxed
+
 #ifndef atomic_fetch_and_relaxed
 #define atomic_fetch_and_acquire atomic_fetch_and
 #define atomic_fetch_and_release atomic_fetch_and
@@ -647,6 +708,8 @@ atomic_fetch_and(int i, atomic_t *v)
 
 #endif /* atomic_fetch_and_relaxed */
 
+#define arch_atomic_andnot atomic_andnot
+
 #ifndef atomic_andnot
 static __always_inline void
 atomic_andnot(int i, atomic_t *v)
@@ -656,6 +719,11 @@ atomic_andnot(int i, atomic_t *v)
 #define atomic_andnot atomic_andnot
 #endif
 
+#define arch_atomic_fetch_andnot atomic_fetch_andnot
+#define arch_atomic_fetch_andnot_acquire atomic_fetch_andnot_acquire
+#define arch_atomic_fetch_andnot_release atomic_fetch_andnot_release
+#define arch_atomic_fetch_andnot_relaxed atomic_fetch_andnot_relaxed
+
 #ifndef atomic_fetch_andnot_relaxed
 #ifdef atomic_fetch_andnot
 #define atomic_fetch_andnot_acquire atomic_fetch_andnot
@@ -737,6 +805,13 @@ atomic_fetch_andnot(int i, atomic_t *v)
 
 #endif /* atomic_fetch_andnot_relaxed */
 
+#define arch_atomic_or atomic_or
+
+#define arch_atomic_fetch_or atomic_fetch_or
+#define arch_atomic_fetch_or_acquire atomic_fetch_or_acquire
+#define arch_atomic_fetch_or_release atomic_fetch_or_release
+#define arch_atomic_fetch_or_relaxed atomic_fetch_or_relaxed
+
 #ifndef atomic_fetch_or_relaxed
 #define atomic_fetch_or_acquire atomic_fetch_or
 #define atomic_fetch_or_release atomic_fetch_or
@@ -779,6 +854,13 @@ atomic_fetch_or(int i, atomic_t *v)
 
 #endif /* atomic_fetch_or_relaxed */
 
+#define arch_atomic_xor atomic_xor
+
+#define arch_atomic_fetch_xor atomic_fetch_xor
+#define arch_atomic_fetch_xor_acquire atomic_fetch_xor_acquire
+#define arch_atomic_fetch_xor_release atomic_fetch_xor_release
+#define arch_atomic_fetch_xor_relaxed atomic_fetch_xor_relaxed
+
 #ifndef atomic_fetch_xor_relaxed
 #define atomic_fetch_xor_acquire atomic_fetch_xor
 #define atomic_fetch_xor_release atomic_fetch_xor
@@ -821,6 +903,11 @@ atomic_fetch_xor(int i, atomic_t *v)
 
 #endif /* atomic_fetch_xor_relaxed */
 
+#define arch_atomic_xchg atomic_xchg
+#define arch_atomic_xchg_acquire atomic_xchg_acquire
+#define arch_atomic_xchg_release atomic_xchg_release
+#define arch_atomic_xchg_relaxed atomic_xchg_relaxed
+
 #ifndef atomic_xchg_relaxed
 #define atomic_xchg_acquire atomic_xchg
 #define atomic_xchg_release atomic_xchg
@@ -863,6 +950,11 @@ atomic_xchg(atomic_t *v, int i)
 
 #endif /* atomic_xchg_relaxed */
 
+#define arch_atomic_cmpxchg atomic_cmpxchg
+#define arch_atomic_cmpxchg_acquire atomic_cmpxchg_acquire
+#define arch_atomic_cmpxchg_release atomic_cmpxchg_release
+#define arch_atomic_cmpxchg_relaxed atomic_cmpxchg_relaxed
+
 #ifndef atomic_cmpxchg_relaxed
 #define atomic_cmpxchg_acquire atomic_cmpxchg
 #define atomic_cmpxchg_release atomic_cmpxchg
@@ -905,6 +997,11 @@ atomic_cmpxchg(atomic_t *v, int old, int new)
 
 #endif /* atomic_cmpxchg_relaxed */
 
+#define arch_atomic_try_cmpxchg atomic_try_cmpxchg
+#define arch_atomic_try_cmpxchg_acquire atomic_try_cmpxchg_acquire
+#define arch_atomic_try_cmpxchg_release atomic_try_cmpxchg_release
+#define arch_atomic_try_cmpxchg_relaxed atomic_try_cmpxchg_relaxed
+
 #ifndef atomic_try_cmpxchg_relaxed
 #ifdef atomic_try_cmpxchg
 #define atomic_try_cmpxchg_acquire atomic_try_cmpxchg
@@ -1002,6 +1099,8 @@ atomic_try_cmpxchg(atomic_t *v, int *old, int new)
 
 #endif /* atomic_try_cmpxchg_relaxed */
 
+#define arch_atomic_sub_and_test atomic_sub_and_test
+
 #ifndef atomic_sub_and_test
 /**
  * atomic_sub_and_test - subtract value from variable and test result
@@ -1020,6 +1119,8 @@ atomic_sub_and_test(int i, atomic_t *v)
 #define atomic_sub_and_test atomic_sub_and_test
 #endif
 
+#define arch_atomic_dec_and_test atomic_dec_and_test
+
 #ifndef atomic_dec_and_test
 /**
  * atomic_dec_and_test - decrement and test
@@ -1037,6 +1138,8 @@ atomic_dec_and_test(atomic_t *v)
 #define atomic_dec_and_test atomic_dec_and_test
 #endif
 
+#define arch_atomic_inc_and_test atomic_inc_and_test
+
 #ifndef atomic_inc_and_test
 /**
  * atomic_inc_and_test - increment and test
@@ -1054,6 +1157,8 @@ atomic_inc_and_test(atomic_t *v)
 #define atomic_inc_and_test atomic_inc_and_test
 #endif
 
+#define arch_atomic_add_negative atomic_add_negative
+
 #ifndef atomic_add_negative
 /**
  * atomic_add_negative - add and test if negative
@@ -1072,6 +1177,8 @@ atomic_add_negative(int i, atomic_t *v)
 #define atomic_add_negative atomic_add_negative
 #endif
 
+#define arch_atomic_fetch_add_unless atomic_fetch_add_unless
+
 #ifndef atomic_fetch_add_unless
 /**
  * atomic_fetch_add_unless - add unless the number is already a given value
@@ -1097,6 +1204,8 @@ atomic_fetch_add_unless(atomic_t *v, int a, int u)
 #define atomic_fetch_add_unless atomic_fetch_add_unless
 #endif
 
+#define arch_atomic_add_unless atomic_add_unless
+
 #ifndef atomic_add_unless
 /**
  * atomic_add_unless - add unless the number is already a given value
@@ -1115,6 +1224,8 @@ atomic_add_unless(atomic_t *v, int a, int u)
 #define atomic_add_unless atomic_add_unless
 #endif
 
+#define arch_atomic_inc_not_zero atomic_inc_not_zero
+
 #ifndef atomic_inc_not_zero
 /**
  * atomic_inc_not_zero - increment unless the number is zero
@@ -1131,6 +1242,8 @@ atomic_inc_not_zero(atomic_t *v)
 #define atomic_inc_not_zero atomic_inc_not_zero
 #endif
 
+#define arch_atomic_inc_unless_negative atomic_inc_unless_negative
+
 #ifndef atomic_inc_unless_negative
 static __always_inline bool
 atomic_inc_unless_negative(atomic_t *v)
@@ -1147,6 +1260,8 @@ atomic_inc_unless_negative(atomic_t *v)
 #define atomic_inc_unless_negative atomic_inc_unless_negative
 #endif
 
+#define arch_atomic_dec_unless_positive atomic_dec_unless_positive
+
 #ifndef atomic_dec_unless_positive
 static __always_inline bool
 atomic_dec_unless_positive(atomic_t *v)
@@ -1163,6 +1278,8 @@ atomic_dec_unless_positive(atomic_t *v)
 #define atomic_dec_unless_positive atomic_dec_unless_positive
 #endif
 
+#define arch_atomic_dec_if_positive atomic_dec_if_positive
+
 #ifndef atomic_dec_if_positive
 static __always_inline int
 atomic_dec_if_positive(atomic_t *v)
@@ -1184,6 +1301,9 @@ atomic_dec_if_positive(atomic_t *v)
 #include <asm-generic/atomic64.h>
 #endif
 
+#define arch_atomic64_read atomic64_read
+#define arch_atomic64_read_acquire atomic64_read_acquire
+
 #ifndef atomic64_read_acquire
 static __always_inline s64
 atomic64_read_acquire(const atomic64_t *v)
@@ -1193,6 +1313,9 @@ atomic64_read_acquire(const atomic64_t *v)
 #define atomic64_read_acquire atomic64_read_acquire
 #endif
 
+#define arch_atomic64_set atomic64_set
+#define arch_atomic64_set_release atomic64_set_release
+
 #ifndef atomic64_set_release
 static __always_inline void
 atomic64_set_release(atomic64_t *v, s64 i)
@@ -1202,6 +1325,13 @@ atomic64_set_release(atomic64_t *v, s64 i)
 #define atomic64_set_release atomic64_set_release
 #endif
 
+#define arch_atomic64_add atomic64_add
+
+#define arch_atomic64_add_return atomic64_add_return
+#define arch_atomic64_add_return_acquire atomic64_add_return_acquire
+#define arch_atomic64_add_return_release atomic64_add_return_release
+#define arch_atomic64_add_return_relaxed atomic64_add_return_relaxed
+
 #ifndef atomic64_add_return_relaxed
 #define atomic64_add_return_acquire atomic64_add_return
 #define atomic64_add_return_release atomic64_add_return
@@ -1244,6 +1374,11 @@ atomic64_add_return(s64 i, atomic64_t *v)
 
 #endif /* atomic64_add_return_relaxed */
 
+#define arch_atomic64_fetch_add atomic64_fetch_add
+#define arch_atomic64_fetch_add_acquire atomic64_fetch_add_acquire
+#define arch_atomic64_fetch_add_release atomic64_fetch_add_release
+#define arch_atomic64_fetch_add_relaxed atomic64_fetch_add_relaxed
+
 #ifndef atomic64_fetch_add_relaxed
 #define atomic64_fetch_add_acquire atomic64_fetch_add
 #define atomic64_fetch_add_release atomic64_fetch_add
@@ -1286,6 +1421,13 @@ atomic64_fetch_add(s64 i, atomic64_t *v)
 
 #endif /* atomic64_fetch_add_relaxed */
 
+#define arch_atomic64_sub atomic64_sub
+
+#define arch_atomic64_sub_return atomic64_sub_return
+#define arch_atomic64_sub_return_acquire atomic64_sub_return_acquire
+#define arch_atomic64_sub_return_release atomic64_sub_return_release
+#define arch_atomic64_sub_return_relaxed atomic64_sub_return_relaxed
+
 #ifndef atomic64_sub_return_relaxed
 #define atomic64_sub_return_acquire atomic64_sub_return
 #define atomic64_sub_return_release atomic64_sub_return
@@ -1328,6 +1470,11 @@ atomic64_sub_return(s64 i, atomic64_t *v)
 
 #endif /* atomic64_sub_return_relaxed */
 
+#define arch_atomic64_fetch_sub atomic64_fetch_sub
+#define arch_atomic64_fetch_sub_acquire atomic64_fetch_sub_acquire
+#define arch_atomic64_fetch_sub_release atomic64_fetch_sub_release
+#define arch_atomic64_fetch_sub_relaxed atomic64_fetch_sub_relaxed
+
 #ifndef atomic64_fetch_sub_relaxed
 #define atomic64_fetch_sub_acquire atomic64_fetch_sub
 #define atomic64_fetch_sub_release atomic64_fetch_sub
@@ -1370,6 +1517,8 @@ atomic64_fetch_sub(s64 i, atomic64_t *v)
 
 #endif /* atomic64_fetch_sub_relaxed */
 
+#define arch_atomic64_inc atomic64_inc
+
 #ifndef atomic64_inc
 static __always_inline void
 atomic64_inc(atomic64_t *v)
@@ -1379,6 +1528,11 @@ atomic64_inc(atomic64_t *v)
 #define atomic64_inc atomic64_inc
 #endif
 
+#define arch_atomic64_inc_return atomic64_inc_return
+#define arch_atomic64_inc_return_acquire atomic64_inc_return_acquire
+#define arch_atomic64_inc_return_release atomic64_inc_return_release
+#define arch_atomic64_inc_return_relaxed atomic64_inc_return_relaxed
+
 #ifndef atomic64_inc_return_relaxed
 #ifdef atomic64_inc_return
 #define atomic64_inc_return_acquire atomic64_inc_return
@@ -1460,6 +1614,11 @@ atomic64_inc_return(atomic64_t *v)
 
 #endif /* atomic64_inc_return_relaxed */
 
+#define arch_atomic64_fetch_inc atomic64_fetch_inc
+#define arch_atomic64_fetch_inc_acquire atomic64_fetch_inc_acquire
+#define arch_atomic64_fetch_inc_release atomic64_fetch_inc_release
+#define arch_atomic64_fetch_inc_relaxed atomic64_fetch_inc_relaxed
+
 #ifndef atomic64_fetch_inc_relaxed
 #ifdef atomic64_fetch_inc
 #define atomic64_fetch_inc_acquire atomic64_fetch_inc
@@ -1541,6 +1700,8 @@ atomic64_fetch_inc(atomic64_t *v)
 
 #endif /* atomic64_fetch_inc_relaxed */
 
+#define arch_atomic64_dec atomic64_dec
+
 #ifndef atomic64_dec
 static __always_inline void
 atomic64_dec(atomic64_t *v)
@@ -1550,6 +1711,11 @@ atomic64_dec(atomic64_t *v)
 #define atomic64_dec atomic64_dec
 #endif
 
+#define arch_atomic64_dec_return atomic64_dec_return
+#define arch_atomic64_dec_return_acquire atomic64_dec_return_acquire
+#define arch_atomic64_dec_return_release atomic64_dec_return_release
+#define arch_atomic64_dec_return_relaxed atomic64_dec_return_relaxed
+
 #ifndef atomic64_dec_return_relaxed
 #ifdef atomic64_dec_return
 #define atomic64_dec_return_acquire atomic64_dec_return
@@ -1631,6 +1797,11 @@ atomic64_dec_return(atomic64_t *v)
 
 #endif /* atomic64_dec_return_relaxed */
 
+#define arch_atomic64_fetch_dec atomic64_fetch_dec
+#define arch_atomic64_fetch_dec_acquire atomic64_fetch_dec_acquire
+#define arch_atomic64_fetch_dec_release atomic64_fetch_dec_release
+#define arch_atomic64_fetch_dec_relaxed atomic64_fetch_dec_relaxed
+
 #ifndef atomic64_fetch_dec_relaxed
 #ifdef atomic64_fetch_dec
 #define atomic64_fetch_dec_acquire atomic64_fetch_dec
@@ -1712,6 +1883,13 @@ atomic64_fetch_dec(atomic64_t *v)
 
 #endif /* atomic64_fetch_dec_relaxed */
 
+#define arch_atomic64_and atomic64_and
+
+#define arch_atomic64_fetch_and atomic64_fetch_and
+#define arch_atomic64_fetch_and_acquire atomic64_fetch_and_acquire
+#define arch_atomic64_fetch_and_release atomic64_fetch_and_release
+#define arch_atomic64_fetch_and_relaxed atomic64_fetch_and_relaxed
+
 #ifndef atomic64_fetch_and_relaxed
 #define atomic64_fetch_and_acquire atomic64_fetch_and
 #define atomic64_fetch_and_release atomic64_fetch_and
@@ -1754,6 +1932,8 @@ atomic64_fetch_and(s64 i, atomic64_t *v)
 
 #endif /* atomic64_fetch_and_relaxed */
 
+#define arch_atomic64_andnot atomic64_andnot
+
 #ifndef atomic64_andnot
 static __always_inline void
 atomic64_andnot(s64 i, atomic64_t *v)
@@ -1763,6 +1943,11 @@ atomic64_andnot(s64 i, atomic64_t *v)
 #define atomic64_andnot atomic64_andnot
 #endif
 
+#define arch_atomic64_fetch_andnot atomic64_fetch_andnot
+#define arch_atomic64_fetch_andnot_acquire atomic64_fetch_andnot_acquire
+#define arch_atomic64_fetch_andnot_release atomic64_fetch_andnot_release
+#define arch_atomic64_fetch_andnot_relaxed atomic64_fetch_andnot_relaxed
+
 #ifndef atomic64_fetch_andnot_relaxed
 #ifdef atomic64_fetch_andnot
 #define atomic64_fetch_andnot_acquire atomic64_fetch_andnot
@@ -1844,6 +2029,13 @@ atomic64_fetch_andnot(s64 i, atomic64_t *v)
 
 #endif /* atomic64_fetch_andnot_relaxed */
 
+#define arch_atomic64_or atomic64_or
+
+#define arch_atomic64_fetch_or atomic64_fetch_or
+#define arch_atomic64_fetch_or_acquire atomic64_fetch_or_acquire
+#define arch_atomic64_fetch_or_release atomic64_fetch_or_release
+#define arch_atomic64_fetch_or_relaxed atomic64_fetch_or_relaxed
+
 #ifndef atomic64_fetch_or_relaxed
 #define atomic64_fetch_or_acquire atomic64_fetch_or
 #define atomic64_fetch_or_release atomic64_fetch_or
@@ -1886,6 +2078,13 @@ atomic64_fetch_or(s64 i, atomic64_t *v)
 
 #endif /* atomic64_fetch_or_relaxed */
 
+#define arch_atomic64_xor atomic64_xor
+
+#define arch_atomic64_fetch_xor atomic64_fetch_xor
+#define arch_atomic64_fetch_xor_acquire atomic64_fetch_xor_acquire
+#define arch_atomic64_fetch_xor_release atomic64_fetch_xor_release
+#define arch_atomic64_fetch_xor_relaxed atomic64_fetch_xor_relaxed
+
 #ifndef atomic64_fetch_xor_relaxed
 #define atomic64_fetch_xor_acquire atomic64_fetch_xor
 #define atomic64_fetch_xor_release atomic64_fetch_xor
@@ -1928,6 +2127,11 @@ atomic64_fetch_xor(s64 i, atomic64_t *v)
 
 #endif /* atomic64_fetch_xor_relaxed */
 
+#define arch_atomic64_xchg atomic64_xchg
+#define arch_atomic64_xchg_acquire atomic64_xchg_acquire
+#define arch_atomic64_xchg_release atomic64_xchg_release
+#define arch_atomic64_xchg_relaxed atomic64_xchg_relaxed
+
 #ifndef atomic64_xchg_relaxed
 #define atomic64_xchg_acquire atomic64_xchg
 #define atomic64_xchg_release atomic64_xchg
@@ -1970,6 +2174,11 @@ atomic64_xchg(atomic64_t *v, s64 i)
 
 #endif /* atomic64_xchg_relaxed */
 
+#define arch_atomic64_cmpxchg atomic64_cmpxchg
+#define arch_atomic64_cmpxchg_acquire atomic64_cmpxchg_acquire
+#define arch_atomic64_cmpxchg_release atomic64_cmpxchg_release
+#define arch_atomic64_cmpxchg_relaxed atomic64_cmpxchg_relaxed
+
 #ifndef atomic64_cmpxchg_relaxed
 #define atomic64_cmpxchg_acquire atomic64_cmpxchg
 #define atomic64_cmpxchg_release atomic64_cmpxchg
@@ -2012,6 +2221,11 @@ atomic64_cmpxchg(atomic64_t *v, s64 old, s64 new)
 
 #endif /* atomic64_cmpxchg_relaxed */
 
+#define arch_atomic64_try_cmpxchg atomic64_try_cmpxchg
+#define arch_atomic64_try_cmpxchg_acquire atomic64_try_cmpxchg_acquire
+#define arch_atomic64_try_cmpxchg_release atomic64_try_cmpxchg_release
+#define arch_atomic64_try_cmpxchg_relaxed atomic64_try_cmpxchg_relaxed
+
 #ifndef atomic64_try_cmpxchg_relaxed
 #ifdef atomic64_try_cmpxchg
 #define atomic64_try_cmpxchg_acquire atomic64_try_cmpxchg
@@ -2109,6 +2323,8 @@ atomic64_try_cmpxchg(atomic64_t *v, s64 *old, s64 new)
 
 #endif /* atomic64_try_cmpxchg_relaxed */
 
+#define arch_atomic64_sub_and_test atomic64_sub_and_test
+
 #ifndef atomic64_sub_and_test
 /**
  * atomic64_sub_and_test - subtract value from variable and test result
@@ -2127,6 +2343,8 @@ atomic64_sub_and_test(s64 i, atomic64_t *v)
 #define atomic64_sub_and_test atomic64_sub_and_test
 #endif
 
+#define arch_atomic64_dec_and_test atomic64_dec_and_test
+
 #ifndef atomic64_dec_and_test
 /**
  * atomic64_dec_and_test - decrement and test
@@ -2144,6 +2362,8 @@ atomic64_dec_and_test(atomic64_t *v)
 #define atomic64_dec_and_test atomic64_dec_and_test
 #endif
 
+#define arch_atomic64_inc_and_test atomic64_inc_and_test
+
 #ifndef atomic64_inc_and_test
 /**
  * atomic64_inc_and_test - increment and test
@@ -2161,6 +2381,8 @@ atomic64_inc_and_test(atomic64_t *v)
 #define atomic64_inc_and_test atomic64_inc_and_test
 #endif
 
+#define arch_atomic64_add_negative atomic64_add_negative
+
 #ifndef atomic64_add_negative
 /**
  * atomic64_add_negative - add and test if negative
@@ -2179,6 +2401,8 @@ atomic64_add_negative(s64 i, atomic64_t *v)
 #define atomic64_add_negative atomic64_add_negative
 #endif
 
+#define arch_atomic64_fetch_add_unless atomic64_fetch_add_unless
+
 #ifndef atomic64_fetch_add_unless
 /**
  * atomic64_fetch_add_unless - add unless the number is already a given value
@@ -2204,6 +2428,8 @@ atomic64_fetch_add_unless(atomic64_t *v, s64 a, s64 u)
 #define atomic64_fetch_add_unless atomic64_fetch_add_unless
 #endif
 
+#define arch_atomic64_add_unless atomic64_add_unless
+
 #ifndef atomic64_add_unless
 /**
  * atomic64_add_unless - add unless the number is already a given value
@@ -2222,6 +2448,8 @@ atomic64_add_unless(atomic64_t *v, s64 a, s64 u)
 #define atomic64_add_unless atomic64_add_unless
 #endif
 
+#define arch_atomic64_inc_not_zero atomic64_inc_not_zero
+
 #ifndef atomic64_inc_not_zero
 /**
  * atomic64_inc_not_zero - increment unless the number is zero
@@ -2238,6 +2466,8 @@ atomic64_inc_not_zero(atomic64_t *v)
 #define atomic64_inc_not_zero atomic64_inc_not_zero
 #endif
 
+#define arch_atomic64_inc_unless_negative atomic64_inc_unless_negative
+
 #ifndef atomic64_inc_unless_negative
 static __always_inline bool
 atomic64_inc_unless_negative(atomic64_t *v)
@@ -2254,6 +2484,8 @@ atomic64_inc_unless_negative(atomic64_t *v)
 #define atomic64_inc_unless_negative atomic64_inc_unless_negative
 #endif
 
+#define arch_atomic64_dec_unless_positive atomic64_dec_unless_positive
+
 #ifndef atomic64_dec_unless_positive
 static __always_inline bool
 atomic64_dec_unless_positive(atomic64_t *v)
@@ -2270,6 +2502,8 @@ atomic64_dec_unless_positive(atomic64_t *v)
 #define atomic64_dec_unless_positive atomic64_dec_unless_positive
 #endif
 
+#define arch_atomic64_dec_if_positive atomic64_dec_if_positive
+
 #ifndef atomic64_dec_if_positive
 static __always_inline s64
 atomic64_dec_if_positive(atomic64_t *v)
@@ -2288,4 +2522,4 @@ atomic64_dec_if_positive(atomic64_t *v)
 #endif
 
 #endif /* _LINUX_ATOMIC_FALLBACK_H */
-// 1fac0941c79bf0ae100723cc2ac9b94061f0b67a
+// 9d95b56f98d82a2a26c7b79ccdd0c47572d50a6f
index 4671fbf..7f475d5 100644 (file)
@@ -18,8 +18,7 @@
  * position @h. For example
  * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.
  */
-#if !defined(__ASSEMBLY__) && \
-       (!defined(CONFIG_CC_IS_GCC) || CONFIG_GCC_VERSION >= 49000)
+#if !defined(__ASSEMBLY__)
 #include <linux/build_bug.h>
 #define GENMASK_INPUT_CHECK(h, l) \
        (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
index 8fd9009..5724141 100644 (file)
@@ -590,6 +590,7 @@ struct request_queue {
        u64                     write_hints[BLK_MAX_WRITE_HINTS];
 };
 
+/* Keep blk_queue_flag_name[] in sync with the definitions below */
 #define QUEUE_FLAG_STOPPED     0       /* queue is stopped */
 #define QUEUE_FLAG_DYING       1       /* queue being torn down */
 #define QUEUE_FLAG_NOMERGES     3      /* disable merge attempts */
index 4052d64..47d5b0c 100644 (file)
@@ -33,7 +33,7 @@ int netns_bpf_prog_query(const union bpf_attr *attr,
                         union bpf_attr __user *uattr);
 int netns_bpf_prog_attach(const union bpf_attr *attr,
                          struct bpf_prog *prog);
-int netns_bpf_prog_detach(const union bpf_attr *attr);
+int netns_bpf_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype);
 int netns_bpf_link_create(const union bpf_attr *attr,
                          struct bpf_prog *prog);
 #else
@@ -49,7 +49,8 @@ static inline int netns_bpf_prog_attach(const union bpf_attr *attr,
        return -EOPNOTSUPP;
 }
 
-static inline int netns_bpf_prog_detach(const union bpf_attr *attr)
+static inline int netns_bpf_prog_detach(const union bpf_attr *attr,
+                                       enum bpf_prog_type ptype)
 {
        return -EOPNOTSUPP;
 }
index 07052d4..9750a19 100644 (file)
@@ -1543,13 +1543,16 @@ static inline void bpf_map_offload_map_free(struct bpf_map *map)
 #endif /* CONFIG_NET && CONFIG_BPF_SYSCALL */
 
 #if defined(CONFIG_BPF_STREAM_PARSER)
-int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog, u32 which);
+int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog,
+                        struct bpf_prog *old, u32 which);
 int sock_map_get_from_fd(const union bpf_attr *attr, struct bpf_prog *prog);
+int sock_map_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype);
 void sock_map_unhash(struct sock *sk);
 void sock_map_close(struct sock *sk, long timeout);
 #else
 static inline int sock_map_prog_update(struct bpf_map *map,
-                                      struct bpf_prog *prog, u32 which)
+                                      struct bpf_prog *prog,
+                                      struct bpf_prog *old, u32 which)
 {
        return -EOPNOTSUPP;
 }
@@ -1559,6 +1562,12 @@ static inline int sock_map_get_from_fd(const union bpf_attr *attr,
 {
        return -EINVAL;
 }
+
+static inline int sock_map_prog_detach(const union bpf_attr *attr,
+                                      enum bpf_prog_type ptype)
+{
+       return -EOPNOTSUPP;
+}
 #endif /* CONFIG_BPF_STREAM_PARSER */
 
 #if defined(CONFIG_INET) && defined(CONFIG_BPF_SYSCALL)
index 5c1ea99..8b81fbb 100644 (file)
@@ -82,6 +82,11 @@ static inline bool btf_type_is_int(const struct btf_type *t)
        return BTF_INFO_KIND(t->info) == BTF_KIND_INT;
 }
 
+static inline bool btf_type_is_small_int(const struct btf_type *t)
+{
+       return btf_type_is_int(t) && t->size <= sizeof(u64);
+}
+
 static inline bool btf_type_is_enum(const struct btf_type *t)
 {
        return BTF_INFO_KIND(t->info) == BTF_KIND_ENUM;
index a954def..900b9f4 100644 (file)
@@ -34,7 +34,7 @@
 struct can_skb_priv {
        int ifindex;
        int skbcnt;
-       struct can_frame cf[0];
+       struct can_frame cf[];
 };
 
 static inline struct can_skb_priv *can_skb_prv(struct sk_buff *skb)
index 60de3fe..405657a 100644 (file)
@@ -36,7 +36,7 @@ struct cb710_chip {
        unsigned                slot_mask;
        unsigned                slots;
        spinlock_t              irq_lock;
-       struct cb710_slot       slot[0];
+       struct cb710_slot       slot[];
 };
 
 /* NOTE: cb710_chip.slots is modified only during device init/exit and
index 2247e71..e5ed1c5 100644 (file)
@@ -52,8 +52,7 @@ struct ceph_options {
        unsigned long osd_idle_ttl;             /* jiffies */
        unsigned long osd_keepalive_timeout;    /* jiffies */
        unsigned long osd_request_timeout;      /* jiffies */
-
-       u32 osd_req_flags;  /* CEPH_OSD_FLAG_*, applied to each OSD request */
+       u32 read_from_replica;  /* CEPH_OSD_FLAG_BALANCE/LOCALIZE_READS */
 
        /*
         * any type that can't be simply compared or doesn't need
@@ -76,6 +75,7 @@ struct ceph_options {
 #define CEPH_OSD_KEEPALIVE_DEFAULT     msecs_to_jiffies(5 * 1000)
 #define CEPH_OSD_IDLE_TTL_DEFAULT      msecs_to_jiffies(60 * 1000)
 #define CEPH_OSD_REQUEST_TIMEOUT_DEFAULT 0  /* no timeout */
+#define CEPH_READ_FROM_REPLICA_DEFAULT 0  /* read from primary */
 
 #define CEPH_MONC_HUNT_INTERVAL                msecs_to_jiffies(3 * 1000)
 #define CEPH_MONC_PING_INTERVAL                msecs_to_jiffies(10 * 1000)
index 5266115..fee0b55 100644 (file)
@@ -790,7 +790,9 @@ struct sock_cgroup_data {
        union {
 #ifdef __LITTLE_ENDIAN
                struct {
-                       u8      is_data;
+                       u8      is_data : 1;
+                       u8      no_refcnt : 1;
+                       u8      unused : 6;
                        u8      padding;
                        u16     prioidx;
                        u32     classid;
@@ -800,7 +802,9 @@ struct sock_cgroup_data {
                        u32     classid;
                        u16     prioidx;
                        u8      padding;
-                       u8      is_data;
+                       u8      unused : 6;
+                       u8      no_refcnt : 1;
+                       u8      is_data : 1;
                } __packed;
 #endif
                u64             val;
index 4598e4d..618838c 100644 (file)
@@ -822,6 +822,7 @@ extern spinlock_t cgroup_sk_update_lock;
 
 void cgroup_sk_alloc_disable(void);
 void cgroup_sk_alloc(struct sock_cgroup_data *skcd);
+void cgroup_sk_clone(struct sock_cgroup_data *skcd);
 void cgroup_sk_free(struct sock_cgroup_data *skcd);
 
 static inline struct cgroup *sock_cgroup_ptr(struct sock_cgroup_data *skcd)
@@ -835,7 +836,7 @@ static inline struct cgroup *sock_cgroup_ptr(struct sock_cgroup_data *skcd)
         */
        v = READ_ONCE(skcd->val);
 
-       if (v & 1)
+       if (v & 3)
                return &cgrp_dfl_root.cgrp;
 
        return (struct cgroup *)(unsigned long)v ?: &cgrp_dfl_root.cgrp;
@@ -847,6 +848,7 @@ static inline struct cgroup *sock_cgroup_ptr(struct sock_cgroup_data *skcd)
 #else  /* CONFIG_CGROUP_DATA */
 
 static inline void cgroup_sk_alloc(struct sock_cgroup_data *skcd) {}
+static inline void cgroup_sk_clone(struct sock_cgroup_data *skcd) {}
 static inline void cgroup_sk_free(struct sock_cgroup_data *skcd) {}
 
 #endif /* CONFIG_CGROUP_DATA */
index ee37256..5e55302 100644 (file)
 #define __no_sanitize_thread
 #endif
 
+#if __has_feature(undefined_behavior_sanitizer)
+/* GCC does not have __SANITIZE_UNDEFINED__ */
+#define __no_sanitize_undefined \
+               __attribute__((no_sanitize("undefined")))
+#else
+#define __no_sanitize_undefined
+#endif
+
 /*
  * Not all versions of clang implement the the type-generic versions
  * of the builtin overflow checkers. Fortunately, clang implements
index 7dd4e03..0b1dc61 100644 (file)
@@ -11,7 +11,7 @@
                     + __GNUC_PATCHLEVEL__)
 
 /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145 */
-#if GCC_VERSION < 40800
+#if GCC_VERSION < 40900
 # error Sorry, your compiler is too old - please upgrade it.
 #endif
 
 #define __no_sanitize_thread
 #endif
 
+#if __has_attribute(__no_sanitize_undefined__)
+#define __no_sanitize_undefined __attribute__((no_sanitize_undefined))
+#else
+#define __no_sanitize_undefined
+#endif
+
 #if GCC_VERSION >= 50100
 #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
 #endif
index 30827f8..204e768 100644 (file)
@@ -123,7 +123,7 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
 #ifdef CONFIG_DEBUG_ENTRY
 /* Begin/end of an instrumentation safe region */
 #define instrumentation_begin() ({                                     \
-       asm volatile("%c0:\n\t"                                         \
+       asm volatile("%c0: nop\n\t"                                             \
                     ".pushsection .discard.instr_begin\n\t"            \
                     ".long %c0b - .\n\t"                               \
                     ".popsection\n\t" : : "i" (__COUNTER__));          \
index cdf0165..c8f03d2 100644 (file)
@@ -40,6 +40,7 @@
 # define __GCC4_has_attribute___noclone__             1
 # define __GCC4_has_attribute___nonstring__           0
 # define __GCC4_has_attribute___no_sanitize_address__ (__GNUC_MINOR__ >= 8)
+# define __GCC4_has_attribute___no_sanitize_undefined__ (__GNUC_MINOR__ >= 9)
 # define __GCC4_has_attribute___fallthrough__         0
 #endif
 
index 21aed09..01dd58c 100644 (file)
@@ -5,20 +5,20 @@
 #ifndef __ASSEMBLY__
 
 #ifdef __CHECKER__
-# define __user                __attribute__((noderef, address_space(1)))
 # define __kernel      __attribute__((address_space(0)))
+# define __user                __attribute__((noderef, address_space(__user)))
 # define __safe                __attribute__((safe))
 # define __force       __attribute__((force))
 # define __nocast      __attribute__((nocast))
-# define __iomem       __attribute__((noderef, address_space(2)))
+# define __iomem       __attribute__((noderef, address_space(__iomem)))
 # define __must_hold(x)        __attribute__((context(x,1,1)))
 # define __acquires(x) __attribute__((context(x,0,1)))
 # define __releases(x) __attribute__((context(x,1,0)))
 # define __acquire(x)  __context__(x,1)
 # define __release(x)  __context__(x,-1)
 # define __cond_lock(x,c)      ((c) ? ({ __acquire(x); 1; }) : 0)
-# define __percpu      __attribute__((noderef, address_space(3)))
-# define __rcu         __attribute__((noderef, address_space(4)))
+# define __percpu      __attribute__((noderef, address_space(__percpu)))
+# define __rcu         __attribute__((noderef, address_space(__rcu)))
 # define __private     __attribute__((noderef))
 extern void __chk_user_ptr(const volatile void __user *);
 extern void __chk_io_ptr(const volatile void __iomem *);
@@ -118,10 +118,6 @@ struct ftrace_likely_data {
 #define notrace                        __attribute__((__no_instrument_function__))
 #endif
 
-/* Section for code which can't be instrumented at all */
-#define noinstr                                                                \
-       noinline notrace __attribute((__section__(".noinstr.text")))
-
 /*
  * it doesn't make sense on ARM (currently the only user of __naked)
  * to trace naked functions because then mcount is called without
@@ -193,16 +189,18 @@ struct ftrace_likely_data {
 
 #define __no_kcsan __no_sanitize_thread
 #ifdef __SANITIZE_THREAD__
-# define __no_kcsan_or_inline __no_kcsan notrace __maybe_unused
-# define __no_sanitize_or_inline __no_kcsan_or_inline
-#else
-# define __no_kcsan_or_inline __always_inline
+# define __no_sanitize_or_inline __no_kcsan notrace __maybe_unused
 #endif
 
 #ifndef __no_sanitize_or_inline
 #define __no_sanitize_or_inline __always_inline
 #endif
 
+/* Section for code which can't be instrumented at all */
+#define noinstr                                                                \
+       noinline notrace __attribute((__section__(".noinstr.text")))    \
+       __no_kcsan __no_sanitize_address
+
 #endif /* __KERNEL__ */
 
 #endif /* __ASSEMBLY__ */
@@ -254,32 +252,8 @@ struct ftrace_likely_data {
  * __unqual_scalar_typeof(x) - Declare an unqualified scalar type, leaving
  *                            non-scalar types unchanged.
  */
-#if (defined(CONFIG_CC_IS_GCC) && CONFIG_GCC_VERSION < 40900) || defined(__CHECKER__)
 /*
- * We build this out of a couple of helper macros in a vain attempt to
- * help you keep your lunch down while reading it.
- */
-#define __pick_scalar_type(x, type, otherwise)                                 \
-       __builtin_choose_expr(__same_type(x, type), (type)0, otherwise)
-
-/*
- * 'char' is not type-compatible with either 'signed char' or 'unsigned char',
- * so we include the naked type here as well as the signed/unsigned variants.
- */
-#define __pick_integer_type(x, type, otherwise)                                        \
-       __pick_scalar_type(x, type,                                             \
-               __pick_scalar_type(x, unsigned type,                            \
-                       __pick_scalar_type(x, signed type, otherwise)))
-
-#define __unqual_scalar_typeof(x) typeof(                                      \
-       __pick_integer_type(x, char,                                            \
-               __pick_integer_type(x, short,                                   \
-                       __pick_integer_type(x, int,                             \
-                               __pick_integer_type(x, long,                    \
-                                       __pick_integer_type(x, long long, x))))))
-#else
-/*
- * If supported, prefer C11 _Generic for better compile-times. As above, 'char'
+ * Prefer C11 _Generic for better compile-times and simpler code. Note: 'char'
  * is not type-compatible with 'signed char', and we define a separate case.
  */
 #define __scalar_type_to_expr_cases(type)                              \
@@ -295,7 +269,6 @@ struct ftrace_likely_data {
                         __scalar_type_to_expr_cases(long),             \
                         __scalar_type_to_expr_cases(long long),        \
                         default: (x)))
-#endif
 
 /* Is this type a native word size -- useful for atomic operations */
 #define __native_word(t) \
index 8750f2d..73dec4b 100644 (file)
@@ -426,6 +426,7 @@ const char *dm_device_name(struct mapped_device *md);
 int dm_copy_name_and_uuid(struct mapped_device *md, char *name, char *uuid);
 struct gendisk *dm_disk(struct mapped_device *md);
 int dm_suspended(struct dm_target *ti);
+int dm_post_suspending(struct dm_target *ti);
 int dm_noflush_suspending(struct dm_target *ti);
 void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors);
 union map_info *dm_get_rq_mapinfo(struct request *rq);
index 15460a5..5efed86 100644 (file)
@@ -433,7 +433,8 @@ enum dl_dev_state {
  * @suppliers: List of links to supplier devices.
  * @consumers: List of links to consumer devices.
  * @needs_suppliers: Hook to global list of devices waiting for suppliers.
- * @defer_sync: Hook to global list of devices that have deferred sync_state.
+ * @defer_hook: Hook to global list of devices that have deferred sync_state or
+ *             deferred fw_devlink.
  * @need_for_probe: If needs_suppliers is on a list, this indicates if the
  *                 suppliers are needed for probe or not.
  * @status: Driver status information.
@@ -442,7 +443,7 @@ struct dev_links_info {
        struct list_head suppliers;
        struct list_head consumers;
        struct list_head needs_suppliers;
-       struct list_head defer_sync;
+       struct list_head defer_hook;
        bool need_for_probe;
        enum dl_dev_state status;
 };
index ab0c156..a2ca294 100644 (file)
@@ -311,6 +311,7 @@ struct dma_buf {
        void *vmap_ptr;
        const char *exp_name;
        const char *name;
+       spinlock_t name_lock; /* spinlock to protect name access */
        struct module *owner;
        struct list_head list_node;
        void *priv;
index 136f984..ab2e20c 100644 (file)
@@ -69,6 +69,7 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size,
 u64 dma_direct_get_required_mask(struct device *dev);
 gfp_t dma_direct_optimal_gfp_mask(struct device *dev, u64 dma_mask,
                                  u64 *phys_mask);
+bool dma_coherent_ok(struct device *dev, phys_addr_t phys, size_t size);
 void *dma_direct_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
                gfp_t gfp, unsigned long attrs);
 void dma_direct_free(struct device *dev, size_t size, void *cpu_addr,
@@ -77,8 +78,6 @@ void *dma_direct_alloc_pages(struct device *dev, size_t size,
                dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs);
 void dma_direct_free_pages(struct device *dev, size_t size, void *cpu_addr,
                dma_addr_t dma_addr, unsigned long attrs);
-struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
-               gfp_t gfp, unsigned long attrs);
 int dma_direct_get_sgtable(struct device *dev, struct sg_table *sgt,
                void *cpu_addr, dma_addr_t dma_addr, size_t size,
                unsigned long attrs);
@@ -87,4 +86,5 @@ int dma_direct_mmap(struct device *dev, struct vm_area_struct *vma,
                void *cpu_addr, dma_addr_t dma_addr, size_t size,
                unsigned long attrs);
 int dma_direct_supported(struct device *dev, u64 mask);
+bool dma_direct_need_sync(struct device *dev, dma_addr_t dma_addr);
 #endif /* _LINUX_DMA_DIRECT_H */
index 78f677c..a33ed39 100644 (file)
@@ -461,6 +461,7 @@ int dma_set_mask(struct device *dev, u64 mask);
 int dma_set_coherent_mask(struct device *dev, u64 mask);
 u64 dma_get_required_mask(struct device *dev);
 size_t dma_max_mapping_size(struct device *dev);
+bool dma_need_sync(struct device *dev, dma_addr_t dma_addr);
 unsigned long dma_get_merge_boundary(struct device *dev);
 #else /* CONFIG_HAS_DMA */
 static inline dma_addr_t dma_map_page_attrs(struct device *dev,
@@ -571,6 +572,10 @@ static inline size_t dma_max_mapping_size(struct device *dev)
 {
        return 0;
 }
+static inline bool dma_need_sync(struct device *dev, dma_addr_t dma_addr)
+{
+       return false;
+}
 static inline unsigned long dma_get_merge_boundary(struct device *dev)
 {
        return 0;
index e1c0333..6283917 100644 (file)
@@ -153,7 +153,7 @@ struct dma_interleaved_template {
        bool dst_sgl;
        size_t numf;
        size_t frame_size;
-       struct data_chunk sgl[0];
+       struct data_chunk sgl[];
 };
 
 /**
@@ -535,7 +535,7 @@ struct dmaengine_unmap_data {
        struct device *dev;
        struct kref kref;
        size_t len;
-       dma_addr_t addr[0];
+       dma_addr_t addr[];
 };
 
 struct dma_async_tx_descriptor;
index 2c6495f..05c47f8 100644 (file)
@@ -350,6 +350,7 @@ void efi_native_runtime_setup(void);
  * associated with ConOut
  */
 #define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID   EFI_GUID(0xe03fc20a, 0x85dc, 0x406e,  0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95)
+#define LINUX_EFI_ARM_CPU_STATE_TABLE_GUID     EFI_GUID(0xef79e4aa, 0x3c3d, 0x4989,  0xb9, 0x02, 0x07, 0xa9, 0x43, 0xe5, 0x50, 0xd2)
 #define LINUX_EFI_LOADER_ENTRY_GUID            EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf,  0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f)
 #define LINUX_EFI_RANDOM_SEED_TABLE_GUID       EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2,  0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b)
 #define LINUX_EFI_TPM_EVENT_LOG_GUID           EFI_GUID(0xb7799cb0, 0xeca2, 0x4943,  0x96, 0x67, 0x1f, 0xae, 0x07, 0xb7, 0x47, 0xfa)
@@ -993,6 +994,7 @@ int efivars_register(struct efivars *efivars,
 int efivars_unregister(struct efivars *efivars);
 struct kobject *efivars_kobject(void);
 
+int efivar_supports_writes(void);
 int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *),
                void *data, bool duplicates, struct list_head *head);
 
@@ -1236,14 +1238,11 @@ struct linux_efi_memreserve {
        struct {
                phys_addr_t     base;
                phys_addr_t     size;
-       } entry[0];
+       } entry[];
 };
 
-#define EFI_MEMRESERVE_SIZE(count) (sizeof(struct linux_efi_memreserve) + \
-       (count) * sizeof(((struct linux_efi_memreserve *)0)->entry[0]))
-
 #define EFI_MEMRESERVE_COUNT(size) (((size) - sizeof(struct linux_efi_memreserve)) \
-       / sizeof(((struct linux_efi_memreserve *)0)->entry[0]))
+       / sizeof_field(struct linux_efi_memreserve, entry[0]))
 
 void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size);
 
index 2593777..0b01447 100644 (file)
@@ -884,12 +884,12 @@ void bpf_jit_compile(struct bpf_prog *prog);
 bool bpf_jit_needs_zext(void);
 bool bpf_helper_changes_pkt_data(void *func);
 
-static inline bool bpf_dump_raw_ok(void)
+static inline bool bpf_dump_raw_ok(const struct cred *cred)
 {
        /* Reconstruction of call-sites is dependent on kallsyms,
         * thus make dump the same restriction.
         */
-       return kallsyms_show_value() == 1;
+       return kallsyms_show_value(cred);
 }
 
 struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
index 6c4ab4d..f5abba8 100644 (file)
@@ -315,6 +315,7 @@ enum rw_hint {
 #define IOCB_SYNC              (1 << 5)
 #define IOCB_WRITE             (1 << 6)
 #define IOCB_NOWAIT            (1 << 7)
+#define IOCB_NOIO              (1 << 9)
 
 struct kiocb {
        struct file             *ki_filp;
@@ -1917,7 +1918,6 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
                              struct iovec *fast_pointer,
                              struct iovec **ret_pointer);
 
-extern ssize_t __vfs_read(struct file *, char __user *, size_t, loff_t *);
 extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *);
 extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *);
 extern ssize_t vfs_readv(struct file *, const struct iovec __user *,
@@ -2592,7 +2592,6 @@ extern void bdput(struct block_device *);
 extern void invalidate_bdev(struct block_device *);
 extern void iterate_bdevs(void (*)(struct block_device *, void *), void *);
 extern int sync_blockdev(struct block_device *bdev);
-extern void kill_bdev(struct block_device *);
 extern struct super_block *freeze_bdev(struct block_device *);
 extern void emergency_thaw_all(void);
 extern void emergency_thaw_bdev(struct super_block *sb);
@@ -2608,7 +2607,6 @@ static inline bool sb_is_blkdev_sb(struct super_block *sb)
 #else
 static inline void bd_forget(struct inode *inode) {}
 static inline int sync_blockdev(struct block_device *bdev) { return 0; }
-static inline void kill_bdev(struct block_device *bdev) {}
 static inline void invalidate_bdev(struct block_device *bdev) {}
 
 static inline struct super_block *freeze_bdev(struct block_device *sb)
@@ -3035,6 +3033,7 @@ extern int kernel_read_file_from_path_initns(const char *, void **, loff_t *, lo
 extern int kernel_read_file_from_fd(int, void **, loff_t *, loff_t,
                                    enum kernel_read_file_id);
 extern ssize_t kernel_read(struct file *, void *, size_t, loff_t *);
+ssize_t __kernel_read(struct file *file, void *buf, size_t count, loff_t *pos);
 extern ssize_t kernel_write(struct file *, const void *, size_t, loff_t *);
 extern ssize_t __kernel_write(struct file *, const void *, size_t, loff_t *);
 extern struct file * open_exec(const char *);
index 5f24fcb..37e1e8f 100644 (file)
@@ -109,6 +109,7 @@ struct fs_context {
        enum fs_context_phase   phase:8;        /* The phase the context is in */
        bool                    need_free:1;    /* Need to call ops->free() */
        bool                    global:1;       /* Goes into &init_user_ns */
+       bool                    oldapi:1;       /* Coming from mount(2) */
 };
 
 struct fs_context_operations {
index ce0b5fb..3f0b19d 100644 (file)
@@ -46,7 +46,7 @@ struct fscache_cache_tag {
        unsigned long           flags;
 #define FSCACHE_TAG_RESERVED   0               /* T if tag is reserved for a cache */
        atomic_t                usage;
-       char                    name[0];        /* tag name */
+       char                    name[]; /* tag name */
 };
 
 /*
index c230b4e..a3a568b 100644 (file)
@@ -48,6 +48,9 @@ struct host1x_client_ops {
  * @channel: host1x channel associated with this client
  * @syncpts: array of syncpoints requested for this client
  * @num_syncpts: number of syncpoints requested for this client
+ * @parent: pointer to parent structure
+ * @usecount: reference count for this structure
+ * @lock: mutex for mutually exclusive concurrency
  */
 struct host1x_client {
        struct list_head list;
index c10617b..4e7714c 100644 (file)
@@ -56,7 +56,7 @@ struct property_entry;
  * on a bus (or read from them). Apart from two basic transfer functions to
  * transmit one message at a time, a more complex version can be used to
  * transmit an arbitrary number of messages without interruption.
- * @count must be be less than 64k since msg.len is u16.
+ * @count must be less than 64k since msg.len is u16.
  */
 int i2c_transfer_buffer_flags(const struct i2c_client *client,
                              char *buf, int count, u16 flags);
@@ -408,7 +408,7 @@ static inline bool i2c_detect_slave_mode(struct device *dev) { return false; }
  * that are present.  This information is used to grow the driver model tree.
  * For mainboards this is done statically using i2c_register_board_info();
  * bus numbers identify adapters that aren't yet available.  For add-on boards,
- * i2c_new_device() does this dynamically with the adapter already known.
+ * i2c_new_client_device() does this dynamically with the adapter already known.
  */
 struct i2c_board_info {
        char            type[I2C_NAME_SIZE];
@@ -439,13 +439,11 @@ struct i2c_board_info {
 
 
 #if IS_ENABLED(CONFIG_I2C)
-/* Add-on boards should register/unregister their devices; e.g. a board
+/*
+ * Add-on boards should register/unregister their devices; e.g. a board
  * with integrated I2C, a config eeprom, sensors, and a codec that's
  * used in conjunction with the primary hardware.
  */
-struct i2c_client *
-i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info);
-
 struct i2c_client *
 i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *info);
 
@@ -1003,7 +1001,7 @@ static inline u32 i2c_acpi_find_bus_speed(struct device *dev)
 static inline struct i2c_client *i2c_acpi_new_device(struct device *dev,
                                        int index, struct i2c_board_info *info)
 {
-       return NULL;
+       return ERR_PTR(-ENODEV);
 }
 static inline struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle)
 {
index fe15f83..9f73249 100644 (file)
@@ -3333,13 +3333,17 @@ struct ieee80211_multiple_bssid_configuration {
 #define WLAN_AKM_SUITE_TDLS                    SUITE(0x000FAC, 7)
 #define WLAN_AKM_SUITE_SAE                     SUITE(0x000FAC, 8)
 #define WLAN_AKM_SUITE_FT_OVER_SAE             SUITE(0x000FAC, 9)
+#define WLAN_AKM_SUITE_AP_PEER_KEY             SUITE(0x000FAC, 10)
 #define WLAN_AKM_SUITE_8021X_SUITE_B           SUITE(0x000FAC, 11)
 #define WLAN_AKM_SUITE_8021X_SUITE_B_192       SUITE(0x000FAC, 12)
+#define WLAN_AKM_SUITE_FT_8021X_SHA384         SUITE(0x000FAC, 13)
 #define WLAN_AKM_SUITE_FILS_SHA256             SUITE(0x000FAC, 14)
 #define WLAN_AKM_SUITE_FILS_SHA384             SUITE(0x000FAC, 15)
 #define WLAN_AKM_SUITE_FT_FILS_SHA256          SUITE(0x000FAC, 16)
 #define WLAN_AKM_SUITE_FT_FILS_SHA384          SUITE(0x000FAC, 17)
 #define WLAN_AKM_SUITE_OWE                     SUITE(0x000FAC, 18)
+#define WLAN_AKM_SUITE_FT_PSK_SHA384           SUITE(0x000FAC, 19)
+#define WLAN_AKM_SUITE_PSK_SHA384              SUITE(0x000FAC, 20)
 
 #define WLAN_MAX_KEY_LEN               32
 
index b05e855..41a5183 100644 (file)
@@ -25,6 +25,8 @@
 #define VLAN_ETH_DATA_LEN      1500    /* Max. octets in payload        */
 #define VLAN_ETH_FRAME_LEN     1518    /* Max. octets in frame sans FCS */
 
+#define VLAN_MAX_DEPTH 8               /* Max. number of nested VLAN tags parsed */
+
 /*
  *     struct vlan_hdr - vlan header
  *     @h_vlan_TCI: priority and VLAN ID
@@ -577,10 +579,10 @@ static inline int vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
  * Returns the EtherType of the packet, regardless of whether it is
  * vlan encapsulated (normal or hardware accelerated) or not.
  */
-static inline __be16 __vlan_get_protocol(struct sk_buff *skb, __be16 type,
+static inline __be16 __vlan_get_protocol(const struct sk_buff *skb, __be16 type,
                                         int *depth)
 {
-       unsigned int vlan_depth = skb->mac_len;
+       unsigned int vlan_depth = skb->mac_len, parse_depth = VLAN_MAX_DEPTH;
 
        /* if type is 802.1Q/AD then the header should already be
         * present at mac_len - VLAN_HLEN (if mac_len > 0), or at
@@ -595,13 +597,12 @@ static inline __be16 __vlan_get_protocol(struct sk_buff *skb, __be16 type,
                        vlan_depth = ETH_HLEN;
                }
                do {
-                       struct vlan_hdr *vh;
+                       struct vlan_hdr vhdr, *vh;
 
-                       if (unlikely(!pskb_may_pull(skb,
-                                                   vlan_depth + VLAN_HLEN)))
+                       vh = skb_header_pointer(skb, vlan_depth, sizeof(vhdr), &vhdr);
+                       if (unlikely(!vh || !--parse_depth))
                                return 0;
 
-                       vh = (struct vlan_hdr *)(skb->data + vlan_depth);
                        type = vh->h_vlan_encapsulated_proto;
                        vlan_depth += VLAN_HLEN;
                } while (eth_type_vlan(type));
@@ -620,11 +621,25 @@ static inline __be16 __vlan_get_protocol(struct sk_buff *skb, __be16 type,
  * Returns the EtherType of the packet, regardless of whether it is
  * vlan encapsulated (normal or hardware accelerated) or not.
  */
-static inline __be16 vlan_get_protocol(struct sk_buff *skb)
+static inline __be16 vlan_get_protocol(const struct sk_buff *skb)
 {
        return __vlan_get_protocol(skb, skb->protocol, NULL);
 }
 
+/* A getter for the SKB protocol field which will handle VLAN tags consistently
+ * whether VLAN acceleration is enabled or not.
+ */
+static inline __be16 skb_protocol(const struct sk_buff *skb, bool skip_vlan)
+{
+       if (!skip_vlan)
+               /* VLAN acceleration strips the VLAN header from the skb and
+                * moves it to skb->vlan_proto
+                */
+               return skb_vlan_tag_present(skb) ? skb->vlan_proto : skb->protocol;
+
+       return vlan_get_protocol(skb);
+}
+
 static inline void vlan_set_encap_proto(struct sk_buff *skb,
                                        struct vlan_hdr *vhdr)
 {
index 1ecb6b4..520858d 100644 (file)
@@ -67,8 +67,15 @@ static const struct acpi_device_id elan_acpi_id[] = {
        { "ELAN062B", 0 },
        { "ELAN062C", 0 },
        { "ELAN062D", 0 },
+       { "ELAN062E", 0 }, /* Lenovo V340 Whiskey Lake U */
+       { "ELAN062F", 0 }, /* Lenovo V340 Comet Lake U */
        { "ELAN0631", 0 },
        { "ELAN0632", 0 },
+       { "ELAN0633", 0 }, /* Lenovo S145 */
+       { "ELAN0634", 0 }, /* Lenovo V340 Ice lake */
+       { "ELAN0635", 0 }, /* Lenovo V1415-IIL */
+       { "ELAN0636", 0 }, /* Lenovo V1415-Dali */
+       { "ELAN0637", 0 }, /* Lenovo V1415-IGLR */
        { "ELAN1000", 0 },
        { }
 };
index 4100bd2..3e8fa1c 100644 (file)
@@ -41,6 +41,7 @@
 #define DMA_PTE_SNP            BIT_ULL(11)
 
 #define DMA_FL_PTE_PRESENT     BIT_ULL(0)
+#define DMA_FL_PTE_US          BIT_ULL(2)
 #define DMA_FL_PTE_XD          BIT_ULL(63)
 
 #define ADDR_WIDTH_5LEVEL      (57)
index 0beaa3e..c75e4d3 100644 (file)
@@ -107,9 +107,12 @@ io_mapping_init_wc(struct io_mapping *iomap,
                   resource_size_t base,
                   unsigned long size)
 {
+       iomap->iomem = ioremap_wc(base, size);
+       if (!iomap->iomem)
+               return NULL;
+
        iomap->base = base;
        iomap->size = size;
-       iomap->iomem = ioremap_wc(base, size);
 #if defined(pgprot_noncached_wc) /* archs can't agree on a name ... */
        iomap->prot = pgprot_noncached_wc(PAGE_KERNEL);
 #elif defined(pgprot_writecombine)
index 2735da5..3082378 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef _LINUX_IRQ_WORK_H
 #define _LINUX_IRQ_WORK_H
 
-#include <linux/llist.h>
+#include <linux/smp_types.h>
 
 /*
  * An entry can be in one of four states:
  * busy      NULL, 2 -> {free, claimed} : callback in progress, can be claimed
  */
 
-/* flags share CSD_FLAG_ space */
-
-#define IRQ_WORK_PENDING       BIT(0)
-#define IRQ_WORK_BUSY          BIT(1)
-
-/* Doesn't want IPI, wait for tick: */
-#define IRQ_WORK_LAZY          BIT(2)
-/* Run hard IRQ context, even on RT */
-#define IRQ_WORK_HARD_IRQ      BIT(3)
-
-#define IRQ_WORK_CLAIMED       (IRQ_WORK_PENDING | IRQ_WORK_BUSY)
-
-/*
- * structure shares layout with single_call_data_t.
- */
 struct irq_work {
-       struct llist_node llnode;
-       atomic_t flags;
+       union {
+               struct __call_single_node node;
+               struct {
+                       struct llist_node llnode;
+                       atomic_t flags;
+               };
+       };
        void (*func)(struct irq_work *);
 };
 
index f613d85..d56128d 100644 (file)
@@ -765,6 +765,11 @@ struct journal_s
         */
        int                     j_errno;
 
+       /**
+        * @j_abort_mutex: Lock the whole aborting procedure.
+        */
+       struct mutex            j_abort_mutex;
+
        /**
         * @j_sb_buffer: The first part of the superblock buffer.
         */
@@ -1247,7 +1252,6 @@ JBD2_FEATURE_INCOMPAT_FUNCS(csum3,                CSUM_V3)
 #define JBD2_ABORT_ON_SYNCDATA_ERR     0x040   /* Abort the journal on file
                                                 * data write error in ordered
                                                 * mode */
-#define JBD2_REC_ERR   0x080   /* The errno in the sb has been recorded */
 
 /*
  * Function declarations for the journaling transaction and buffer
index 98338dc..481273f 100644 (file)
@@ -18,6 +18,7 @@
 #define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \
                         2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1)
 
+struct cred;
 struct module;
 
 static inline int is_kernel_inittext(unsigned long addr)
@@ -98,7 +99,7 @@ int lookup_symbol_name(unsigned long addr, char *symname);
 int lookup_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name);
 
 /* How and when do we show kallsyms values? */
-extern int kallsyms_show_value(void);
+extern bool kallsyms_show_value(const struct cred *cred);
 
 #else /* !CONFIG_KALLSYMS */
 
@@ -158,7 +159,7 @@ static inline int lookup_symbol_attrs(unsigned long addr, unsigned long *size, u
        return -ERANGE;
 }
 
-static inline int kallsyms_show_value(void)
+static inline bool kallsyms_show_value(const struct cred *cred)
 {
        return false;
 }
index 1776eb2..ea67910 100644 (file)
@@ -208,7 +208,7 @@ struct crash_mem_range {
 struct crash_mem {
        unsigned int max_nr_ranges;
        unsigned int nr_ranges;
-       struct crash_mem_range ranges[0];
+       struct crash_mem_range ranges[];
 };
 
 extern int crash_exclude_mem_range(struct crash_mem *mem,
index c62d764..477b8b7 100644 (file)
@@ -176,6 +176,17 @@ kgdb_arch_handle_exception(int vector, int signo, int err_code,
                           char *remcom_out_buffer,
                           struct pt_regs *regs);
 
+/**
+ *     kgdb_arch_handle_qxfer_pkt - Handle architecture specific GDB XML
+ *                                  packets.
+ *     @remcom_in_buffer: The buffer of the packet we have read.
+ *     @remcom_out_buffer: The buffer of %BUFMAX bytes to write a packet into.
+ */
+
+extern void
+kgdb_arch_handle_qxfer_pkt(char *remcom_in_buffer,
+                          char *remcom_out_buffer);
+
 /**
  *     kgdb_call_nmi_hook - Call kgdb_nmicallback() on the current CPU
  *     @ignored: This parameter is only here to match the prototype.
@@ -276,8 +287,7 @@ struct kgdb_arch {
  * the I/O driver.
  * @post_exception: Pointer to a function that will do any cleanup work
  * for the I/O driver.
- * @is_console: 1 if the end device is a console 0 if the I/O device is
- * not a console
+ * @cons: valid if the I/O device is a console; else NULL.
  */
 struct kgdb_io {
        const char              *name;
@@ -288,7 +298,7 @@ struct kgdb_io {
        void                    (*deinit) (void);
        void                    (*pre_exception) (void);
        void                    (*post_exception) (void);
-       int                     is_console;
+       struct console          *cons;
 };
 
 extern const struct kgdb_arch          arch_kgdb_ops;
@@ -315,6 +325,7 @@ extern int kgdb_hex2mem(char *buf, char *mem, int count);
 
 extern int kgdb_isremovedbreak(unsigned long addr);
 extern void kgdb_schedule_breakpoint(void);
+extern int kgdb_has_hit_break(unsigned long addr);
 
 extern int
 kgdb_handle_exception(int ex_vector, int signo, int err_code,
index 594265b..6adf90f 100644 (file)
@@ -161,7 +161,7 @@ struct kretprobe_instance {
        kprobe_opcode_t *ret_addr;
        struct task_struct *task;
        void *fp;
-       char data[0];
+       char data[];
 };
 
 struct kretprobe_blackpoint {
@@ -350,6 +350,10 @@ static inline struct kprobe_ctlblk *get_kprobe_ctlblk(void)
        return this_cpu_ptr(&kprobe_ctlblk);
 }
 
+extern struct kprobe kprobe_busy;
+void kprobe_busy_begin(void);
+void kprobe_busy_end(void);
+
 kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset);
 int register_kprobe(struct kprobe *p);
 void unregister_kprobe(struct kprobe *p);
index 62ec926..d564855 100644 (file)
@@ -409,7 +409,7 @@ struct kvm_irq_routing_table {
         * Array indexed by gsi. Each entry contains list of irq chips
         * the gsi is connected to.
         */
-       struct hlist_head map[0];
+       struct hlist_head map[];
 };
 #endif
 
index af83285..77ccf04 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/acpi.h>
 #include <linux/cdrom.h>
 #include <linux/sched.h>
+#include <linux/async.h>
 
 /*
  * Define if arch has non-standard setup.  This is a _PCI_ standard
@@ -609,7 +610,7 @@ struct ata_host {
        struct task_struct      *eh_owner;
 
        struct ata_port         *simplex_claimed;       /* channel owning the DMA */
-       struct ata_port         *ports[0];
+       struct ata_port         *ports[];
 };
 
 struct ata_queued_cmd {
@@ -872,6 +873,8 @@ struct ata_port {
        struct timer_list       fastdrain_timer;
        unsigned long           fastdrain_cnt;
 
+       async_cookie_t          cookie;
+
        int                     em_message_type;
        void                    *private_data;
 
@@ -1092,7 +1095,11 @@ extern int ata_scsi_ioctl(struct scsi_device *dev, unsigned int cmd,
 #define ATA_SCSI_COMPAT_IOCTL /* empty */
 #endif
 extern int ata_scsi_queuecmd(struct Scsi_Host *h, struct scsi_cmnd *cmd);
+#if IS_REACHABLE(CONFIG_ATA)
 bool ata_scsi_dma_need_drain(struct request *rq);
+#else
+#define ata_scsi_dma_need_drain NULL
+#endif
 extern int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *dev,
                            unsigned int cmd, void __user *arg);
 extern bool ata_link_online(struct ata_link *link);
index 6791813..af998f9 100644 (file)
@@ -150,7 +150,7 @@ LSM_HOOK(int, 0, inode_listsecurity, struct inode *inode, char *buffer,
         size_t buffer_size)
 LSM_HOOK(void, LSM_RET_VOID, inode_getsecid, struct inode *inode, u32 *secid)
 LSM_HOOK(int, 0, inode_copy_up, struct dentry *src, struct cred **new)
-LSM_HOOK(int, 0, inode_copy_up_xattr, const char *name)
+LSM_HOOK(int, -EOPNOTSUPP, inode_copy_up_xattr, const char *name)
 LSM_HOOK(int, 0, kernfs_init_security, struct kernfs_node *kn_dir,
         struct kernfs_node *kn)
 LSM_HOOK(int, 0, file_permission, struct file *file, int mask)
@@ -360,7 +360,7 @@ LSM_HOOK(int, 0, key_alloc, struct key *key, const struct cred *cred,
         unsigned long flags)
 LSM_HOOK(void, LSM_RET_VOID, key_free, struct key *key)
 LSM_HOOK(int, 0, key_permission, key_ref_t key_ref, const struct cred *cred,
-        unsigned perm)
+        enum key_need_perm need_perm)
 LSM_HOOK(int, 0, key_getsecurity, struct key *key, char **_buffer)
 #endif /* CONFIG_KEYS */
 
index 13c0e45..1e6ca71 100644 (file)
@@ -147,6 +147,7 @@ enum {
        MLX5_REG_MCDA            = 0x9063,
        MLX5_REG_MCAM            = 0x907f,
        MLX5_REG_MIRC            = 0x9162,
+       MLX5_REG_SBCAM           = 0xB01F,
        MLX5_REG_RESOURCE_DUMP   = 0xC000,
 };
 
index 116bd9b..073b79e 100644 (file)
@@ -4283,7 +4283,8 @@ struct mlx5_ifc_rst2init_qp_out_bits {
 
        u8         syndrome[0x20];
 
-       u8         reserved_at_40[0x40];
+       u8         reserved_at_40[0x20];
+       u8         ece[0x20];
 };
 
 struct mlx5_ifc_rst2init_qp_in_bits {
@@ -4300,7 +4301,7 @@ struct mlx5_ifc_rst2init_qp_in_bits {
 
        u8         opt_param_mask[0x20];
 
-       u8         reserved_at_a0[0x20];
+       u8         ece[0x20];
 
        struct mlx5_ifc_qpc_bits qpc;
 
@@ -6619,7 +6620,8 @@ struct mlx5_ifc_init2init_qp_out_bits {
 
        u8         syndrome[0x20];
 
-       u8         reserved_at_40[0x40];
+       u8         reserved_at_40[0x20];
+       u8         ece[0x20];
 };
 
 struct mlx5_ifc_init2init_qp_in_bits {
@@ -6636,7 +6638,7 @@ struct mlx5_ifc_init2init_qp_in_bits {
 
        u8         opt_param_mask[0x20];
 
-       u8         reserved_at_a0[0x20];
+       u8         ece[0x20];
 
        struct mlx5_ifc_qpc_bits qpc;
 
@@ -9958,6 +9960,34 @@ struct mlx5_ifc_pptb_reg_bits {
        u8         untagged_buff[0x4];
 };
 
+struct mlx5_ifc_sbcam_reg_bits {
+       u8         reserved_at_0[0x8];
+       u8         feature_group[0x8];
+       u8         reserved_at_10[0x8];
+       u8         access_reg_group[0x8];
+
+       u8         reserved_at_20[0x20];
+
+       u8         sb_access_reg_cap_mask[4][0x20];
+
+       u8         reserved_at_c0[0x80];
+
+       u8         sb_feature_cap_mask[4][0x20];
+
+       u8         reserved_at_1c0[0x40];
+
+       u8         cap_total_buffer_size[0x20];
+
+       u8         cap_cell_size[0x10];
+       u8         cap_max_pg_buffers[0x8];
+       u8         cap_num_pool_supported[0x8];
+
+       u8         reserved_at_240[0x8];
+       u8         cap_sbsr_stat_size[0x8];
+       u8         cap_max_tclass_data[0x8];
+       u8         cap_max_cpu_ingress_tclass_sb[0x8];
+};
+
 struct mlx5_ifc_pbmc_reg_bits {
        u8         reserved_at_0[0x8];
        u8         local_port[0x8];
index c4c37fd..f6f8849 100644 (file)
@@ -257,8 +257,8 @@ struct lruvec {
         */
        unsigned long                   anon_cost;
        unsigned long                   file_cost;
-       /* Evictions & activations on the inactive file list */
-       atomic_long_t                   inactive_age;
+       /* Non-resident age, driven by LRU movement */
+       atomic_long_t                   nonresident_age;
        /* Refaults at the time of last reclaim cycle */
        unsigned long                   refaults;
        /* Various lruvec state flags (enum lruvec_flags) */
index 8d764aa..e14cbe4 100644 (file)
@@ -318,7 +318,7 @@ struct pcmcia_device_id {
 #define INPUT_DEVICE_ID_LED_MAX                0x0f
 #define INPUT_DEVICE_ID_SND_MAX                0x07
 #define INPUT_DEVICE_ID_FF_MAX         0x7f
-#define INPUT_DEVICE_ID_SW_MAX         0x0f
+#define INPUT_DEVICE_ID_SW_MAX         0x10
 #define INPUT_DEVICE_ID_PROP_MAX       0x1f
 
 #define INPUT_DEVICE_ID_MATCH_BUS      1
index 6fc613e..39e28e1 100644 (file)
@@ -3157,7 +3157,7 @@ static inline int dev_recursion_level(void)
        return this_cpu_read(softnet_data.xmit.recursion);
 }
 
-#define XMIT_RECURSION_LIMIT   10
+#define XMIT_RECURSION_LIMIT   8
 static inline bool dev_xmit_recursion(void)
 {
        return unlikely(__this_cpu_read(softnet_data.xmit.recursion) >
index b394bd4..c4676d6 100644 (file)
 int ipt_register_table(struct net *net, const struct xt_table *table,
                       const struct ipt_replace *repl,
                       const struct nf_hook_ops *ops, struct xt_table **res);
+
+void ipt_unregister_table_pre_exit(struct net *net, struct xt_table *table,
+                      const struct nf_hook_ops *ops);
+
+void ipt_unregister_table_exit(struct net *net, struct xt_table *table);
+
 void ipt_unregister_table(struct net *net, struct xt_table *table,
                          const struct nf_hook_ops *ops);
 
index 8225f78..1547d5f 100644 (file)
@@ -29,6 +29,9 @@ int ip6t_register_table(struct net *net, const struct xt_table *table,
                        const struct nf_hook_ops *ops, struct xt_table **res);
 void ip6t_unregister_table(struct net *net, struct xt_table *table,
                           const struct nf_hook_ops *ops);
+void ip6t_unregister_table_pre_exit(struct net *net, struct xt_table *table,
+                                   const struct nf_hook_ops *ops);
+void ip6t_unregister_table_exit(struct net *net, struct xt_table *table);
 extern unsigned int ip6t_do_table(struct sk_buff *skb,
                                  const struct nf_hook_state *state,
                                  struct xt_table *table);
index 6590450..93fcef1 100644 (file)
@@ -304,16 +304,33 @@ static inline __must_check size_t __ab_c_size(size_t a, size_t b, size_t c)
  * struct_size() - Calculate size of structure with trailing array.
  * @p: Pointer to the structure.
  * @member: Name of the array member.
- * @n: Number of elements in the array.
+ * @count: Number of elements in the array.
  *
  * Calculates size of memory needed for structure @p followed by an
- * array of @n @member elements.
+ * array of @count number of @member elements.
  *
  * Return: number of bytes needed or SIZE_MAX on overflow.
  */
-#define struct_size(p, member, n)                                      \
-       __ab_c_size(n,                                                  \
+#define struct_size(p, member, count)                                  \
+       __ab_c_size(count,                                              \
                    sizeof(*(p)->member) + __must_be_array((p)->member),\
                    sizeof(*(p)))
 
+/**
+ * flex_array_size() - Calculate size of a flexible array member
+ *                     within an enclosing structure.
+ *
+ * @p: Pointer to the structure.
+ * @member: Name of the flexible array member.
+ * @count: Number of elements in the array.
+ *
+ * Calculates size of a flexible array of @count number of @member
+ * elements, at the end of structure @p.
+ *
+ * Return: number of bytes needed or SIZE_MAX on overflow.
+ */
+#define flex_array_size(p, member, count)                              \
+       array_size(count,                                               \
+                   sizeof(*(p)->member) + __must_be_array((p)->member))
+
 #endif /* __LINUX_OVERFLOW_H */
index c79d833..34c1c4f 100644 (file)
@@ -2169,12 +2169,11 @@ static inline int pci_pcie_type(const struct pci_dev *dev)
  */
 static inline struct pci_dev *pcie_find_root_port(struct pci_dev *dev)
 {
-       struct pci_dev *bridge = pci_upstream_bridge(dev);
-
-       while (bridge) {
-               if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT)
-                       return bridge;
-               bridge = pci_upstream_bridge(bridge);
+       while (dev) {
+               if (pci_is_pcie(dev) &&
+                   pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
+                       return dev;
+               dev = pci_upstream_bridge(dev);
        }
 
        return NULL;
index 32b6c52..56c1e8e 100644 (file)
@@ -249,6 +249,13 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
 }
 #endif
 
+#ifndef __HAVE_ARCH_PTEP_GET
+static inline pte_t ptep_get(pte_t *ptep)
+{
+       return READ_ONCE(*ptep);
+}
+#endif
+
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 #ifndef __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
 static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
index 8c05d0f..b693b60 100644 (file)
@@ -1416,6 +1416,7 @@ int phy_ethtool_ksettings_set(struct phy_device *phydev,
 int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd);
 int phy_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 int phy_do_ioctl_running(struct net_device *dev, struct ifreq *ifr, int cmd);
+int phy_disable_interrupts(struct phy_device *phydev);
 void phy_request_interrupt(struct phy_device *phydev);
 void phy_free_interrupt(struct phy_device *phydev);
 void phy_print_status(struct phy_device *phydev);
index 7fbc867..49d155c 100644 (file)
@@ -597,7 +597,7 @@ int sev_guest_df_flush(int *error);
  */
 int sev_guest_decommission(struct sev_data_decommission *data, int *error);
 
-void *psp_copy_user_blob(u64 __user uaddr, u32 len);
+void *psp_copy_user_blob(u64 uaddr, u32 len);
 
 #else  /* !CONFIG_CRYPTO_DEV_SP_PSP */
 
index 733fad7..6d15040 100644 (file)
@@ -207,28 +207,34 @@ static inline u32 qed_chain_get_cons_idx_u32(struct qed_chain *p_chain)
 
 static inline u16 qed_chain_get_elem_left(struct qed_chain *p_chain)
 {
+       u16 elem_per_page = p_chain->elem_per_page;
+       u32 prod = p_chain->u.chain16.prod_idx;
+       u32 cons = p_chain->u.chain16.cons_idx;
        u16 used;
 
-       used = (u16) (((u32)0x10000 +
-                      (u32)p_chain->u.chain16.prod_idx) -
-                     (u32)p_chain->u.chain16.cons_idx);
+       if (prod < cons)
+               prod += (u32)U16_MAX + 1;
+
+       used = (u16)(prod - cons);
        if (p_chain->mode == QED_CHAIN_MODE_NEXT_PTR)
-               used -= p_chain->u.chain16.prod_idx / p_chain->elem_per_page -
-                   p_chain->u.chain16.cons_idx / p_chain->elem_per_page;
+               used -= prod / elem_per_page - cons / elem_per_page;
 
        return (u16)(p_chain->capacity - used);
 }
 
 static inline u32 qed_chain_get_elem_left_u32(struct qed_chain *p_chain)
 {
+       u16 elem_per_page = p_chain->elem_per_page;
+       u64 prod = p_chain->u.chain32.prod_idx;
+       u64 cons = p_chain->u.chain32.cons_idx;
        u32 used;
 
-       used = (u32) (((u64)0x100000000ULL +
-                      (u64)p_chain->u.chain32.prod_idx) -
-                     (u64)p_chain->u.chain32.cons_idx);
+       if (prod < cons)
+               prod += (u64)U32_MAX + 1;
+
+       used = (u32)(prod - cons);
        if (p_chain->mode == QED_CHAIN_MODE_NEXT_PTR)
-               used -= p_chain->u.chain32.prod_idx / p_chain->elem_per_page -
-                   p_chain->u.chain32.cons_idx / p_chain->elem_per_page;
+               used -= (u32)(prod / elem_per_page - cons / elem_per_page);
 
        return p_chain->capacity - used;
 }
index 45e1f8f..9ab7443 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/once.h>
+#include <asm/percpu.h>
 
 #include <uapi/linux/random.h>
 
@@ -119,6 +120,8 @@ struct rnd_state {
        __u32 s1, s2, s3, s4;
 };
 
+DECLARE_PER_CPU(struct rnd_state, net_rand_state);
+
 u32 prandom_u32_state(struct rnd_state *state);
 void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes);
 void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state);
index 70ebef8..d3432ee 100644 (file)
@@ -33,7 +33,7 @@
  * of two or more hash tables when the rhashtable is being resized.
  * The end of the chain is marked with a special nulls marks which has
  * the least significant bit set but otherwise stores the address of
- * the hash bucket.  This allows us to be be sure we've found the end
+ * the hash bucket.  This allows us to be sure we've found the end
  * of the right list.
  * The value stored in the hash bucket has BIT(0) used as a lock bit.
  * This bit must be atomically set before any changes are made to
index 4f922af..45cf7b6 100644 (file)
@@ -155,7 +155,7 @@ static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
  * Loop over each sg element in the given sg_table object.
  */
 #define for_each_sgtable_sg(sgt, sg, i)                \
-       for_each_sg(sgt->sgl, sg, sgt->orig_nents, i)
+       for_each_sg((sgt)->sgl, sg, (sgt)->orig_nents, i)
 
 /*
  * Loop over each sg element in the given *DMA mapped* sg_table object.
@@ -163,7 +163,7 @@ static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
  * of the each element.
  */
 #define for_each_sgtable_dma_sg(sgt, sg, i)    \
-       for_each_sg(sgt->sgl, sg, sgt->nents, i)
+       for_each_sg((sgt)->sgl, sg, (sgt)->nents, i)
 
 /**
  * sg_chain - Chain two sglists together
@@ -451,7 +451,7 @@ sg_page_iter_dma_address(struct sg_dma_page_iter *dma_iter)
  * See also for_each_sg_page(). In each loop it operates on PAGE_SIZE unit.
  */
 #define for_each_sgtable_page(sgt, piter, pgoffset)    \
-       for_each_sg_page(sgt->sgl, piter, sgt->orig_nents, pgoffset)
+       for_each_sg_page((sgt)->sgl, piter, (sgt)->orig_nents, pgoffset)
 
 /**
  * for_each_sgtable_dma_page - iterate over the DMA mapped sg_table object
@@ -465,7 +465,7 @@ sg_page_iter_dma_address(struct sg_dma_page_iter *dma_iter)
  * unit.
  */
 #define for_each_sgtable_dma_page(sgt, dma_iter, pgoffset)     \
-       for_each_sg_dma_page(sgt->sgl, dma_iter, sgt->nents, pgoffset)
+       for_each_sg_dma_page((sgt)->sgl, dma_iter, (sgt)->nents, pgoffset)
 
 
 /*
index b62e6aa..6833729 100644 (file)
@@ -114,10 +114,6 @@ struct task_group;
 
 #define task_is_stopped_or_traced(task)        ((task->state & (__TASK_STOPPED | __TASK_TRACED)) != 0)
 
-#define task_contributes_to_load(task) ((task->state & TASK_UNINTERRUPTIBLE) != 0 && \
-                                        (task->flags & PF_FROZEN) == 0 && \
-                                        (task->state & TASK_NOLOAD) == 0)
-
 #ifdef CONFIG_DEBUG_ATOMIC_SLEEP
 
 /*
@@ -654,9 +650,8 @@ struct task_struct {
        unsigned int                    ptrace;
 
 #ifdef CONFIG_SMP
-       struct llist_node               wake_entry;
-       unsigned int                    wake_entry_type;
        int                             on_cpu;
+       struct __call_single_node       wake_entry;
 #ifdef CONFIG_THREAD_INFO_IN_TASK
        /* Current CPU: */
        unsigned int                    cpu;
index fa067de..d2b4204 100644 (file)
@@ -19,6 +19,7 @@ struct task_struct;
 #define JOBCTL_TRAPPING_BIT    21      /* switching to TRACED */
 #define JOBCTL_LISTENING_BIT   22      /* ptracer is listening for events */
 #define JOBCTL_TRAP_FREEZE_BIT 23      /* trap for cgroup freezer */
+#define JOBCTL_TASK_WORK_BIT   24      /* set by TWA_SIGNAL */
 
 #define JOBCTL_STOP_DEQUEUED   (1UL << JOBCTL_STOP_DEQUEUED_BIT)
 #define JOBCTL_STOP_PENDING    (1UL << JOBCTL_STOP_PENDING_BIT)
@@ -28,9 +29,10 @@ struct task_struct;
 #define JOBCTL_TRAPPING                (1UL << JOBCTL_TRAPPING_BIT)
 #define JOBCTL_LISTENING       (1UL << JOBCTL_LISTENING_BIT)
 #define JOBCTL_TRAP_FREEZE     (1UL << JOBCTL_TRAP_FREEZE_BIT)
+#define JOBCTL_TASK_WORK       (1UL << JOBCTL_TASK_WORK_BIT)
 
 #define JOBCTL_TRAP_MASK       (JOBCTL_TRAP_STOP | JOBCTL_TRAP_NOTIFY)
-#define JOBCTL_PENDING_MASK    (JOBCTL_STOP_PENDING | JOBCTL_TRAP_MASK)
+#define JOBCTL_PENDING_MASK    (JOBCTL_STOP_PENDING | JOBCTL_TRAP_MASK | JOBCTL_TASK_WORK)
 
 extern bool task_set_jobctl_pending(struct task_struct *task, unsigned long mask);
 extern void task_clear_jobctl_trapping(struct task_struct *task);
index 8ccd821..7673123 100644 (file)
@@ -221,7 +221,7 @@ struct sctp_datahdr {
        __be16 stream;
        __be16 ssn;
        __u32 ppid;
-       __u8  payload[0];
+       __u8  payload[];
 };
 
 struct sctp_data_chunk {
@@ -269,7 +269,7 @@ struct sctp_inithdr {
        __be16 num_outbound_streams;
        __be16 num_inbound_streams;
        __be32 initial_tsn;
-       __u8  params[0];
+       __u8  params[];
 };
 
 struct sctp_init_chunk {
@@ -299,13 +299,13 @@ struct sctp_cookie_preserve_param {
 /* Section 3.3.2.1 Host Name Address (11) */
 struct sctp_hostname_param {
        struct sctp_paramhdr param_hdr;
-       uint8_t hostname[0];
+       uint8_t hostname[];
 };
 
 /* Section 3.3.2.1 Supported Address Types (12) */
 struct sctp_supported_addrs_param {
        struct sctp_paramhdr param_hdr;
-       __be16 types[0];
+       __be16 types[];
 };
 
 /* ADDIP Section 3.2.6 Adaptation Layer Indication */
@@ -317,25 +317,25 @@ struct sctp_adaptation_ind_param {
 /* ADDIP Section 4.2.7 Supported Extensions Parameter */
 struct sctp_supported_ext_param {
        struct sctp_paramhdr param_hdr;
-       __u8 chunks[0];
+       __u8 chunks[];
 };
 
 /* AUTH Section 3.1 Random */
 struct sctp_random_param {
        struct sctp_paramhdr param_hdr;
-       __u8 random_val[0];
+       __u8 random_val[];
 };
 
 /* AUTH Section 3.2 Chunk List */
 struct sctp_chunks_param {
        struct sctp_paramhdr param_hdr;
-       __u8 chunks[0];
+       __u8 chunks[];
 };
 
 /* AUTH Section 3.3 HMAC Algorithm */
 struct sctp_hmac_algo_param {
        struct sctp_paramhdr param_hdr;
-       __be16 hmac_ids[0];
+       __be16 hmac_ids[];
 };
 
 /* RFC 2960.  Section 3.3.3 Initiation Acknowledgement (INIT ACK) (2):
@@ -350,7 +350,7 @@ struct sctp_initack_chunk {
 /* Section 3.3.3.1 State Cookie (7) */
 struct sctp_cookie_param {
        struct sctp_paramhdr p;
-       __u8 body[0];
+       __u8 body[];
 };
 
 /* Section 3.3.3.1 Unrecognized Parameters (8) */
@@ -384,7 +384,7 @@ struct sctp_sackhdr {
        __be32 a_rwnd;
        __be16 num_gap_ack_blocks;
        __be16 num_dup_tsns;
-       union sctp_sack_variable variable[0];
+       union sctp_sack_variable variable[];
 };
 
 struct sctp_sack_chunk {
@@ -436,7 +436,7 @@ struct sctp_shutdown_chunk {
 struct sctp_errhdr {
        __be16 cause;
        __be16 length;
-       __u8  variable[0];
+       __u8  variable[];
 };
 
 struct sctp_operr_chunk {
@@ -594,7 +594,7 @@ struct sctp_fwdtsn_skip {
 
 struct sctp_fwdtsn_hdr {
        __be32 new_cum_tsn;
-       struct sctp_fwdtsn_skip skip[0];
+       struct sctp_fwdtsn_skip skip[];
 };
 
 struct sctp_fwdtsn_chunk {
@@ -611,7 +611,7 @@ struct sctp_ifwdtsn_skip {
 
 struct sctp_ifwdtsn_hdr {
        __be32 new_cum_tsn;
-       struct sctp_ifwdtsn_skip skip[0];
+       struct sctp_ifwdtsn_skip skip[];
 };
 
 struct sctp_ifwdtsn_chunk {
@@ -658,7 +658,7 @@ struct sctp_addip_param {
 
 struct sctp_addiphdr {
        __be32  serial;
-       __u8    params[0];
+       __u8    params[];
 };
 
 struct sctp_addip_chunk {
@@ -718,7 +718,7 @@ struct sctp_addip_chunk {
 struct sctp_authhdr {
        __be16 shkey_id;
        __be16 hmac_id;
-       __u8   hmac[0];
+       __u8   hmac[];
 };
 
 struct sctp_auth_chunk {
@@ -733,7 +733,7 @@ struct sctp_infox {
 
 struct sctp_reconf_chunk {
        struct sctp_chunkhdr chunk_hdr;
-       __u8 params[0];
+       __u8 params[];
 };
 
 struct sctp_strreset_outreq {
@@ -741,13 +741,13 @@ struct sctp_strreset_outreq {
        __be32 request_seq;
        __be32 response_seq;
        __be32 send_reset_at_tsn;
-       __be16 list_of_streams[0];
+       __be16 list_of_streams[];
 };
 
 struct sctp_strreset_inreq {
        struct sctp_paramhdr param_hdr;
        __be32 request_seq;
-       __be16 list_of_streams[0];
+       __be16 list_of_streams[];
 };
 
 struct sctp_strreset_tsnreq {
index 9fd550e..791f484 100644 (file)
@@ -462,10 +462,104 @@ extern void uart_handle_cts_change(struct uart_port *uport,
 extern void uart_insert_char(struct uart_port *port, unsigned int status,
                 unsigned int overrun, unsigned int ch, unsigned int flag);
 
-extern int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch);
-extern int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch);
-extern void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long flags);
-extern int uart_handle_break(struct uart_port *port);
+#ifdef CONFIG_MAGIC_SYSRQ_SERIAL
+#define SYSRQ_TIMEOUT  (HZ * 5)
+
+bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch);
+
+static inline int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
+{
+       if (!port->sysrq)
+               return 0;
+
+       if (ch && time_before(jiffies, port->sysrq)) {
+               if (sysrq_mask()) {
+                       handle_sysrq(ch);
+                       port->sysrq = 0;
+                       return 1;
+               }
+               if (uart_try_toggle_sysrq(port, ch))
+                       return 1;
+       }
+       port->sysrq = 0;
+
+       return 0;
+}
+
+static inline int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch)
+{
+       if (!port->sysrq)
+               return 0;
+
+       if (ch && time_before(jiffies, port->sysrq)) {
+               if (sysrq_mask()) {
+                       port->sysrq_ch = ch;
+                       port->sysrq = 0;
+                       return 1;
+               }
+               if (uart_try_toggle_sysrq(port, ch))
+                       return 1;
+       }
+       port->sysrq = 0;
+
+       return 0;
+}
+
+static inline void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long irqflags)
+{
+       int sysrq_ch;
+
+       if (!port->has_sysrq) {
+               spin_unlock_irqrestore(&port->lock, irqflags);
+               return;
+       }
+
+       sysrq_ch = port->sysrq_ch;
+       port->sysrq_ch = 0;
+
+       spin_unlock_irqrestore(&port->lock, irqflags);
+
+       if (sysrq_ch)
+               handle_sysrq(sysrq_ch);
+}
+#else  /* CONFIG_MAGIC_SYSRQ_SERIAL */
+static inline int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
+{
+       return 0;
+}
+static inline int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch)
+{
+       return 0;
+}
+static inline void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long irqflags)
+{
+       spin_unlock_irqrestore(&port->lock, irqflags);
+}
+#endif /* CONFIG_MAGIC_SYSRQ_SERIAL */
+
+/*
+ * We do the SysRQ and SAK checking like this...
+ */
+static inline int uart_handle_break(struct uart_port *port)
+{
+       struct uart_state *state = port->state;
+
+       if (port->handle_break)
+               port->handle_break(port);
+
+#ifdef CONFIG_MAGIC_SYSRQ_SERIAL
+       if (port->has_sysrq && uart_console(port)) {
+               if (!port->sysrq) {
+                       port->sysrq = jiffies + SYSRQ_TIMEOUT;
+                       return 1;
+               }
+               port->sysrq = 0;
+       }
+#endif
+       if (port->flags & UPF_SAK)
+               do_SAK(state->port.tty);
+       return 0;
+}
 
 /*
  *     UART_ENABLE_MS - determine if port should enable modem status irqs
index 08674cd..1e9ed84 100644 (file)
@@ -430,6 +430,19 @@ static inline void psock_set_prog(struct bpf_prog **pprog,
                bpf_prog_put(prog);
 }
 
+static inline int psock_replace_prog(struct bpf_prog **pprog,
+                                    struct bpf_prog *prog,
+                                    struct bpf_prog *old)
+{
+       if (cmpxchg(pprog, old, prog) != old)
+               return -ENOENT;
+
+       if (old)
+               bpf_prog_put(old);
+
+       return 0;
+}
+
 static inline void psock_progs_drop(struct sk_psock_progs *progs)
 {
        psock_set_prog(&progs->msg_parser, NULL);
index 7ee202a..80d557e 100644 (file)
 #include <linux/list.h>
 #include <linux/cpumask.h>
 #include <linux/init.h>
-#include <linux/llist.h>
+#include <linux/smp_types.h>
 
 typedef void (*smp_call_func_t)(void *info);
 typedef bool (*smp_cond_func_t)(int cpu, void *info);
 
-enum {
-       CSD_FLAG_LOCK           = 0x01,
-
-       /* IRQ_WORK_flags */
-
-       CSD_TYPE_ASYNC          = 0x00,
-       CSD_TYPE_SYNC           = 0x10,
-       CSD_TYPE_IRQ_WORK       = 0x20,
-       CSD_TYPE_TTWU           = 0x30,
-       CSD_FLAG_TYPE_MASK      = 0xF0,
-};
-
 /*
  * structure shares (partial) layout with struct irq_work
  */
 struct __call_single_data {
-       struct llist_node llist;
-       unsigned int flags;
+       union {
+               struct __call_single_node node;
+               struct {
+                       struct llist_node llist;
+                       unsigned int flags;
+               };
+       };
        smp_call_func_t func;
        void *info;
 };
diff --git a/include/linux/smp_types.h b/include/linux/smp_types.h
new file mode 100644 (file)
index 0000000..364b3ae
--- /dev/null
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LINUX_SMP_TYPES_H
+#define __LINUX_SMP_TYPES_H
+
+#include <linux/llist.h>
+
+enum {
+       CSD_FLAG_LOCK           = 0x01,
+
+       IRQ_WORK_PENDING        = 0x01,
+       IRQ_WORK_BUSY           = 0x02,
+       IRQ_WORK_LAZY           = 0x04, /* No IPI, wait for tick */
+       IRQ_WORK_HARD_IRQ       = 0x08, /* IRQ context on PREEMPT_RT */
+
+       IRQ_WORK_CLAIMED        = (IRQ_WORK_PENDING | IRQ_WORK_BUSY),
+
+       CSD_TYPE_ASYNC          = 0x00,
+       CSD_TYPE_SYNC           = 0x10,
+       CSD_TYPE_IRQ_WORK       = 0x20,
+       CSD_TYPE_TTWU           = 0x30,
+
+       CSD_FLAG_TYPE_MASK      = 0xF0,
+};
+
+/*
+ * struct __call_single_node is the primary type on
+ * smp.c:call_single_queue.
+ *
+ * flush_smp_call_function_queue() only reads the type from
+ * __call_single_node::u_flags as a regular load, the above
+ * (anonymous) enum defines all the bits of this word.
+ *
+ * Other bits are not modified until the type is known.
+ *
+ * CSD_TYPE_SYNC/ASYNC:
+ *     struct {
+ *             struct llist_node node;
+ *             unsigned int flags;
+ *             smp_call_func_t func;
+ *             void *info;
+ *     };
+ *
+ * CSD_TYPE_IRQ_WORK:
+ *     struct {
+ *             struct llist_node node;
+ *             atomic_t flags;
+ *             void (*func)(struct irq_work *);
+ *     };
+ *
+ * CSD_TYPE_TTWU:
+ *     struct {
+ *             struct llist_node node;
+ *             unsigned int flags;
+ *     };
+ *
+ */
+
+struct __call_single_node {
+       struct llist_node       llist;
+       union {
+               unsigned int    u_flags;
+               atomic_t        a_flags;
+       };
+};
+
+#endif /* __LINUX_SMP_TYPES_H */
index 4c5974b..5b3216b 100644 (file)
@@ -313,6 +313,7 @@ struct vma_swap_readahead {
 };
 
 /* linux/mm/workingset.c */
+void workingset_age_nonresident(struct lruvec *lruvec, unsigned long nr_pages);
 void *workingset_eviction(struct page *page, struct mem_cgroup *target_memcg);
 void workingset_refault(struct page *page, void *shadow);
 void workingset_activation(struct page *page);
index 7c354c2..b951a87 100644 (file)
@@ -1360,7 +1360,7 @@ static inline long ksys_lchown(const char __user *filename, uid_t user,
 
 extern long do_sys_ftruncate(unsigned int fd, loff_t length, int small);
 
-static inline long ksys_ftruncate(unsigned int fd, unsigned long length)
+static inline long ksys_ftruncate(unsigned int fd, loff_t length)
 {
        return do_sys_ftruncate(fd, length, 1);
 }
index bd9a6a9..0fb93aa 100644 (file)
@@ -13,7 +13,10 @@ init_task_work(struct callback_head *twork, task_work_func_t func)
        twork->func = func;
 }
 
-int task_work_add(struct task_struct *task, struct callback_head *twork, bool);
+#define TWA_RESUME     1
+#define TWA_SIGNAL     2
+int task_work_add(struct task_struct *task, struct callback_head *twork, int);
+
 struct callback_head *task_work_cancel(struct task_struct *, task_work_func_t);
 void task_work_run(void);
 
index 9aac824..a1bbaa1 100644 (file)
@@ -220,7 +220,9 @@ struct tcp_sock {
        } rack;
        u16     advmss;         /* Advertised MSS                       */
        u8      compressed_ack;
-       u8      dup_ack_counter;
+       u8      dup_ack_counter:2,
+               tlp_retrans:1,  /* TLP is a retransmission */
+               unused:5;
        u32     chrono_start;   /* Start time in jiffies of a TCP chrono */
        u32     chrono_stat[3]; /* Time in jiffies for chrono_stat stats */
        u8      chrono_type:2,  /* current chronograph type */
@@ -243,7 +245,7 @@ struct tcp_sock {
                save_syn:1,     /* Save headers of SYN packet */
                is_cwnd_limited:1,/* forward progress limited by snd_cwnd? */
                syn_smc:1;      /* SYN includes SMC */
-       u32     tlp_high_seq;   /* snd_nxt at the time of TLP retransmit. */
+       u32     tlp_high_seq;   /* snd_nxt at the time of TLP */
 
        u32     tcp_tx_delay;   /* delay (in usec) added to TX packets */
        u64     tcp_wstamp_ns;  /* departure time for next sent data packet */
index 299cbb8..44073d0 100644 (file)
@@ -124,7 +124,7 @@ struct tifm_adapter {
        int                 (*has_ms_pif)(struct tifm_adapter *fm,
                                          struct tifm_dev *sock);
 
-       struct tifm_dev     *sockets[0];
+       struct tifm_dev     *sockets[];
 };
 
 struct tifm_adapter *tifm_alloc_adapter(unsigned int num_sockets,
index b27e2ff..d5471d6 100644 (file)
@@ -222,9 +222,9 @@ extern bool timekeeping_rtc_skipresume(void);
 
 extern void timekeeping_inject_sleeptime64(const struct timespec64 *delta);
 
-/*
+/**
  * struct system_time_snapshot - simultaneous raw/real time capture with
- *     counter value
+ *                              counter value
  * @cycles:    Clocksource counter value to produce the system times
  * @real:      Realtime system time
  * @raw:       Monotonic raw system time
@@ -239,9 +239,9 @@ struct system_time_snapshot {
        u8              cs_was_changed_seq;
 };
 
-/*
+/**
  * struct system_device_crosststamp - system/device cross-timestamp
- *     (syncronized capture)
+ *                                   (synchronized capture)
  * @device:            Device time
  * @sys_realtime:      Realtime simultaneous with device time
  * @sys_monoraw:       Monotonic raw simultaneous with device time
@@ -252,12 +252,12 @@ struct system_device_crosststamp {
        ktime_t sys_monoraw;
 };
 
-/*
+/**
  * struct system_counterval_t - system counter value with the pointer to the
- *     corresponding clocksource
+ *                             corresponding clocksource
  * @cycles:    System counter value
  * @cs:                Clocksource corresponding to system counter value. Used by
- *     timekeeping code to verify comparibility of two cycle values
+ *             timekeeping code to verify comparibility of two cycle values
  */
 struct system_counterval_t {
        u64                     cycles;
index 4f8c90c..64356b1 100644 (file)
@@ -81,6 +81,8 @@ struct tcg_efi_specid_event_algs {
        u16 digest_size;
 } __packed;
 
+#define TCG_SPECID_SIG "Spec ID Event03"
+
 struct tcg_efi_specid_event_head {
        u8 signature[16];
        u32 platform_class;
@@ -171,6 +173,7 @@ static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
        int i;
        int j;
        u32 count, event_type;
+       const u8 zero_digest[sizeof(event_header->digest)] = {0};
 
        marker = event;
        marker_start = marker;
@@ -198,10 +201,19 @@ static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
        count = READ_ONCE(event->count);
        event_type = READ_ONCE(event->event_type);
 
+       /* Verify that it's the log header */
+       if (event_header->pcr_idx != 0 ||
+           event_header->event_type != NO_ACTION ||
+           memcmp(event_header->digest, zero_digest, sizeof(zero_digest))) {
+               size = 0;
+               goto out;
+       }
+
        efispecid = (struct tcg_efi_specid_event_head *)event_header->event;
 
        /* Check if event is malformed. */
-       if (count > efispecid->num_algs) {
+       if (memcmp(efispecid->signature, TCG_SPECID_SIG,
+                  sizeof(TCG_SPECID_SIG)) || count > efispecid->num_algs) {
                size = 0;
                goto out;
        }
index 7bcadca..0a76ddc 100644 (file)
@@ -301,13 +301,14 @@ copy_struct_from_user(void *dst, size_t ksize, const void __user *src,
        return 0;
 }
 
-bool probe_kernel_read_allowed(const void *unsafe_src, size_t size);
+bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size);
 
-extern long probe_kernel_read(void *dst, const void *src, size_t size);
-extern long probe_user_read(void *dst, const void __user *src, size_t size);
+long copy_from_kernel_nofault(void *dst, const void *src, size_t size);
+long notrace copy_to_kernel_nofault(void *dst, const void *src, size_t size);
 
-extern long notrace probe_kernel_write(void *dst, const void *src, size_t size);
-extern long notrace probe_user_write(void __user *dst, const void *src, size_t size);
+long copy_from_user_nofault(void *dst, const void __user *src, size_t size);
+long notrace copy_to_user_nofault(void __user *dst, const void *src,
+               size_t size);
 
 long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr,
                long count);
@@ -317,14 +318,16 @@ long strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
 long strnlen_user_nofault(const void __user *unsafe_addr, long count);
 
 /**
- * probe_kernel_address(): safely attempt to read from a location
- * @addr: address to read from
- * @retval: read into this variable
+ * get_kernel_nofault(): safely attempt to read from a location
+ * @val: read into this variable
+ * @ptr: address to read from
  *
  * Returns 0 on success, or -EFAULT.
  */
-#define probe_kernel_address(addr, retval)             \
-       probe_kernel_read(&retval, addr, sizeof(retval))
+#define get_kernel_nofault(val, ptr) ({                                \
+       const typeof(val) *__gk_ptr = (ptr);                    \
+       copy_from_kernel_nofault(&(val), __gk_ptr, sizeof(val));\
+})
 
 #ifndef user_access_begin
 #define user_access_begin(ptr,len) access_ok(ptr, len)
index 48bb681..0221f85 100644 (file)
@@ -106,7 +106,6 @@ extern void *vzalloc(unsigned long size);
 extern void *vmalloc_user(unsigned long size);
 extern void *vmalloc_node(unsigned long size, int node);
 extern void *vzalloc_node(unsigned long size, int node);
-extern void *vmalloc_exec(unsigned long size);
 extern void *vmalloc_32(unsigned long size);
 extern void *vmalloc_32_user(unsigned long size);
 extern void *__vmalloc(unsigned long size, gfp_t gfp_mask);
index 47eaa34..c5afaf8 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
+#include <linux/mm.h>
 #include <uapi/linux/xattr.h>
 
 struct inode;
@@ -94,7 +95,7 @@ static inline void simple_xattrs_free(struct simple_xattrs *xattrs)
 
        list_for_each_entry_safe(xattr, node, &xattrs->head, list) {
                kfree(xattr->name);
-               kfree(xattr);
+               kvfree(xattr);
        }
 }
 
index 07adfac..852d8fb 100644 (file)
@@ -400,7 +400,15 @@ static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, co
 static inline struct neighbour *dst_neigh_lookup_skb(const struct dst_entry *dst,
                                                     struct sk_buff *skb)
 {
-       struct neighbour *n =  dst->ops->neigh_lookup(dst, skb, NULL);
+       struct neighbour *n = NULL;
+
+       /* The packets from tunnel devices (eg bareudp) may have only
+        * metadata in the dst pointer of skb. Hence a pointer check of
+        * neigh_lookup is needed.
+        */
+       if (dst->ops->neigh_lookup)
+               n = dst->ops->neigh_lookup(dst, skb, NULL);
+
        return IS_ERR(n) ? NULL : n;
 }
 
index a7eba43..4b6e362 100644 (file)
@@ -372,7 +372,8 @@ flow_dissector_init_keys(struct flow_dissector_key_control *key_control,
 }
 
 #ifdef CONFIG_BPF_SYSCALL
-int flow_dissector_bpf_prog_attach(struct net *net, struct bpf_prog *prog);
+int flow_dissector_bpf_prog_attach_check(struct net *net,
+                                        struct bpf_prog *prog);
 #endif /* CONFIG_BPF_SYSCALL */
 
 #endif
index f2c8311..3eaf25f 100644 (file)
@@ -5,7 +5,6 @@
 #include <linux/list.h>
 #include <linux/netlink.h>
 #include <net/flow_dissector.h>
-#include <linux/rhashtable.h>
 
 struct flow_match {
        struct flow_dissector   *dissector;
@@ -450,6 +449,7 @@ struct flow_block_indr {
        struct net_device               *dev;
        enum flow_block_binder_type     binder_type;
        void                            *data;
+       void                            *cb_priv;
        void                            (*cleanup)(struct flow_block_cb *block_cb);
 };
 
@@ -467,6 +467,13 @@ struct flow_block_cb {
 struct flow_block_cb *flow_block_cb_alloc(flow_setup_cb_t *cb,
                                          void *cb_ident, void *cb_priv,
                                          void (*release)(void *cb_priv));
+struct flow_block_cb *flow_indr_block_cb_alloc(flow_setup_cb_t *cb,
+                                              void *cb_ident, void *cb_priv,
+                                              void (*release)(void *cb_priv),
+                                              struct flow_block_offload *bo,
+                                              struct net_device *dev, void *data,
+                                              void *indr_cb_priv,
+                                              void (*cleanup)(struct flow_block_cb *block_cb));
 void flow_block_cb_free(struct flow_block_cb *block_cb);
 
 struct flow_block_cb *flow_block_cb_lookup(struct flow_block *block,
@@ -488,6 +495,13 @@ static inline void flow_block_cb_remove(struct flow_block_cb *block_cb,
        list_move(&block_cb->list, &offload->cb_list);
 }
 
+static inline void flow_indr_block_cb_remove(struct flow_block_cb *block_cb,
+                                            struct flow_block_offload *offload)
+{
+       list_del(&block_cb->indr.list);
+       list_move(&block_cb->list, &offload->cb_list);
+}
+
 bool flow_block_cb_is_busy(flow_setup_cb_t *cb, void *cb_ident,
                           struct list_head *driver_block_list);
 
@@ -532,11 +546,13 @@ static inline void flow_block_init(struct flow_block *flow_block)
 }
 
 typedef int flow_indr_block_bind_cb_t(struct net_device *dev, void *cb_priv,
-                                     enum tc_setup_type type, void *type_data);
+                                     enum tc_setup_type type, void *type_data,
+                                     void *data,
+                                     void (*cleanup)(struct flow_block_cb *block_cb));
 
 int flow_indr_dev_register(flow_indr_block_bind_cb_t *cb, void *cb_priv);
 void flow_indr_dev_unregister(flow_indr_block_bind_cb_t *cb, void *cb_priv,
-                             flow_setup_cb_t *setup_cb);
+                             void (*release)(void *cb_priv));
 int flow_indr_dev_setup_offload(struct net_device *dev,
                                enum tc_setup_type type, void *data,
                                struct flow_block_offload *bo,
index 7495066..6e5f1e1 100644 (file)
@@ -35,13 +35,6 @@ struct genl_info;
  *     do additional, common, filtering and return an error
  * @post_doit: called after an operation's doit callback, it may
  *     undo operations done by pre_doit, for example release locks
- * @mcast_bind: a socket bound to the given multicast group (which
- *     is given as the offset into the groups array)
- * @mcast_unbind: a socket was unbound from the given multicast group.
- *     Note that unbind() will not be called symmetrically if the
- *     generic netlink family is removed while there are still open
- *     sockets.
- * @attrbuf: buffer to store parsed attributes (private)
  * @mcgrps: multicast groups used by this family
  * @n_mcgrps: number of multicast groups
  * @mcgrp_offset: starting number of multicast group IDs in this family
@@ -64,9 +57,6 @@ struct genl_family {
        void                    (*post_doit)(const struct genl_ops *ops,
                                             struct sk_buff *skb,
                                             struct genl_info *info);
-       int                     (*mcast_bind)(struct net *net, int group);
-       void                    (*mcast_unbind)(struct net *net, int group);
-       struct nlattr **        attrbuf;        /* private */
        const struct genl_ops * ops;
        const struct genl_multicast_group *mcgrps;
        unsigned int            n_ops;
index 3a6595b..e42402f 100644 (file)
@@ -21,7 +21,7 @@
  * |                                                               |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *
- * C bit indicates contol message when set, data message when unset.
+ * C bit indicates control message when set, data message when unset.
  * For a control message, proto/ctype is interpreted as a type of
  * control message. For data messages, proto/ctype is the IP protocol
  * of the next header.
index 0f0d1ef..e1eaf17 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <linux/ip.h>
 #include <linux/skbuff.h>
+#include <linux/if_vlan.h>
 
 #include <net/inet_sock.h>
 #include <net/dsfield.h>
@@ -172,7 +173,7 @@ static inline void ipv6_copy_dscp(unsigned int dscp, struct ipv6hdr *inner)
 
 static inline int INET_ECN_set_ce(struct sk_buff *skb)
 {
-       switch (skb->protocol) {
+       switch (skb_protocol(skb, true)) {
        case cpu_to_be16(ETH_P_IP):
                if (skb_network_header(skb) + sizeof(struct iphdr) <=
                    skb_tail_pointer(skb))
@@ -191,7 +192,7 @@ static inline int INET_ECN_set_ce(struct sk_buff *skb)
 
 static inline int INET_ECN_set_ect1(struct sk_buff *skb)
 {
-       switch (skb->protocol) {
+       switch (skb_protocol(skb, true)) {
        case cpu_to_be16(ETH_P_IP):
                if (skb_network_header(skb) + sizeof(struct iphdr) <=
                    skb_tail_pointer(skb))
@@ -272,12 +273,16 @@ static inline int IP_ECN_decapsulate(const struct iphdr *oiph,
 {
        __u8 inner;
 
-       if (skb->protocol == htons(ETH_P_IP))
+       switch (skb_protocol(skb, true)) {
+       case htons(ETH_P_IP):
                inner = ip_hdr(skb)->tos;
-       else if (skb->protocol == htons(ETH_P_IPV6))
+               break;
+       case htons(ETH_P_IPV6):
                inner = ipv6_get_dsfield(ipv6_hdr(skb));
-       else
+               break;
+       default:
                return 0;
+       }
 
        return INET_ECN_decapsulate(skb, oiph->tos, inner);
 }
@@ -287,12 +292,16 @@ static inline int IP6_ECN_decapsulate(const struct ipv6hdr *oipv6h,
 {
        __u8 inner;
 
-       if (skb->protocol == htons(ETH_P_IP))
+       switch (skb_protocol(skb, true)) {
+       case htons(ETH_P_IP):
                inner = ip_hdr(skb)->tos;
-       else if (skb->protocol == htons(ETH_P_IPV6))
+               break;
+       case htons(ETH_P_IPV6):
                inner = ipv6_get_dsfield(ipv6_hdr(skb));
-       else
+               break;
+       default:
                return 0;
+       }
 
        return INET_ECN_decapsulate(skb, ipv6_get_dsfield(oipv6h), inner);
 }
index 076e5d7..36025de 100644 (file)
@@ -290,6 +290,9 @@ int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
                      struct ip_tunnel_parm *p, __u32 fwmark);
 void ip_tunnel_setup(struct net_device *dev, unsigned int net_id);
 
+extern const struct header_ops ip_tunnel_header_ops;
+__be16 ip_tunnel_parse_protocol(const struct sk_buff *skb);
+
 struct ip_tunnel_encap_ops {
        size_t (*encap_hlen)(struct ip_tunnel_encap *e);
        int (*build_header)(struct sk_buff *skb, struct ip_tunnel_encap *e,
index d7338bf..16e8b2f 100644 (file)
@@ -161,10 +161,51 @@ struct nf_flow_route {
 struct flow_offload *flow_offload_alloc(struct nf_conn *ct);
 void flow_offload_free(struct flow_offload *flow);
 
-int nf_flow_table_offload_add_cb(struct nf_flowtable *flow_table,
-                                flow_setup_cb_t *cb, void *cb_priv);
-void nf_flow_table_offload_del_cb(struct nf_flowtable *flow_table,
-                                 flow_setup_cb_t *cb, void *cb_priv);
+static inline int
+nf_flow_table_offload_add_cb(struct nf_flowtable *flow_table,
+                            flow_setup_cb_t *cb, void *cb_priv)
+{
+       struct flow_block *block = &flow_table->flow_block;
+       struct flow_block_cb *block_cb;
+       int err = 0;
+
+       down_write(&flow_table->flow_block_lock);
+       block_cb = flow_block_cb_lookup(block, cb, cb_priv);
+       if (block_cb) {
+               err = -EEXIST;
+               goto unlock;
+       }
+
+       block_cb = flow_block_cb_alloc(cb, cb_priv, cb_priv, NULL);
+       if (IS_ERR(block_cb)) {
+               err = PTR_ERR(block_cb);
+               goto unlock;
+       }
+
+       list_add_tail(&block_cb->list, &block->cb_list);
+
+unlock:
+       up_write(&flow_table->flow_block_lock);
+       return err;
+}
+
+static inline void
+nf_flow_table_offload_del_cb(struct nf_flowtable *flow_table,
+                            flow_setup_cb_t *cb, void *cb_priv)
+{
+       struct flow_block *block = &flow_table->flow_block;
+       struct flow_block_cb *block_cb;
+
+       down_write(&flow_table->flow_block_lock);
+       block_cb = flow_block_cb_lookup(block, cb, cb_priv);
+       if (block_cb) {
+               list_del(&block_cb->list);
+               flow_block_cb_free(block_cb);
+       } else {
+               WARN_ON(true);
+       }
+       up_write(&flow_table->flow_block_lock);
+}
 
 int flow_offload_route_init(struct flow_offload *flow,
                            const struct nf_flow_route *route);
index a8dce2a..0ca6a1b 100644 (file)
@@ -9,10 +9,13 @@
 #include <linux/bpf-netns.h>
 
 struct bpf_prog;
+struct bpf_prog_array;
 
 struct netns_bpf {
-       struct bpf_prog __rcu *progs[MAX_NETNS_BPF_ATTACH_TYPE];
-       struct bpf_link *links[MAX_NETNS_BPF_ATTACH_TYPE];
+       /* Array of programs to run compiled from progs or links */
+       struct bpf_prog_array __rcu *run_array[MAX_NETNS_BPF_ATTACH_TYPE];
+       struct bpf_prog *progs[MAX_NETNS_BPF_ATTACH_TYPE];
+       struct list_head links[MAX_NETNS_BPF_ATTACH_TYPE];
 };
 
 #endif /* __NETNS_BPF_H__ */
index 9092e69..ac8c890 100644 (file)
@@ -136,17 +136,6 @@ static inline void qdisc_run(struct Qdisc *q)
        }
 }
 
-static inline __be16 tc_skb_protocol(const struct sk_buff *skb)
-{
-       /* We need to take extra care in case the skb came via
-        * vlan accelerated path. In that case, use skb->vlan_proto
-        * as the original vlan header was already stripped.
-        */
-       if (skb_vlan_tag_present(skb))
-               return skb->vlan_proto;
-       return skb->protocol;
-}
-
 /* Calculate maximal size of packet seen by hard_start_xmit
    routine of this device.
  */
index 15b4d9a..122d9e2 100644 (file)
@@ -353,11 +353,13 @@ enum {
         ipv4_is_anycast_6to4(a))
 
 /* Flags used for the bind address copy functions.  */
-#define SCTP_ADDR6_ALLOWED     0x00000001      /* IPv6 address is allowed by
+#define SCTP_ADDR4_ALLOWED     0x00000001      /* IPv4 address is allowed by
                                                   local sock family */
-#define SCTP_ADDR4_PEERSUPP    0x00000002      /* IPv4 address is supported by
+#define SCTP_ADDR6_ALLOWED     0x00000002      /* IPv6 address is allowed by
+                                                  local sock family */
+#define SCTP_ADDR4_PEERSUPP    0x00000004      /* IPv4 address is supported by
                                                   peer */
-#define SCTP_ADDR6_PEERSUPP    0x00000004      /* IPv6 address is supported by
+#define SCTP_ADDR6_PEERSUPP    0x00000008      /* IPv6 address is supported by
                                                   peer */
 
 /* Reasons to retransmit. */
index c53cc42..1183507 100644 (file)
@@ -533,7 +533,8 @@ enum sk_pacing {
  * be copied.
  */
 #define SK_USER_DATA_NOCOPY    1UL
-#define SK_USER_DATA_PTRMASK   ~(SK_USER_DATA_NOCOPY)
+#define SK_USER_DATA_BPF       2UL     /* Managed by BPF */
+#define SK_USER_DATA_PTRMASK   ~(SK_USER_DATA_NOCOPY | SK_USER_DATA_BPF)
 
 /**
  * sk_user_data_is_nocopy - Test if sk_user_data pointer must not be copied
@@ -1848,7 +1849,6 @@ static inline int sk_rx_queue_get(const struct sock *sk)
 
 static inline void sk_set_socket(struct sock *sk, struct socket *sock)
 {
-       sk_tx_queue_clear(sk);
        sk->sk_socket = sock;
 }
 
index 79654bc..8250d6f 100644 (file)
@@ -66,7 +66,16 @@ static inline struct nf_flowtable *tcf_ct_ft(const struct tc_action *a)
 #endif /* CONFIG_NF_CONNTRACK */
 
 #if IS_ENABLED(CONFIG_NET_ACT_CT)
-void tcf_ct_flow_table_restore_skb(struct sk_buff *skb, unsigned long cookie);
+static inline void
+tcf_ct_flow_table_restore_skb(struct sk_buff *skb, unsigned long cookie)
+{
+       enum ip_conntrack_info ctinfo = cookie & NFCT_INFOMASK;
+       struct nf_conn *ct;
+
+       ct = (struct nf_conn *)(cookie & NFCT_PTRMASK);
+       nf_conntrack_get(&ct->ct_general);
+       nf_ct_set(skb, ct, ctinfo);
+}
 #else
 static inline void
 tcf_ct_flow_table_restore_skb(struct sk_buff *skb, unsigned long cookie) { }
index 094fe68..c7d213c 100644 (file)
@@ -1008,6 +1008,7 @@ struct xfrm_offload {
 #define        XFRM_GRO                32
 #define        XFRM_ESP_NO_TRAILER     64
 #define        XFRM_DEV_RESUME         128
+#define        XFRM_XMIT               256
 
        __u32                   status;
 #define CRYPTO_SUCCESS                         1
index a4ff226..6842990 100644 (file)
@@ -40,7 +40,7 @@ struct xsk_buff_pool {
        u32 headroom;
        u32 chunk_size;
        u32 frame_len;
-       bool cheap_dma;
+       bool dma_need_sync;
        bool unaligned;
        void *addrs;
        struct device *dev;
@@ -80,7 +80,7 @@ static inline dma_addr_t xp_get_frame_dma(struct xdp_buff_xsk *xskb)
 void xp_dma_sync_for_cpu_slow(struct xdp_buff_xsk *xskb);
 static inline void xp_dma_sync_for_cpu(struct xdp_buff_xsk *xskb)
 {
-       if (xskb->pool->cheap_dma)
+       if (!xskb->pool->dma_need_sync)
                return;
 
        xp_dma_sync_for_cpu_slow(xskb);
@@ -91,7 +91,7 @@ void xp_dma_sync_for_device_slow(struct xsk_buff_pool *pool, dma_addr_t dma,
 static inline void xp_dma_sync_for_device(struct xsk_buff_pool *pool,
                                          dma_addr_t dma, size_t size)
 {
-       if (pool->cheap_dma)
+       if (!pool->dma_need_sync)
                return;
 
        xp_dma_sync_for_device_slow(pool, dma, size);
index c4369a6..2f1fc23 100644 (file)
@@ -305,6 +305,25 @@ struct rvt_rq {
        spinlock_t lock ____cacheline_aligned_in_smp;
 };
 
+/**
+ * rvt_get_rq_count - count numbers of request work queue entries
+ * in circular buffer
+ * @rq: data structure for request queue entry
+ * @head: head indices of the circular buffer
+ * @tail: tail indices of the circular buffer
+ *
+ * Return - total number of entries in the Receive Queue
+ */
+
+static inline u32 rvt_get_rq_count(struct rvt_rq *rq, u32 head, u32 tail)
+{
+       u32 count = head - tail;
+
+       if ((s32)count < 0)
+               count += rq->size;
+       return count;
+}
+
 /*
  * This structure holds the information that the send tasklet needs
  * to send a RDMA read response or atomic operation.
index 6ce8eff..70cbc50 100644 (file)
@@ -66,6 +66,7 @@ struct snd_compr_runtime {
  * @direction: stream direction, playback/recording
  * @metadata_set: metadata set flag, true when set
  * @next_track: has userspace signal next track transition, true when set
+ * @partial_drain: undergoing partial_drain for stream, true when set
  * @private_data: pointer to DSP private data
  * @dma_buffer: allocated buffer if any
  */
@@ -78,6 +79,7 @@ struct snd_compr_stream {
        enum snd_compr_direction direction;
        bool metadata_set;
        bool next_track;
+       bool partial_drain;
        void *private_data;
        struct snd_dma_buffer dma_buffer;
 };
@@ -182,7 +184,13 @@ 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;
+       /* for partial_drain case we are back to running state on success */
+       if (stream->partial_drain) {
+               stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
+               stream->partial_drain = false; /* clear this flag as well */
+       } else {
+               stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+       }
 
        wake_up(&stream->runtime->sleep);
 }
index b652206..8c5e381 100644 (file)
@@ -161,4 +161,15 @@ int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream,
 
 #define SND_DMAENGINE_PCM_DRV_NAME "snd_dmaengine_pcm"
 
+struct dmaengine_pcm {
+       struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1];
+       const struct snd_dmaengine_pcm_config *config;
+       struct snd_soc_component component;
+       unsigned int flags;
+};
+
+static inline struct dmaengine_pcm *soc_component_to_pcm(struct snd_soc_component *p)
+{
+       return container_of(p, struct dmaengine_pcm, component);
+}
 #endif
index f9024c7..02e1d77 100644 (file)
@@ -12,6 +12,7 @@ struct rt5670_platform_data {
        int jd_mode;
        bool in2_diff;
        bool dev_gpio;
+       bool gpio1_is_ext_spk_en;
 
        bool dmic_en;
        unsigned int dmic1_data_pin;
index 212257e..71e178c 100644 (file)
@@ -161,6 +161,7 @@ void snd_soc_dai_resume(struct snd_soc_dai *dai);
 int snd_soc_dai_compress_new(struct snd_soc_dai *dai,
                             struct snd_soc_pcm_runtime *rtd, int num);
 bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream);
+void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link);
 void snd_soc_dai_action(struct snd_soc_dai *dai,
                        int stream, int action);
 static inline void snd_soc_dai_activate(struct snd_soc_dai *dai,
index ef5dd28..3ce7f0f 100644 (file)
@@ -444,6 +444,10 @@ int devm_snd_soc_register_component(struct device *dev,
                         const struct snd_soc_component_driver *component_driver,
                         struct snd_soc_dai_driver *dai_drv, int num_dai);
 void snd_soc_unregister_component(struct device *dev);
+void snd_soc_unregister_component_by_driver(struct device *dev,
+                        const struct snd_soc_component_driver *component_driver);
+struct snd_soc_component *snd_soc_lookup_component_nolocked(struct device *dev,
+                                                           const char *driver_name);
 struct snd_soc_component *snd_soc_lookup_component(struct device *dev,
                                                   const char *driver_name);
 
@@ -1361,6 +1365,10 @@ void snd_soc_remove_pcm_runtime(struct snd_soc_card *card,
 struct snd_soc_dai *snd_soc_register_dai(struct snd_soc_component *component,
                                         struct snd_soc_dai_driver *dai_drv,
                                         bool legacy_dai_naming);
+struct snd_soc_dai *devm_snd_soc_register_dai(struct device *dev,
+                                             struct snd_soc_component *component,
+                                             struct snd_soc_dai_driver *dai_drv,
+                                             bool legacy_dai_naming);
 void snd_soc_unregister_dai(struct snd_soc_dai *dai);
 
 struct snd_soc_dai *snd_soc_find_dai(
index 1257f26..93b1142 100644 (file)
@@ -254,7 +254,6 @@ TRACE_EVENT(block_bio_bounce,
  * block_bio_complete - completed all work on the block operation
  * @q: queue holding the block operation
  * @bio: block operation completed
- * @error: io error value
  *
  * This tracepoint indicates there is no further work to do on this
  * block IO operation @bio.
index ba9efdc..059b6e4 100644 (file)
@@ -400,7 +400,7 @@ enum rxrpc_tx_point {
        EM(rxrpc_cong_begin_retransmission,     " Retrans") \
        EM(rxrpc_cong_cleared_nacks,            " Cleared") \
        EM(rxrpc_cong_new_low_nack,             " NewLowN") \
-       EM(rxrpc_cong_no_change,                "") \
+       EM(rxrpc_cong_no_change,                " -") \
        EM(rxrpc_cong_progress,                 " Progres") \
        EM(rxrpc_cong_retransmit_again,         " ReTxAgn") \
        EM(rxrpc_cong_rtt_window_end,           " RttWinE") \
index 1968481..8bd3305 100644 (file)
@@ -3168,16 +3168,15 @@ union bpf_attr {
  *     Return
  *             The id is returned or 0 in case the id could not be retrieved.
  *
- * void *bpf_ringbuf_output(void *ringbuf, void *data, u64 size, u64 flags)
+ * int bpf_ringbuf_output(void *ringbuf, void *data, u64 size, u64 flags)
  *     Description
  *             Copy *size* bytes from *data* into a ring buffer *ringbuf*.
- *             If BPF_RB_NO_WAKEUP is specified in *flags*, no notification of
- *             new data availability is sent.
- *             IF BPF_RB_FORCE_WAKEUP is specified in *flags*, notification of
- *             new data availability is sent unconditionally.
+ *             If **BPF_RB_NO_WAKEUP** is specified in *flags*, no notification
+ *             of new data availability is sent.
+ *             If **BPF_RB_FORCE_WAKEUP** is specified in *flags*, notification
+ *             of new data availability is sent unconditionally.
  *     Return
- *             0, on success;
- *             < 0, on error.
+ *             0 on success, or a negative error in case of failure.
  *
  * void *bpf_ringbuf_reserve(void *ringbuf, u64 size, u64 flags)
  *     Description
@@ -3189,20 +3188,20 @@ union bpf_attr {
  * void bpf_ringbuf_submit(void *data, u64 flags)
  *     Description
  *             Submit reserved ring buffer sample, pointed to by *data*.
- *             If BPF_RB_NO_WAKEUP is specified in *flags*, no notification of
- *             new data availability is sent.
- *             IF BPF_RB_FORCE_WAKEUP is specified in *flags*, notification of
- *             new data availability is sent unconditionally.
+ *             If **BPF_RB_NO_WAKEUP** is specified in *flags*, no notification
+ *             of new data availability is sent.
+ *             If **BPF_RB_FORCE_WAKEUP** is specified in *flags*, notification
+ *             of new data availability is sent unconditionally.
  *     Return
  *             Nothing. Always succeeds.
  *
  * void bpf_ringbuf_discard(void *data, u64 flags)
  *     Description
  *             Discard reserved ring buffer sample, pointed to by *data*.
- *             If BPF_RB_NO_WAKEUP is specified in *flags*, no notification of
- *             new data availability is sent.
- *             IF BPF_RB_FORCE_WAKEUP is specified in *flags*, notification of
- *             new data availability is sent unconditionally.
+ *             If **BPF_RB_NO_WAKEUP** is specified in *flags*, no notification
+ *             of new data availability is sent.
+ *             If **BPF_RB_FORCE_WAKEUP** is specified in *flags*, notification
+ *             of new data availability is sent unconditionally.
  *     Return
  *             Nothing. Always succeeds.
  *
@@ -3210,16 +3209,18 @@ union bpf_attr {
  *     Description
  *             Query various characteristics of provided ring buffer. What
  *             exactly is queries is determined by *flags*:
- *               - BPF_RB_AVAIL_DATA - amount of data not yet consumed;
- *               - BPF_RB_RING_SIZE - the size of ring buffer;
- *               - BPF_RB_CONS_POS - consumer position (can wrap around);
- *               - BPF_RB_PROD_POS - producer(s) position (can wrap around);
- *             Data returned is just a momentary snapshots of actual values
+ *
+ *             * **BPF_RB_AVAIL_DATA**: Amount of data not yet consumed.
+ *             * **BPF_RB_RING_SIZE**: The size of ring buffer.
+ *             * **BPF_RB_CONS_POS**: Consumer position (can wrap around).
+ *             * **BPF_RB_PROD_POS**: Producer(s) position (can wrap around).
+ *
+ *             Data returned is just a momentary snapshot of actual values
  *             and could be inaccurate, so this facility should be used to
  *             power heuristics and for reporting, not to make 100% correct
  *             calculation.
  *     Return
- *             Requested value, or 0, if flags are not recognized.
+ *             Requested value, or 0, if *flags* are not recognized.
  *
  * int bpf_csum_level(struct sk_buff *skb, u64 level)
  *     Description
index b6aac7e..4c14e8b 100644 (file)
@@ -205,6 +205,7 @@ struct fb_bitfield {
 #define FB_ACTIVATE_ALL               64       /* change all VCs on this fb    */
 #define FB_ACTIVATE_FORCE     128      /* force apply even when no change*/
 #define FB_ACTIVATE_INV_MODE  256       /* invalidate videomode */
+#define FB_ACTIVATE_KD_TEXT   512       /* for KDSET vt ioctl */
 
 #define FB_ACCELF_TEXT         1       /* (OBSOLETE) see fb_info.flags and vc_mode */
 
index 379a612..f44eb0a 100644 (file)
@@ -262,6 +262,7 @@ struct fsxattr {
 #define FS_EA_INODE_FL                 0x00200000 /* Inode used for large EA */
 #define FS_EOFBLOCKS_FL                        0x00400000 /* Reserved for ext4 */
 #define FS_NOCOW_FL                    0x00800000 /* Do not cow file */
+#define FS_DAX_FL                      0x02000000 /* Inode is DAX */
 #define FS_INLINE_DATA_FL              0x10000000 /* Reserved for ext4 */
 #define FS_PROJINHERIT_FL              0x20000000 /* Create with parents projid */
 #define FS_CASEFOLD_FL                 0x40000000 /* Folder is case insensitive */
index 1f412fb..e103c14 100644 (file)
@@ -110,9 +110,12 @@ struct dsa_hw_desc {
        uint16_t        rsvd1;
        union {
                uint8_t         expected_res;
+               /* create delta record */
                struct {
                        uint64_t        delta_addr;
                        uint32_t        max_delta_size;
+                       uint32_t        delt_rsvd;
+                       uint8_t         expected_res_mask;
                };
                uint32_t        delta_rec_size;
                uint64_t        dest2;
index b6a835d..0c2e27d 100644 (file)
 #define SW_LINEIN_INSERT       0x0d  /* set = inserted */
 #define SW_MUTE_DEVICE         0x0e  /* set = device disabled */
 #define SW_PEN_INSERTED                0x0f  /* set = pen inserted */
-#define SW_MAX                 0x0f
+#define SW_MACHINE_COVER       0x10  /* set = cover closed */
+#define SW_MAX                 0x10
 #define SW_CNT                 (SW_MAX+1)
 
 /*
index 92c2269..7843742 100644 (file)
@@ -197,6 +197,7 @@ struct io_sqring_offsets {
  * sq_ring->flags
  */
 #define IORING_SQ_NEED_WAKEUP  (1U << 0) /* needs io_uring_enter wakeup */
+#define IORING_SQ_CQ_OVERFLOW  (1U << 1) /* CQ ring is overflown */
 
 struct io_cqring_offsets {
        __u32 head;
index 84f15f4..bee3665 100644 (file)
@@ -36,7 +36,6 @@ enum br_mrp_port_state_type {
 enum br_mrp_port_role_type {
        BR_MRP_PORT_ROLE_PRIMARY,
        BR_MRP_PORT_ROLE_SECONDARY,
-       BR_MRP_PORT_ROLE_NONE,
 };
 
 enum br_mrp_tlv_header_type {
index de5d902..0e09dc5 100644 (file)
@@ -244,6 +244,7 @@ struct nd_cmd_pkg {
 #define NVDIMM_FAMILY_HPE2 2
 #define NVDIMM_FAMILY_MSFT 3
 #define NVDIMM_FAMILY_HYPERV 4
+#define NVDIMM_FAMILY_PAPR 5
 
 #define ND_IOCTL_CALL                  _IOWR(ND_IOCTL, ND_CMD_CALL,\
                                        struct nd_cmd_pkg)
index cba368e..c21edb9 100644 (file)
 
 /* supported values for SO_RDS_TRANSPORT */
 #define        RDS_TRANS_IB    0
-#define        RDS_TRANS_IWARP 1
+#define        RDS_TRANS_GAP   1
 #define        RDS_TRANS_TCP   2
 #define RDS_TRANS_COUNT        3
 #define        RDS_TRANS_NONE  (~0)
+/* don't use RDS_TRANS_IWARP - it is deprecated */
+#define RDS_TRANS_IWARP RDS_TRANS_GAP
 
 /* IOCTLS commands for SOL_RDS */
 #define SIOCRDSSETTOS          (SIOCPROTOPRIVATE)
index ee0f246..d56427c 100644 (file)
 #define SPI_TX_QUAD            0x200
 #define SPI_RX_DUAL            0x400
 #define SPI_RX_QUAD            0x800
+#define SPI_CS_WORD            0x1000
+#define SPI_TX_OCTAL           0x2000
+#define SPI_RX_OCTAL           0x4000
+#define SPI_3WIRE_HIZ          0x8000
 
 /*---------------------------------------------------------------------------*/
 
index 9cec58a..f79d7ab 100644 (file)
@@ -103,7 +103,7 @@ VMMDEV_ASSERT_SIZE(vbg_ioctl_driver_version_info, 24 + 20);
 
 
 /* IOCTL to perform a VMM Device request larger then 1KB. */
-#define VBG_IOCTL_VMMDEV_REQUEST_BIG   _IOC(_IOC_READ | _IOC_WRITE, 'V', 3, 0)
+#define VBG_IOCTL_VMMDEV_REQUEST_BIG   _IO('V', 3)
 
 
 /** VBG_IOCTL_HGCM_CONNECT data structure. */
@@ -198,7 +198,7 @@ struct vbg_ioctl_log {
        } u;
 };
 
-#define VBG_IOCTL_LOG(s)               _IOC(_IOC_READ | _IOC_WRITE, 'V', 9, s)
+#define VBG_IOCTL_LOG(s)               _IO('V', 9)
 
 
 /** VBG_IOCTL_WAIT_FOR_EVENTS data structure. */
index eca6692..9204705 100644 (file)
@@ -1030,7 +1030,7 @@ struct vfio_iommu_type1_info_cap_iova_range {
  * size in bytes that can be used by user applications when getting the dirty
  * bitmap.
  */
-#define VFIO_IOMMU_TYPE1_INFO_CAP_MIGRATION  1
+#define VFIO_IOMMU_TYPE1_INFO_CAP_MIGRATION  2
 
 struct vfio_iommu_type1_info_cap_migration {
        struct  vfio_info_cap_header header;
index c1395b5..9463db2 100644 (file)
@@ -7,6 +7,7 @@
   Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
   Copyright (c) 2001-2002 Silicon Graphics, Inc.  All Rights Reserved.
   Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
+  Copyright (c) 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
 */
 
 #include <linux/libc-compat.h>
@@ -31,6 +32,9 @@
 #define XATTR_BTRFS_PREFIX "btrfs."
 #define XATTR_BTRFS_PREFIX_LEN (sizeof(XATTR_BTRFS_PREFIX) - 1)
 
+#define XATTR_HURD_PREFIX "gnu."
+#define XATTR_HURD_PREFIX_LEN (sizeof(XATTR_HURD_PREFIX) - 1)
+
 #define XATTR_SECURITY_PREFIX  "security."
 #define XATTR_SECURITY_PREFIX_LEN (sizeof(XATTR_SECURITY_PREFIX) - 1)
 
index a46aa8f..0498af5 100644 (file)
@@ -49,13 +49,13 @@ config CLANG_VERSION
 
 config CC_CAN_LINK
        bool
-       default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(m64-flag)) if 64BIT
-       default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(m32-flag))
+       default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(m64-flag)) if 64BIT
+       default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(m32-flag))
 
 config CC_CAN_LINK_STATIC
        bool
-       default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) -static $(m64-flag)) if 64BIT
-       default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) -static $(m32-flag))
+       default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(m64-flag) -static) if 64BIT
+       default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(m32-flag) -static)
 
 config CC_HAS_ASM_GOTO
        def_bool $(success,$(srctree)/scripts/gcc-goto.sh $(CC))
index 8c201f4..b2301bd 100644 (file)
@@ -1851,7 +1851,6 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
        }
 
        audit_get_stamp(ab->ctx, &t, &serial);
-       audit_clear_dummy(ab->ctx);
        audit_log_format(ab, "audit(%llu.%03lu:%u): ",
                         (unsigned long long)t.tv_sec, t.tv_nsec/1000000, serial);
 
index f0233dc..ddc2287 100644 (file)
@@ -290,13 +290,6 @@ extern int audit_signal_info_syscall(struct task_struct *t);
 extern void audit_filter_inodes(struct task_struct *tsk,
                                struct audit_context *ctx);
 extern struct list_head *audit_killed_trees(void);
-
-static inline void audit_clear_dummy(struct audit_context *ctx)
-{
-       if (ctx)
-               ctx->dummy = 0;
-}
-
 #else /* CONFIG_AUDITSYSCALL */
 #define auditsc_get_stamp(c, t, s) 0
 #define audit_put_watch(w) {}
@@ -330,7 +323,6 @@ static inline int audit_signal_info_syscall(struct task_struct *t)
 }
 
 #define audit_filter_inodes(t, c) AUDIT_DISABLED
-#define audit_clear_dummy(c) {}
 #endif /* CONFIG_AUDITSYSCALL */
 
 extern char *audit_unpack_string(void **bufp, size_t *remain, size_t len);
index 468a233..fd840c4 100644 (file)
@@ -1417,6 +1417,9 @@ static void audit_log_proctitle(void)
        struct audit_context *context = audit_context();
        struct audit_buffer *ab;
 
+       if (!context || context->dummy)
+               return;
+
        ab = audit_log_start(context, GFP_KERNEL, AUDIT_PROCTITLE);
        if (!ab)
                return; /* audit_panic or being filtered */
index 58c9af1..9a1a98d 100644 (file)
@@ -3746,7 +3746,7 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
                                return false;
 
                        t = btf_type_skip_modifiers(btf, t->type, NULL);
-                       if (!btf_type_is_int(t)) {
+                       if (!btf_type_is_small_int(t)) {
                                bpf_log(log,
                                        "ret type %s not allowed for fmod_ret\n",
                                        btf_kind_str[BTF_INFO_KIND(t->info)]);
@@ -3768,7 +3768,7 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
        /* skip modifiers */
        while (btf_type_is_modifier(t))
                t = btf_type_by_id(btf, t->type);
-       if (btf_type_is_int(t) || btf_type_is_enum(t))
+       if (btf_type_is_small_int(t) || btf_type_is_enum(t))
                /* accessing a scalar */
                return true;
        if (!btf_type_is_ptr(t)) {
index 4d76f16..ac53102 100644 (file)
@@ -1276,16 +1276,23 @@ static bool __cgroup_bpf_prog_array_is_empty(struct cgroup *cgrp,
 
 static int sockopt_alloc_buf(struct bpf_sockopt_kern *ctx, int max_optlen)
 {
-       if (unlikely(max_optlen > PAGE_SIZE) || max_optlen < 0)
+       if (unlikely(max_optlen < 0))
                return -EINVAL;
 
+       if (unlikely(max_optlen > PAGE_SIZE)) {
+               /* We don't expose optvals that are greater than PAGE_SIZE
+                * to the BPF program.
+                */
+               max_optlen = PAGE_SIZE;
+       }
+
        ctx->optval = kzalloc(max_optlen, GFP_USER);
        if (!ctx->optval)
                return -ENOMEM;
 
        ctx->optval_end = ctx->optval + max_optlen;
 
-       return 0;
+       return max_optlen;
 }
 
 static void sockopt_free_buf(struct bpf_sockopt_kern *ctx)
@@ -1319,13 +1326,13 @@ int __cgroup_bpf_run_filter_setsockopt(struct sock *sk, int *level,
         */
        max_optlen = max_t(int, 16, *optlen);
 
-       ret = sockopt_alloc_buf(&ctx, max_optlen);
-       if (ret)
-               return ret;
+       max_optlen = sockopt_alloc_buf(&ctx, max_optlen);
+       if (max_optlen < 0)
+               return max_optlen;
 
        ctx.optlen = *optlen;
 
-       if (copy_from_user(ctx.optval, optval, *optlen) != 0) {
+       if (copy_from_user(ctx.optval, optval, min(*optlen, max_optlen)) != 0) {
                ret = -EFAULT;
                goto out;
        }
@@ -1353,8 +1360,14 @@ int __cgroup_bpf_run_filter_setsockopt(struct sock *sk, int *level,
                /* export any potential modifications */
                *level = ctx.level;
                *optname = ctx.optname;
-               *optlen = ctx.optlen;
-               *kernel_optval = ctx.optval;
+
+               /* optlen == 0 from BPF indicates that we should
+                * use original userspace data.
+                */
+               if (ctx.optlen != 0) {
+                       *optlen = ctx.optlen;
+                       *kernel_optval = ctx.optval;
+               }
        }
 
 out:
@@ -1385,12 +1398,12 @@ int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level,
            __cgroup_bpf_prog_array_is_empty(cgrp, BPF_CGROUP_GETSOCKOPT))
                return retval;
 
-       ret = sockopt_alloc_buf(&ctx, max_optlen);
-       if (ret)
-               return ret;
-
        ctx.optlen = max_optlen;
 
+       max_optlen = sockopt_alloc_buf(&ctx, max_optlen);
+       if (max_optlen < 0)
+               return max_optlen;
+
        if (!retval) {
                /* If kernel getsockopt finished successfully,
                 * copy whatever was returned to the user back
@@ -1404,10 +1417,8 @@ int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level,
                        goto out;
                }
 
-               if (ctx.optlen > max_optlen)
-                       ctx.optlen = max_optlen;
-
-               if (copy_from_user(ctx.optval, optval, ctx.optlen) != 0) {
+               if (copy_from_user(ctx.optval, optval,
+                                  min(ctx.optlen, max_optlen)) != 0) {
                        ret = -EFAULT;
                        goto out;
                }
@@ -1436,10 +1447,12 @@ int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level,
                goto out;
        }
 
-       if (copy_to_user(optval, ctx.optval, ctx.optlen) ||
-           put_user(ctx.optlen, optlen)) {
-               ret = -EFAULT;
-               goto out;
+       if (ctx.optlen != 0) {
+               if (copy_to_user(optval, ctx.optval, ctx.optlen) ||
+                   put_user(ctx.optlen, optlen)) {
+                       ret = -EFAULT;
+                       goto out;
+               }
        }
 
        ret = ctx.retval;
index 0cbb72c..5fdbc77 100644 (file)
@@ -86,12 +86,13 @@ static DEFINE_PER_CPU(struct list_head, dev_flush_list);
 static DEFINE_SPINLOCK(dev_map_lock);
 static LIST_HEAD(dev_map_list);
 
-static struct hlist_head *dev_map_create_hash(unsigned int entries)
+static struct hlist_head *dev_map_create_hash(unsigned int entries,
+                                             int numa_node)
 {
        int i;
        struct hlist_head *hash;
 
-       hash = kmalloc_array(entries, sizeof(*hash), GFP_KERNEL);
+       hash = bpf_map_area_alloc(entries * sizeof(*hash), numa_node);
        if (hash != NULL)
                for (i = 0; i < entries; i++)
                        INIT_HLIST_HEAD(&hash[i]);
@@ -145,7 +146,8 @@ static int dev_map_init_map(struct bpf_dtab *dtab, union bpf_attr *attr)
                return -EINVAL;
 
        if (attr->map_type == BPF_MAP_TYPE_DEVMAP_HASH) {
-               dtab->dev_index_head = dev_map_create_hash(dtab->n_buckets);
+               dtab->dev_index_head = dev_map_create_hash(dtab->n_buckets,
+                                                          dtab->map.numa_node);
                if (!dtab->dev_index_head)
                        goto free_charge;
 
@@ -232,7 +234,7 @@ static void dev_map_free(struct bpf_map *map)
                        }
                }
 
-               kfree(dtab->dev_index_head);
+               bpf_map_area_free(dtab->dev_index_head);
        } else {
                for (i = 0; i < dtab->map.max_entries; i++) {
                        struct bpf_dtab_netdev *dev;
index 78cf061..310241c 100644 (file)
@@ -19,18 +19,21 @@ struct bpf_netns_link {
         * with netns_bpf_mutex held.
         */
        struct net *net;
+       struct list_head node; /* node in list of links attached to net */
 };
 
 /* Protects updates to netns_bpf */
 DEFINE_MUTEX(netns_bpf_mutex);
 
 /* Must be called with netns_bpf_mutex held. */
-static void __net_exit bpf_netns_link_auto_detach(struct bpf_link *link)
+static void netns_bpf_run_array_detach(struct net *net,
+                                      enum netns_bpf_attach_type type)
 {
-       struct bpf_netns_link *net_link =
-               container_of(link, struct bpf_netns_link, link);
+       struct bpf_prog_array *run_array;
 
-       net_link->net = NULL;
+       run_array = rcu_replace_pointer(net->bpf.run_array[type], NULL,
+                                       lockdep_is_held(&netns_bpf_mutex));
+       bpf_prog_array_free(run_array);
 }
 
 static void bpf_netns_link_release(struct bpf_link *link)
@@ -40,22 +43,18 @@ static void bpf_netns_link_release(struct bpf_link *link)
        enum netns_bpf_attach_type type = net_link->netns_type;
        struct net *net;
 
-       /* Link auto-detached by dying netns. */
-       if (!net_link->net)
-               return;
-
        mutex_lock(&netns_bpf_mutex);
 
-       /* Recheck after potential sleep. We can race with cleanup_net
-        * here, but if we see a non-NULL struct net pointer pre_exit
-        * has not happened yet and will block on netns_bpf_mutex.
+       /* We can race with cleanup_net, but if we see a non-NULL
+        * struct net pointer, pre_exit has not run yet and wait for
+        * netns_bpf_mutex.
         */
        net = net_link->net;
        if (!net)
                goto out_unlock;
 
-       net->bpf.links[type] = NULL;
-       RCU_INIT_POINTER(net->bpf.progs[type], NULL);
+       netns_bpf_run_array_detach(net, type);
+       list_del(&net_link->node);
 
 out_unlock:
        mutex_unlock(&netns_bpf_mutex);
@@ -76,6 +75,7 @@ static int bpf_netns_link_update_prog(struct bpf_link *link,
        struct bpf_netns_link *net_link =
                container_of(link, struct bpf_netns_link, link);
        enum netns_bpf_attach_type type = net_link->netns_type;
+       struct bpf_prog_array *run_array;
        struct net *net;
        int ret = 0;
 
@@ -93,8 +93,11 @@ static int bpf_netns_link_update_prog(struct bpf_link *link,
                goto out_unlock;
        }
 
+       run_array = rcu_dereference_protected(net->bpf.run_array[type],
+                                             lockdep_is_held(&netns_bpf_mutex));
+       WRITE_ONCE(run_array->items[0].prog, new_prog);
+
        old_prog = xchg(&link->prog, new_prog);
-       rcu_assign_pointer(net->bpf.progs[type], new_prog);
        bpf_prog_put(old_prog);
 
 out_unlock:
@@ -142,14 +145,38 @@ static const struct bpf_link_ops bpf_netns_link_ops = {
        .show_fdinfo = bpf_netns_link_show_fdinfo,
 };
 
+/* Must be called with netns_bpf_mutex held. */
+static int __netns_bpf_prog_query(const union bpf_attr *attr,
+                                 union bpf_attr __user *uattr,
+                                 struct net *net,
+                                 enum netns_bpf_attach_type type)
+{
+       __u32 __user *prog_ids = u64_to_user_ptr(attr->query.prog_ids);
+       struct bpf_prog_array *run_array;
+       u32 prog_cnt = 0, flags = 0;
+
+       run_array = rcu_dereference_protected(net->bpf.run_array[type],
+                                             lockdep_is_held(&netns_bpf_mutex));
+       if (run_array)
+               prog_cnt = bpf_prog_array_length(run_array);
+
+       if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags)))
+               return -EFAULT;
+       if (copy_to_user(&uattr->query.prog_cnt, &prog_cnt, sizeof(prog_cnt)))
+               return -EFAULT;
+       if (!attr->query.prog_cnt || !prog_ids || !prog_cnt)
+               return 0;
+
+       return bpf_prog_array_copy_to_user(run_array, prog_ids,
+                                          attr->query.prog_cnt);
+}
+
 int netns_bpf_prog_query(const union bpf_attr *attr,
                         union bpf_attr __user *uattr)
 {
-       __u32 __user *prog_ids = u64_to_user_ptr(attr->query.prog_ids);
-       u32 prog_id, prog_cnt = 0, flags = 0;
        enum netns_bpf_attach_type type;
-       struct bpf_prog *attached;
        struct net *net;
+       int ret;
 
        if (attr->query.query_flags)
                return -EINVAL;
@@ -162,36 +189,25 @@ int netns_bpf_prog_query(const union bpf_attr *attr,
        if (IS_ERR(net))
                return PTR_ERR(net);
 
-       rcu_read_lock();
-       attached = rcu_dereference(net->bpf.progs[type]);
-       if (attached) {
-               prog_cnt = 1;
-               prog_id = attached->aux->id;
-       }
-       rcu_read_unlock();
+       mutex_lock(&netns_bpf_mutex);
+       ret = __netns_bpf_prog_query(attr, uattr, net, type);
+       mutex_unlock(&netns_bpf_mutex);
 
        put_net(net);
-
-       if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags)))
-               return -EFAULT;
-       if (copy_to_user(&uattr->query.prog_cnt, &prog_cnt, sizeof(prog_cnt)))
-               return -EFAULT;
-
-       if (!attr->query.prog_cnt || !prog_ids || !prog_cnt)
-               return 0;
-
-       if (copy_to_user(prog_ids, &prog_id, sizeof(u32)))
-               return -EFAULT;
-
-       return 0;
+       return ret;
 }
 
 int netns_bpf_prog_attach(const union bpf_attr *attr, struct bpf_prog *prog)
 {
+       struct bpf_prog_array *run_array;
        enum netns_bpf_attach_type type;
+       struct bpf_prog *attached;
        struct net *net;
        int ret;
 
+       if (attr->target_fd || attr->attach_flags || attr->replace_bpf_fd)
+               return -EINVAL;
+
        type = to_netns_bpf_attach_type(attr->attach_type);
        if (type < 0)
                return -EINVAL;
@@ -200,19 +216,47 @@ int netns_bpf_prog_attach(const union bpf_attr *attr, struct bpf_prog *prog)
        mutex_lock(&netns_bpf_mutex);
 
        /* Attaching prog directly is not compatible with links */
-       if (net->bpf.links[type]) {
+       if (!list_empty(&net->bpf.links[type])) {
                ret = -EEXIST;
                goto out_unlock;
        }
 
        switch (type) {
        case NETNS_BPF_FLOW_DISSECTOR:
-               ret = flow_dissector_bpf_prog_attach(net, prog);
+               ret = flow_dissector_bpf_prog_attach_check(net, prog);
                break;
        default:
                ret = -EINVAL;
                break;
        }
+       if (ret)
+               goto out_unlock;
+
+       attached = net->bpf.progs[type];
+       if (attached == prog) {
+               /* The same program cannot be attached twice */
+               ret = -EINVAL;
+               goto out_unlock;
+       }
+
+       run_array = rcu_dereference_protected(net->bpf.run_array[type],
+                                             lockdep_is_held(&netns_bpf_mutex));
+       if (run_array) {
+               WRITE_ONCE(run_array->items[0].prog, prog);
+       } else {
+               run_array = bpf_prog_array_alloc(1, GFP_KERNEL);
+               if (!run_array) {
+                       ret = -ENOMEM;
+                       goto out_unlock;
+               }
+               run_array->items[0].prog = prog;
+               rcu_assign_pointer(net->bpf.run_array[type], run_array);
+       }
+
+       net->bpf.progs[type] = prog;
+       if (attached)
+               bpf_prog_put(attached);
+
 out_unlock:
        mutex_unlock(&netns_bpf_mutex);
 
@@ -221,63 +265,74 @@ out_unlock:
 
 /* Must be called with netns_bpf_mutex held. */
 static int __netns_bpf_prog_detach(struct net *net,
-                                  enum netns_bpf_attach_type type)
+                                  enum netns_bpf_attach_type type,
+                                  struct bpf_prog *old)
 {
        struct bpf_prog *attached;
 
        /* Progs attached via links cannot be detached */
-       if (net->bpf.links[type])
+       if (!list_empty(&net->bpf.links[type]))
                return -EINVAL;
 
-       attached = rcu_dereference_protected(net->bpf.progs[type],
-                                            lockdep_is_held(&netns_bpf_mutex));
-       if (!attached)
+       attached = net->bpf.progs[type];
+       if (!attached || attached != old)
                return -ENOENT;
-       RCU_INIT_POINTER(net->bpf.progs[type], NULL);
+       netns_bpf_run_array_detach(net, type);
+       net->bpf.progs[type] = NULL;
        bpf_prog_put(attached);
        return 0;
 }
 
-int netns_bpf_prog_detach(const union bpf_attr *attr)
+int netns_bpf_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype)
 {
        enum netns_bpf_attach_type type;
+       struct bpf_prog *prog;
        int ret;
 
+       if (attr->target_fd)
+               return -EINVAL;
+
        type = to_netns_bpf_attach_type(attr->attach_type);
        if (type < 0)
                return -EINVAL;
 
+       prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
+       if (IS_ERR(prog))
+               return PTR_ERR(prog);
+
        mutex_lock(&netns_bpf_mutex);
-       ret = __netns_bpf_prog_detach(current->nsproxy->net_ns, type);
+       ret = __netns_bpf_prog_detach(current->nsproxy->net_ns, type, prog);
        mutex_unlock(&netns_bpf_mutex);
 
+       bpf_prog_put(prog);
+
        return ret;
 }
 
 static int netns_bpf_link_attach(struct net *net, struct bpf_link *link,
                                 enum netns_bpf_attach_type type)
 {
-       struct bpf_prog *prog;
+       struct bpf_netns_link *net_link =
+               container_of(link, struct bpf_netns_link, link);
+       struct bpf_prog_array *run_array;
        int err;
 
        mutex_lock(&netns_bpf_mutex);
 
        /* Allow attaching only one prog or link for now */
-       if (net->bpf.links[type]) {
+       if (!list_empty(&net->bpf.links[type])) {
                err = -E2BIG;
                goto out_unlock;
        }
        /* Links are not compatible with attaching prog directly */
-       prog = rcu_dereference_protected(net->bpf.progs[type],
-                                        lockdep_is_held(&netns_bpf_mutex));
-       if (prog) {
+       if (net->bpf.progs[type]) {
                err = -EEXIST;
                goto out_unlock;
        }
 
        switch (type) {
        case NETNS_BPF_FLOW_DISSECTOR:
-               err = flow_dissector_bpf_prog_attach(net, link->prog);
+               err = flow_dissector_bpf_prog_attach_check(net, link->prog);
                break;
        default:
                err = -EINVAL;
@@ -286,7 +341,15 @@ static int netns_bpf_link_attach(struct net *net, struct bpf_link *link,
        if (err)
                goto out_unlock;
 
-       net->bpf.links[type] = link;
+       run_array = bpf_prog_array_alloc(1, GFP_KERNEL);
+       if (!run_array) {
+               err = -ENOMEM;
+               goto out_unlock;
+       }
+       run_array->items[0].prog = link->prog;
+       rcu_assign_pointer(net->bpf.run_array[type], run_array);
+
+       list_add_tail(&net_link->node, &net->bpf.links[type]);
 
 out_unlock:
        mutex_unlock(&netns_bpf_mutex);
@@ -345,23 +408,34 @@ out_put_net:
        return err;
 }
 
+static int __net_init netns_bpf_pernet_init(struct net *net)
+{
+       int type;
+
+       for (type = 0; type < MAX_NETNS_BPF_ATTACH_TYPE; type++)
+               INIT_LIST_HEAD(&net->bpf.links[type]);
+
+       return 0;
+}
+
 static void __net_exit netns_bpf_pernet_pre_exit(struct net *net)
 {
        enum netns_bpf_attach_type type;
-       struct bpf_link *link;
+       struct bpf_netns_link *net_link;
 
        mutex_lock(&netns_bpf_mutex);
        for (type = 0; type < MAX_NETNS_BPF_ATTACH_TYPE; type++) {
-               link = net->bpf.links[type];
-               if (link)
-                       bpf_netns_link_auto_detach(link);
-               else
-                       __netns_bpf_prog_detach(net, type);
+               netns_bpf_run_array_detach(net, type);
+               list_for_each_entry(net_link, &net->bpf.links[type], node)
+                       net_link->net = NULL; /* auto-detach link */
+               if (net->bpf.progs[type])
+                       bpf_prog_put(net->bpf.progs[type]);
        }
        mutex_unlock(&netns_bpf_mutex);
 }
 
 static struct pernet_operations netns_bpf_pernet_ops __net_initdata = {
+       .init = netns_bpf_pernet_init,
        .pre_exit = netns_bpf_pernet_pre_exit,
 };
 
index 21cde24..cae9d50 100644 (file)
@@ -20,11 +20,14 @@ static struct reuseport_array *reuseport_array(struct bpf_map *map)
 /* The caller must hold the reuseport_lock */
 void bpf_sk_reuseport_detach(struct sock *sk)
 {
-       struct sock __rcu **socks;
+       uintptr_t sk_user_data;
 
        write_lock_bh(&sk->sk_callback_lock);
-       socks = sk->sk_user_data;
-       if (socks) {
+       sk_user_data = (uintptr_t)sk->sk_user_data;
+       if (sk_user_data & SK_USER_DATA_BPF) {
+               struct sock __rcu **socks;
+
+               socks = (void *)(sk_user_data & SK_USER_DATA_PTRMASK);
                WRITE_ONCE(sk->sk_user_data, NULL);
                /*
                 * Do not move this NULL assignment outside of
@@ -252,6 +255,7 @@ int bpf_fd_reuseport_array_update_elem(struct bpf_map *map, void *key,
        struct sock *free_osk = NULL, *osk, *nsk;
        struct sock_reuseport *reuse;
        u32 index = *(u32 *)key;
+       uintptr_t sk_user_data;
        struct socket *socket;
        int err, fd;
 
@@ -305,7 +309,9 @@ int bpf_fd_reuseport_array_update_elem(struct bpf_map *map, void *key,
        if (err)
                goto put_file_unlock;
 
-       WRITE_ONCE(nsk->sk_user_data, &array->ptrs[index]);
+       sk_user_data = (uintptr_t)&array->ptrs[index] | SK_USER_DATA_NOCOPY |
+               SK_USER_DATA_BPF;
+       WRITE_ONCE(nsk->sk_user_data, (void *)sk_user_data);
        rcu_assign_pointer(array->ptrs[index], nsk);
        free_osk = osk;
        err = 0;
index 180414b..0af88bb 100644 (file)
@@ -132,15 +132,6 @@ static struct bpf_ringbuf *bpf_ringbuf_alloc(size_t data_sz, int numa_node)
 {
        struct bpf_ringbuf *rb;
 
-       if (!data_sz || !PAGE_ALIGNED(data_sz))
-               return ERR_PTR(-EINVAL);
-
-#ifdef CONFIG_64BIT
-       /* on 32-bit arch, it's impossible to overflow record's hdr->pgoff */
-       if (data_sz > RINGBUF_MAX_DATA_SZ)
-               return ERR_PTR(-E2BIG);
-#endif
-
        rb = bpf_ringbuf_area_alloc(data_sz, numa_node);
        if (!rb)
                return ERR_PTR(-ENOMEM);
@@ -166,9 +157,16 @@ static struct bpf_map *ringbuf_map_alloc(union bpf_attr *attr)
                return ERR_PTR(-EINVAL);
 
        if (attr->key_size || attr->value_size ||
-           attr->max_entries == 0 || !PAGE_ALIGNED(attr->max_entries))
+           !is_power_of_2(attr->max_entries) ||
+           !PAGE_ALIGNED(attr->max_entries))
                return ERR_PTR(-EINVAL);
 
+#ifdef CONFIG_64BIT
+       /* on 32-bit arch, it's impossible to overflow record's hdr->pgoff */
+       if (attr->max_entries > RINGBUF_MAX_DATA_SZ)
+               return ERR_PTR(-E2BIG);
+#endif
+
        rb_map = kzalloc(sizeof(*rb_map), GFP_USER);
        if (!rb_map)
                return ERR_PTR(-ENOMEM);
index 8da1599..0fd80ac 100644 (file)
@@ -2121,7 +2121,7 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)
            !bpf_capable())
                return -EPERM;
 
-       if (is_net_admin_prog_type(type) && !capable(CAP_NET_ADMIN))
+       if (is_net_admin_prog_type(type) && !capable(CAP_NET_ADMIN) && !capable(CAP_SYS_ADMIN))
                return -EPERM;
        if (is_perfmon_prog_type(type) && !perfmon_capable())
                return -EPERM;
@@ -2893,13 +2893,11 @@ static int bpf_prog_detach(const union bpf_attr *attr)
        switch (ptype) {
        case BPF_PROG_TYPE_SK_MSG:
        case BPF_PROG_TYPE_SK_SKB:
-               return sock_map_get_from_fd(attr, NULL);
+               return sock_map_prog_detach(attr, ptype);
        case BPF_PROG_TYPE_LIRC_MODE2:
                return lirc_prog_detach(attr);
        case BPF_PROG_TYPE_FLOW_DISSECTOR:
-               if (!capable(CAP_NET_ADMIN))
-                       return -EPERM;
-               return netns_bpf_prog_detach(attr);
+               return netns_bpf_prog_detach(attr, ptype);
        case BPF_PROG_TYPE_CGROUP_DEVICE:
        case BPF_PROG_TYPE_CGROUP_SKB:
        case BPF_PROG_TYPE_CGROUP_SOCK:
@@ -3139,7 +3137,8 @@ static const struct bpf_map *bpf_map_from_imm(const struct bpf_prog *prog,
        return NULL;
 }
 
-static struct bpf_insn *bpf_insn_prepare_dump(const struct bpf_prog *prog)
+static struct bpf_insn *bpf_insn_prepare_dump(const struct bpf_prog *prog,
+                                             const struct cred *f_cred)
 {
        const struct bpf_map *map;
        struct bpf_insn *insns;
@@ -3165,7 +3164,7 @@ static struct bpf_insn *bpf_insn_prepare_dump(const struct bpf_prog *prog)
                    code == (BPF_JMP | BPF_CALL_ARGS)) {
                        if (code == (BPF_JMP | BPF_CALL_ARGS))
                                insns[i].code = BPF_JMP | BPF_CALL;
-                       if (!bpf_dump_raw_ok())
+                       if (!bpf_dump_raw_ok(f_cred))
                                insns[i].imm = 0;
                        continue;
                }
@@ -3221,7 +3220,8 @@ static int set_info_rec_size(struct bpf_prog_info *info)
        return 0;
 }
 
-static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
+static int bpf_prog_get_info_by_fd(struct file *file,
+                                  struct bpf_prog *prog,
                                   const union bpf_attr *attr,
                                   union bpf_attr __user *uattr)
 {
@@ -3290,11 +3290,11 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
                struct bpf_insn *insns_sanitized;
                bool fault;
 
-               if (prog->blinded && !bpf_dump_raw_ok()) {
+               if (prog->blinded && !bpf_dump_raw_ok(file->f_cred)) {
                        info.xlated_prog_insns = 0;
                        goto done;
                }
-               insns_sanitized = bpf_insn_prepare_dump(prog);
+               insns_sanitized = bpf_insn_prepare_dump(prog, file->f_cred);
                if (!insns_sanitized)
                        return -ENOMEM;
                uinsns = u64_to_user_ptr(info.xlated_prog_insns);
@@ -3328,7 +3328,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
        }
 
        if (info.jited_prog_len && ulen) {
-               if (bpf_dump_raw_ok()) {
+               if (bpf_dump_raw_ok(file->f_cred)) {
                        uinsns = u64_to_user_ptr(info.jited_prog_insns);
                        ulen = min_t(u32, info.jited_prog_len, ulen);
 
@@ -3363,7 +3363,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
        ulen = info.nr_jited_ksyms;
        info.nr_jited_ksyms = prog->aux->func_cnt ? : 1;
        if (ulen) {
-               if (bpf_dump_raw_ok()) {
+               if (bpf_dump_raw_ok(file->f_cred)) {
                        unsigned long ksym_addr;
                        u64 __user *user_ksyms;
                        u32 i;
@@ -3394,7 +3394,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
        ulen = info.nr_jited_func_lens;
        info.nr_jited_func_lens = prog->aux->func_cnt ? : 1;
        if (ulen) {
-               if (bpf_dump_raw_ok()) {
+               if (bpf_dump_raw_ok(file->f_cred)) {
                        u32 __user *user_lens;
                        u32 func_len, i;
 
@@ -3451,7 +3451,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
        else
                info.nr_jited_line_info = 0;
        if (info.nr_jited_line_info && ulen) {
-               if (bpf_dump_raw_ok()) {
+               if (bpf_dump_raw_ok(file->f_cred)) {
                        __u64 __user *user_linfo;
                        u32 i;
 
@@ -3497,7 +3497,8 @@ done:
        return 0;
 }
 
-static int bpf_map_get_info_by_fd(struct bpf_map *map,
+static int bpf_map_get_info_by_fd(struct file *file,
+                                 struct bpf_map *map,
                                  const union bpf_attr *attr,
                                  union bpf_attr __user *uattr)
 {
@@ -3540,7 +3541,8 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map,
        return 0;
 }
 
-static int bpf_btf_get_info_by_fd(struct btf *btf,
+static int bpf_btf_get_info_by_fd(struct file *file,
+                                 struct btf *btf,
                                  const union bpf_attr *attr,
                                  union bpf_attr __user *uattr)
 {
@@ -3555,7 +3557,8 @@ static int bpf_btf_get_info_by_fd(struct btf *btf,
        return btf_get_info_by_fd(btf, attr, uattr);
 }
 
-static int bpf_link_get_info_by_fd(struct bpf_link *link,
+static int bpf_link_get_info_by_fd(struct file *file,
+                                 struct bpf_link *link,
                                  const union bpf_attr *attr,
                                  union bpf_attr __user *uattr)
 {
@@ -3608,15 +3611,15 @@ static int bpf_obj_get_info_by_fd(const union bpf_attr *attr,
                return -EBADFD;
 
        if (f.file->f_op == &bpf_prog_fops)
-               err = bpf_prog_get_info_by_fd(f.file->private_data, attr,
+               err = bpf_prog_get_info_by_fd(f.file, f.file->private_data, attr,
                                              uattr);
        else if (f.file->f_op == &bpf_map_fops)
-               err = bpf_map_get_info_by_fd(f.file->private_data, attr,
+               err = bpf_map_get_info_by_fd(f.file, f.file->private_data, attr,
                                             uattr);
        else if (f.file->f_op == &btf_fops)
-               err = bpf_btf_get_info_by_fd(f.file->private_data, attr, uattr);
+               err = bpf_btf_get_info_by_fd(f.file, f.file->private_data, attr, uattr);
        else if (f.file->f_op == &bpf_link_fops)
-               err = bpf_link_get_info_by_fd(f.file->private_data,
+               err = bpf_link_get_info_by_fd(f.file, f.file->private_data,
                                              attr, uattr);
        else
                err = -EINVAL;
index 34cde84..94cead5 100644 (file)
@@ -399,8 +399,7 @@ static bool reg_type_not_null(enum bpf_reg_type type)
        return type == PTR_TO_SOCKET ||
                type == PTR_TO_TCP_SOCK ||
                type == PTR_TO_MAP_VALUE ||
-               type == PTR_TO_SOCK_COMMON ||
-               type == PTR_TO_BTF_ID;
+               type == PTR_TO_SOCK_COMMON;
 }
 
 static bool reg_type_may_be_null(enum bpf_reg_type type)
@@ -9801,7 +9800,7 @@ static int jit_subprogs(struct bpf_verifier_env *env)
        int i, j, subprog_start, subprog_end = 0, len, subprog;
        struct bpf_insn *insn;
        void *old_bpf_func;
-       int err;
+       int err, num_exentries;
 
        if (env->subprog_cnt <= 1)
                return 0;
@@ -9876,6 +9875,14 @@ static int jit_subprogs(struct bpf_verifier_env *env)
                func[i]->aux->nr_linfo = prog->aux->nr_linfo;
                func[i]->aux->jited_linfo = prog->aux->jited_linfo;
                func[i]->aux->linfo_idx = env->subprog_info[i].linfo_idx;
+               num_exentries = 0;
+               insn = func[i]->insnsi;
+               for (j = 0; j < func[i]->len; j++, insn++) {
+                       if (BPF_CLASS(insn->code) == BPF_LDX &&
+                           BPF_MODE(insn->code) == BPF_PROBE_MEM)
+                               num_exentries++;
+               }
+               func[i]->aux->num_exentries = num_exentries;
                func[i] = bpf_int_jit_compile(func[i]);
                if (!func[i]->jited) {
                        err = -ENOTSUPP;
index 1ea181a..dd24774 100644 (file)
@@ -6439,18 +6439,8 @@ void cgroup_sk_alloc_disable(void)
 
 void cgroup_sk_alloc(struct sock_cgroup_data *skcd)
 {
-       if (cgroup_sk_alloc_disabled)
-               return;
-
-       /* Socket clone path */
-       if (skcd->val) {
-               /*
-                * We might be cloning a socket which is left in an empty
-                * cgroup and the cgroup might have already been rmdir'd.
-                * Don't use cgroup_get_live().
-                */
-               cgroup_get(sock_cgroup_ptr(skcd));
-               cgroup_bpf_get(sock_cgroup_ptr(skcd));
+       if (cgroup_sk_alloc_disabled) {
+               skcd->no_refcnt = 1;
                return;
        }
 
@@ -6475,10 +6465,27 @@ void cgroup_sk_alloc(struct sock_cgroup_data *skcd)
        rcu_read_unlock();
 }
 
+void cgroup_sk_clone(struct sock_cgroup_data *skcd)
+{
+       if (skcd->val) {
+               if (skcd->no_refcnt)
+                       return;
+               /*
+                * We might be cloning a socket which is left in an empty
+                * cgroup and the cgroup might have already been rmdir'd.
+                * Don't use cgroup_get_live().
+                */
+               cgroup_get(sock_cgroup_ptr(skcd));
+               cgroup_bpf_get(sock_cgroup_ptr(skcd));
+       }
+}
+
 void cgroup_sk_free(struct sock_cgroup_data *skcd)
 {
        struct cgroup *cgrp = sock_cgroup_ptr(skcd);
 
+       if (skcd->no_refcnt)
+               return;
        cgroup_bpf_put(cgrp);
        cgroup_put(cgrp);
 }
index ccc0f98..9e59347 100644 (file)
@@ -169,18 +169,18 @@ int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
 {
        int err;
 
-       err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
+       err = copy_from_kernel_nofault(bpt->saved_instr, (char *)bpt->bpt_addr,
                                BREAK_INSTR_SIZE);
        if (err)
                return err;
-       err = probe_kernel_write((char *)bpt->bpt_addr,
+       err = copy_to_kernel_nofault((char *)bpt->bpt_addr,
                                 arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
        return err;
 }
 
 int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
 {
-       return probe_kernel_write((char *)bpt->bpt_addr,
+       return copy_to_kernel_nofault((char *)bpt->bpt_addr,
                                  (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
 }
 
@@ -587,6 +587,7 @@ static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs,
                arch_kgdb_ops.disable_hw_break(regs);
 
 acquirelock:
+       rcu_read_lock();
        /*
         * Interrupts will be restored by the 'trap return' code, except when
         * single stepping.
@@ -646,6 +647,7 @@ return_normal:
                        atomic_dec(&slaves_in_kgdb);
                        dbg_touch_watchdogs();
                        local_irq_restore(flags);
+                       rcu_read_unlock();
                        return 0;
                }
                cpu_relax();
@@ -664,6 +666,7 @@ return_normal:
                raw_spin_unlock(&dbg_master_lock);
                dbg_touch_watchdogs();
                local_irq_restore(flags);
+               rcu_read_unlock();
 
                goto acquirelock;
        }
@@ -787,6 +790,7 @@ kgdb_restore:
        raw_spin_unlock(&dbg_master_lock);
        dbg_touch_watchdogs();
        local_irq_restore(flags);
+       rcu_read_unlock();
 
        return kgdb_info[cpu].ret_state;
 }
index 4b280fc..a790026 100644 (file)
@@ -247,7 +247,7 @@ char *kgdb_mem2hex(char *mem, char *buf, int count)
         */
        tmp = buf + count;
 
-       err = probe_kernel_read(tmp, mem, count);
+       err = copy_from_kernel_nofault(tmp, mem, count);
        if (err)
                return NULL;
        while (count > 0) {
@@ -283,7 +283,7 @@ int kgdb_hex2mem(char *buf, char *mem, int count)
                *tmp_raw |= hex_to_bin(*tmp_hex--) << 4;
        }
 
-       return probe_kernel_write(mem, tmp_raw, count);
+       return copy_to_kernel_nofault(mem, tmp_raw, count);
 }
 
 /*
@@ -335,7 +335,7 @@ static int kgdb_ebin2mem(char *buf, char *mem, int count)
                size++;
        }
 
-       return probe_kernel_write(mem, c, size);
+       return copy_to_kernel_nofault(mem, c, size);
 }
 
 #if DBG_MAX_REG_NUM > 0
@@ -792,6 +792,19 @@ static void gdb_cmd_query(struct kgdb_state *ks)
                }
                break;
 #endif
+#ifdef CONFIG_HAVE_ARCH_KGDB_QXFER_PKT
+       case 'S':
+               if (!strncmp(remcom_in_buffer, "qSupported:", 11))
+                       strcpy(remcom_out_buffer, kgdb_arch_gdb_stub_feature);
+               break;
+       case 'X':
+               if (!strncmp(remcom_in_buffer, "qXfer:", 6))
+                       kgdb_arch_handle_qxfer_pkt(remcom_in_buffer,
+                                                  remcom_out_buffer);
+               break;
+#endif
+       default:
+               break;
        }
 }
 
index 924bc92..683a799 100644 (file)
@@ -542,6 +542,44 @@ static int kdb_search_string(char *searched, char *searchfor)
        return 0;
 }
 
+static void kdb_msg_write(const char *msg, int msg_len)
+{
+       struct console *c;
+
+       if (msg_len == 0)
+               return;
+
+       if (dbg_io_ops) {
+               const char *cp = msg;
+               int len = msg_len;
+
+               while (len--) {
+                       dbg_io_ops->write_char(*cp);
+                       cp++;
+               }
+       }
+
+       for_each_console(c) {
+               if (!(c->flags & CON_ENABLED))
+                       continue;
+               if (c == dbg_io_ops->cons)
+                       continue;
+               /*
+                * Set oops_in_progress to encourage the console drivers to
+                * disregard their internal spin locks: in the current calling
+                * context the risk of deadlock is a bigger problem than risks
+                * due to re-entering the console driver. We operate directly on
+                * oops_in_progress rather than using bust_spinlocks() because
+                * the calls bust_spinlocks() makes on exit are not appropriate
+                * for this calling context.
+                */
+               ++oops_in_progress;
+               c->write(c, msg, msg_len);
+               --oops_in_progress;
+               touch_nmi_watchdog();
+       }
+}
+
 int vkdb_printf(enum kdb_msgsrc src, const char *fmt, va_list ap)
 {
        int diag;
@@ -553,7 +591,6 @@ int vkdb_printf(enum kdb_msgsrc src, const char *fmt, va_list ap)
        int this_cpu, old_cpu;
        char *cp, *cp2, *cphold = NULL, replaced_byte = ' ';
        char *moreprompt = "more> ";
-       struct console *c;
        unsigned long uninitialized_var(flags);
 
        /* Serialize kdb_printf if multiple cpus try to write at once.
@@ -687,22 +724,11 @@ kdb_printit:
         */
        retlen = strlen(kdb_buffer);
        cp = (char *) printk_skip_headers(kdb_buffer);
-       if (!dbg_kdb_mode && kgdb_connected) {
+       if (!dbg_kdb_mode && kgdb_connected)
                gdbstub_msg_write(cp, retlen - (cp - kdb_buffer));
-       } else {
-               if (dbg_io_ops && !dbg_io_ops->is_console) {
-                       len = retlen - (cp - kdb_buffer);
-                       cp2 = cp;
-                       while (len--) {
-                               dbg_io_ops->write_char(*cp2);
-                               cp2++;
-                       }
-               }
-               for_each_console(c) {
-                       c->write(c, cp, retlen - (cp - kdb_buffer));
-                       touch_nmi_watchdog();
-               }
-       }
+       else
+               kdb_msg_write(cp, retlen - (cp - kdb_buffer));
+
        if (logging) {
                saved_loglevel = console_loglevel;
                console_loglevel = CONSOLE_LOGLEVEL_SILENT;
@@ -751,19 +777,7 @@ kdb_printit:
                        moreprompt = "more> ";
 
                kdb_input_flush();
-
-               if (dbg_io_ops && !dbg_io_ops->is_console) {
-                       len = strlen(moreprompt);
-                       cp = moreprompt;
-                       while (len--) {
-                               dbg_io_ops->write_char(*cp);
-                               cp++;
-                       }
-               }
-               for_each_console(c) {
-                       c->write(c, moreprompt, strlen(moreprompt));
-                       touch_nmi_watchdog();
-               }
+               kdb_msg_write(moreprompt, strlen(moreprompt));
 
                if (logging)
                        printk("%s", moreprompt);
index ec19056..5c79490 100644 (file)
@@ -2326,7 +2326,8 @@ void kdb_ps1(const struct task_struct *p)
        int cpu;
        unsigned long tmp;
 
-       if (!p || probe_kernel_read(&tmp, (char *)p, sizeof(unsigned long)))
+       if (!p ||
+           copy_from_kernel_nofault(&tmp, (char *)p, sizeof(unsigned long)))
                return;
 
        cpu = kdb_process_cpu(p);
index b8e6306..004c5b6 100644 (file)
@@ -325,7 +325,7 @@ char *kdb_strdup(const char *str, gfp_t type)
  */
 int kdb_getarea_size(void *res, unsigned long addr, size_t size)
 {
-       int ret = probe_kernel_read((char *)res, (char *)addr, size);
+       int ret = copy_from_kernel_nofault((char *)res, (char *)addr, size);
        if (ret) {
                if (!KDB_STATE(SUPPRESS)) {
                        kdb_printf("kdb_getarea: Bad address 0x%lx\n", addr);
@@ -350,7 +350,7 @@ int kdb_getarea_size(void *res, unsigned long addr, size_t size)
  */
 int kdb_putarea_size(unsigned long addr, void *res, size_t size)
 {
-       int ret = probe_kernel_read((char *)addr, (char *)res, size);
+       int ret = copy_from_kernel_nofault((char *)addr, (char *)res, size);
        if (ret) {
                if (!KDB_STATE(SUPPRESS)) {
                        kdb_printf("kdb_putarea: Bad address 0x%lx\n", addr);
@@ -624,7 +624,8 @@ char kdb_task_state_char (const struct task_struct *p)
        char state;
        unsigned long tmp;
 
-       if (!p || probe_kernel_read(&tmp, (char *)p, sizeof(unsigned long)))
+       if (!p ||
+           copy_from_kernel_nofault(&tmp, (char *)p, sizeof(unsigned long)))
                return 'E';
 
        cpu = kdb_process_cpu(p);
index d006668..1da3f44 100644 (file)
@@ -71,20 +71,21 @@ config SWIOTLB
 # in the pagetables
 #
 config DMA_NONCOHERENT_MMAP
+       default y if !MMU
        bool
 
-config DMA_REMAP
-       depends on MMU
+config DMA_COHERENT_POOL
        select GENERIC_ALLOCATOR
-       select DMA_NONCOHERENT_MMAP
        bool
 
-config DMA_COHERENT_POOL
+config DMA_REMAP
        bool
-       select DMA_REMAP
+       depends on MMU
+       select DMA_NONCOHERENT_MMAP
 
 config DMA_DIRECT_REMAP
        bool
+       select DMA_REMAP
        select DMA_COHERENT_POOL
 
 config DMA_CMA
index 0a4881e..67f060b 100644 (file)
@@ -70,7 +70,7 @@ gfp_t dma_direct_optimal_gfp_mask(struct device *dev, u64 dma_mask,
        return 0;
 }
 
-static bool dma_coherent_ok(struct device *dev, phys_addr_t phys, size_t size)
+bool dma_coherent_ok(struct device *dev, phys_addr_t phys, size_t size)
 {
        return phys_to_dma_direct(dev, phys) + size - 1 <=
                        min_not_zero(dev->coherent_dma_mask, dev->bus_dma_limit);
@@ -109,14 +109,15 @@ static inline bool dma_should_free_from_pool(struct device *dev,
        return false;
 }
 
-struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
+static struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
                gfp_t gfp, unsigned long attrs)
 {
-       size_t alloc_size = PAGE_ALIGN(size);
        int node = dev_to_node(dev);
        struct page *page = NULL;
        u64 phys_limit;
 
+       WARN_ON_ONCE(!PAGE_ALIGNED(size));
+
        if (attrs & DMA_ATTR_NO_WARN)
                gfp |= __GFP_NOWARN;
 
@@ -124,14 +125,14 @@ struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
        gfp &= ~__GFP_ZERO;
        gfp |= dma_direct_optimal_gfp_mask(dev, dev->coherent_dma_mask,
                                           &phys_limit);
-       page = dma_alloc_contiguous(dev, alloc_size, gfp);
+       page = dma_alloc_contiguous(dev, size, gfp);
        if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
-               dma_free_contiguous(dev, page, alloc_size);
+               dma_free_contiguous(dev, page, size);
                page = NULL;
        }
 again:
        if (!page)
-               page = alloc_pages_node(node, gfp, get_order(alloc_size));
+               page = alloc_pages_node(node, gfp, get_order(size));
        if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
                dma_free_contiguous(dev, page, size);
                page = NULL;
@@ -157,9 +158,12 @@ void *dma_direct_alloc_pages(struct device *dev, size_t size,
 {
        struct page *page;
        void *ret;
+       int err;
+
+       size = PAGE_ALIGN(size);
 
        if (dma_should_alloc_from_pool(dev, gfp, attrs)) {
-               ret = dma_alloc_from_pool(dev, PAGE_ALIGN(size), &page, gfp);
+               ret = dma_alloc_from_pool(dev, size, &page, gfp);
                if (!ret)
                        return NULL;
                goto done;
@@ -183,14 +187,20 @@ void *dma_direct_alloc_pages(struct device *dev, size_t size,
             dma_alloc_need_uncached(dev, attrs)) ||
            (IS_ENABLED(CONFIG_DMA_REMAP) && PageHighMem(page))) {
                /* remove any dirty cache lines on the kernel alias */
-               arch_dma_prep_coherent(page, PAGE_ALIGN(size));
+               arch_dma_prep_coherent(page, size);
 
                /* create a coherent mapping */
-               ret = dma_common_contiguous_remap(page, PAGE_ALIGN(size),
+               ret = dma_common_contiguous_remap(page, size,
                                dma_pgprot(dev, PAGE_KERNEL, attrs),
                                __builtin_return_address(0));
                if (!ret)
                        goto out_free_pages;
+               if (force_dma_unencrypted(dev)) {
+                       err = set_memory_decrypted((unsigned long)ret,
+                                                  1 << get_order(size));
+                       if (err)
+                               goto out_free_pages;
+               }
                memset(ret, 0, size);
                goto done;
        }
@@ -207,8 +217,12 @@ void *dma_direct_alloc_pages(struct device *dev, size_t size,
        }
 
        ret = page_address(page);
-       if (force_dma_unencrypted(dev))
-               set_memory_decrypted((unsigned long)ret, 1 << get_order(size));
+       if (force_dma_unencrypted(dev)) {
+               err = set_memory_decrypted((unsigned long)ret,
+                                          1 << get_order(size));
+               if (err)
+                       goto out_free_pages;
+       }
 
        memset(ret, 0, size);
 
@@ -217,7 +231,7 @@ void *dma_direct_alloc_pages(struct device *dev, size_t size,
                arch_dma_prep_coherent(page, size);
                ret = arch_dma_set_uncached(ret, size);
                if (IS_ERR(ret))
-                       goto out_free_pages;
+                       goto out_encrypt_pages;
        }
 done:
        if (force_dma_unencrypted(dev))
@@ -225,6 +239,15 @@ done:
        else
                *dma_handle = phys_to_dma(dev, page_to_phys(page));
        return ret;
+
+out_encrypt_pages:
+       if (force_dma_unencrypted(dev)) {
+               err = set_memory_encrypted((unsigned long)page_address(page),
+                                          1 << get_order(size));
+               /* If memory cannot be re-encrypted, it must be leaked */
+               if (err)
+                       return NULL;
+       }
 out_free_pages:
        dma_free_contiguous(dev, page, size);
        return NULL;
@@ -459,7 +482,6 @@ int dma_direct_get_sgtable(struct device *dev, struct sg_table *sgt,
        return ret;
 }
 
-#ifdef CONFIG_MMU
 bool dma_direct_can_mmap(struct device *dev)
 {
        return dev_is_dma_coherent(dev) ||
@@ -485,19 +507,6 @@ int dma_direct_mmap(struct device *dev, struct vm_area_struct *vma,
        return remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff,
                        user_count << PAGE_SHIFT, vma->vm_page_prot);
 }
-#else /* CONFIG_MMU */
-bool dma_direct_can_mmap(struct device *dev)
-{
-       return false;
-}
-
-int dma_direct_mmap(struct device *dev, struct vm_area_struct *vma,
-               void *cpu_addr, dma_addr_t dma_addr, size_t size,
-               unsigned long attrs)
-{
-       return -ENXIO;
-}
-#endif /* CONFIG_MMU */
 
 int dma_direct_supported(struct device *dev, u64 mask)
 {
@@ -530,3 +539,9 @@ size_t dma_direct_max_mapping_size(struct device *dev)
                return swiotlb_max_mapping_size(dev);
        return SIZE_MAX;
 }
+
+bool dma_direct_need_sync(struct device *dev, dma_addr_t dma_addr)
+{
+       return !dev_is_dma_coherent(dev) ||
+               is_swiotlb_buffer(dma_to_phys(dev, dma_addr));
+}
index 98e3d87..a8c18c9 100644 (file)
@@ -397,6 +397,16 @@ size_t dma_max_mapping_size(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(dma_max_mapping_size);
 
+bool dma_need_sync(struct device *dev, dma_addr_t dma_addr)
+{
+       const struct dma_map_ops *ops = get_dma_ops(dev);
+
+       if (dma_is_direct(ops))
+               return dma_direct_need_sync(dev, dma_addr);
+       return ops->sync_single_for_cpu || ops->sync_single_for_device;
+}
+EXPORT_SYMBOL_GPL(dma_need_sync);
+
 unsigned long dma_get_merge_boundary(struct device *dev)
 {
        const struct dma_map_ops *ops = get_dma_ops(dev);
index 35bb51c..6bc74a2 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/debugfs.h>
 #include <linux/dma-direct.h>
 #include <linux/dma-noncoherent.h>
-#include <linux/dma-contiguous.h>
 #include <linux/init.h>
 #include <linux/genalloc.h>
 #include <linux/set_memory.h>
@@ -69,12 +68,7 @@ static int atomic_pool_expand(struct gen_pool *pool, size_t pool_size,
 
        do {
                pool_size = 1 << (PAGE_SHIFT + order);
-
-               if (dev_get_cma_area(NULL))
-                       page = dma_alloc_from_contiguous(NULL, 1 << order,
-                                                        order, false);
-               else
-                       page = alloc_pages(gfp, order);
+               page = alloc_pages(gfp, order);
        } while (!page && order-- > 0);
        if (!page)
                goto out;
@@ -118,8 +112,7 @@ remove_mapping:
        dma_common_free_remap(addr, pool_size);
 #endif
 free_page: __maybe_unused
-       if (!dma_release_from_contiguous(NULL, page, 1 << order))
-               __free_pages(page, order);
+       __free_pages(page, order);
 out:
        return ret;
 }
@@ -175,10 +168,9 @@ static int __init dma_atomic_pool_init(void)
         * sizes to 128KB per 1GB of memory, min 128KB, max MAX_ORDER-1.
         */
        if (!atomic_pool_size) {
-               atomic_pool_size = max(totalram_pages() >> PAGE_SHIFT, 1UL) *
-                                       SZ_128K;
-               atomic_pool_size = min_t(size_t, atomic_pool_size,
-                                        1 << (PAGE_SHIFT + MAX_ORDER-1));
+               unsigned long pages = totalram_pages() / (SZ_1G / SZ_128K);
+               pages = min_t(unsigned long, pages, MAX_ORDER_NR_PAGES);
+               atomic_pool_size = max_t(size_t, pages << PAGE_SHIFT, SZ_128K);
        }
        INIT_WORK(&atomic_pool_work, atomic_pool_work_fn);
 
@@ -204,7 +196,7 @@ static int __init dma_atomic_pool_init(void)
 }
 postcore_initcall(dma_atomic_pool_init);
 
-static inline struct gen_pool *dev_to_pool(struct device *dev)
+static inline struct gen_pool *dma_guess_pool_from_device(struct device *dev)
 {
        u64 phys_mask;
        gfp_t gfp;
@@ -218,47 +210,79 @@ static inline struct gen_pool *dev_to_pool(struct device *dev)
        return atomic_pool_kernel;
 }
 
-static bool dma_in_atomic_pool(struct device *dev, void *start, size_t size)
+static inline struct gen_pool *dma_get_safer_pool(struct gen_pool *bad_pool)
+{
+       if (bad_pool == atomic_pool_kernel)
+               return atomic_pool_dma32 ? : atomic_pool_dma;
+
+       if (bad_pool == atomic_pool_dma32)
+               return atomic_pool_dma;
+
+       return NULL;
+}
+
+static inline struct gen_pool *dma_guess_pool(struct device *dev,
+                                             struct gen_pool *bad_pool)
 {
-       struct gen_pool *pool = dev_to_pool(dev);
+       if (bad_pool)
+               return dma_get_safer_pool(bad_pool);
 
-       if (unlikely(!pool))
-               return false;
-       return gen_pool_has_addr(pool, (unsigned long)start, size);
+       return dma_guess_pool_from_device(dev);
 }
 
 void *dma_alloc_from_pool(struct device *dev, size_t size,
                          struct page **ret_page, gfp_t flags)
 {
-       struct gen_pool *pool = dev_to_pool(dev);
-       unsigned long val;
+       struct gen_pool *pool = NULL;
+       unsigned long val = 0;
        void *ptr = NULL;
-
-       if (!pool) {
-               WARN(1, "%pGg atomic pool not initialised!\n", &flags);
-               return NULL;
+       phys_addr_t phys;
+
+       while (1) {
+               pool = dma_guess_pool(dev, pool);
+               if (!pool) {
+                       WARN(1, "Failed to get suitable pool for %s\n",
+                            dev_name(dev));
+                       break;
+               }
+
+               val = gen_pool_alloc(pool, size);
+               if (!val)
+                       continue;
+
+               phys = gen_pool_virt_to_phys(pool, val);
+               if (dma_coherent_ok(dev, phys, size))
+                       break;
+
+               gen_pool_free(pool, val, size);
+               val = 0;
        }
 
-       val = gen_pool_alloc(pool, size);
-       if (val) {
-               phys_addr_t phys = gen_pool_virt_to_phys(pool, val);
 
+       if (val) {
                *ret_page = pfn_to_page(__phys_to_pfn(phys));
                ptr = (void *)val;
                memset(ptr, 0, size);
+
+               if (gen_pool_avail(pool) < atomic_pool_size)
+                       schedule_work(&atomic_pool_work);
        }
-       if (gen_pool_avail(pool) < atomic_pool_size)
-               schedule_work(&atomic_pool_work);
 
        return ptr;
 }
 
 bool dma_free_from_pool(struct device *dev, void *start, size_t size)
 {
-       struct gen_pool *pool = dev_to_pool(dev);
+       struct gen_pool *pool = NULL;
+
+       while (1) {
+               pool = dma_guess_pool(dev, pool);
+               if (!pool)
+                       return false;
 
-       if (!dma_in_atomic_pool(dev, start, size))
-               return false;
-       gen_pool_free(pool, (unsigned long)start, size);
-       return true;
+               if (gen_pool_has_addr(pool, (unsigned long)start, size)) {
+                       gen_pool_free(pool, (unsigned long)start, size);
+                       return true;
+               }
+       }
 }
index e739a6e..78b23f0 100644 (file)
@@ -24,7 +24,8 @@ void *dma_common_pages_remap(struct page **pages, size_t size,
 {
        void *vaddr;
 
-       vaddr = vmap(pages, size >> PAGE_SHIFT, VM_DMA_COHERENT, prot);
+       vaddr = vmap(pages, PAGE_ALIGN(size) >> PAGE_SHIFT,
+                    VM_DMA_COHERENT, prot);
        if (vaddr)
                find_vm_area(vaddr)->pages = pages;
        return vaddr;
@@ -37,7 +38,7 @@ void *dma_common_pages_remap(struct page **pages, size_t size,
 void *dma_common_contiguous_remap(struct page *page, size_t size,
                        pgprot_t prot, const void *caller)
 {
-       int count = size >> PAGE_SHIFT;
+       int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
        struct page **pages;
        void *vaddr;
        int i;
index bb08628..5f8b0c5 100644 (file)
@@ -2199,7 +2199,7 @@ static void handle_swbp(struct pt_regs *regs)
        if (!uprobe) {
                if (is_swbp > 0) {
                        /* No matching uprobe; signal SIGTRAP. */
-                       send_sig(SIGTRAP, current, 0);
+                       force_sig(SIGTRAP);
                } else {
                        /*
                         * Either we raced with uprobe_unregister() or we can't
index 142b236..efc5493 100644 (file)
@@ -1977,7 +1977,7 @@ static __latent_entropy struct task_struct *copy_process(
         * to stop root fork bombs.
         */
        retval = -EAGAIN;
-       if (nr_threads >= max_threads)
+       if (data_race(nr_threads >= max_threads))
                goto bad_fork_cleanup_count;
 
        delayacct_tsk_init(p);  /* Must remain after dup_task_struct() */
index 7619111..2a9fec5 100644 (file)
@@ -195,9 +195,9 @@ void irq_set_thread_affinity(struct irq_desc *desc)
                        set_bit(IRQTF_AFFINITY, &action->thread_flags);
 }
 
+#ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK
 static void irq_validate_effective_affinity(struct irq_data *data)
 {
-#ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK
        const struct cpumask *m = irq_data_get_effective_affinity_mask(data);
        struct irq_chip *chip = irq_data_get_irq_chip(data);
 
@@ -205,9 +205,19 @@ static void irq_validate_effective_affinity(struct irq_data *data)
                return;
        pr_warn_once("irq_chip %s did not update eff. affinity mask of irq %u\n",
                     chip->name, data->irq);
-#endif
 }
 
+static inline void irq_init_effective_affinity(struct irq_data *data,
+                                              const struct cpumask *mask)
+{
+       cpumask_copy(irq_data_get_effective_affinity_mask(data), mask);
+}
+#else
+static inline void irq_validate_effective_affinity(struct irq_data *data) { }
+static inline void irq_init_effective_affinity(struct irq_data *data,
+                                              const struct cpumask *mask) { }
+#endif
+
 int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask,
                        bool force)
 {
@@ -304,6 +314,26 @@ static int irq_try_set_affinity(struct irq_data *data,
        return ret;
 }
 
+static bool irq_set_affinity_deactivated(struct irq_data *data,
+                                        const struct cpumask *mask, bool force)
+{
+       struct irq_desc *desc = irq_data_to_desc(data);
+
+       /*
+        * If the interrupt is not yet activated, just store the affinity
+        * mask and do not call the chip driver at all. On activation the
+        * driver has to make sure anyway that the interrupt is in a
+        * useable state so startup works.
+        */
+       if (!IS_ENABLED(CONFIG_IRQ_DOMAIN_HIERARCHY) || irqd_is_activated(data))
+               return false;
+
+       cpumask_copy(desc->irq_common_data.affinity, mask);
+       irq_init_effective_affinity(data, mask);
+       irqd_set(data, IRQD_AFFINITY_SET);
+       return true;
+}
+
 int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask,
                            bool force)
 {
@@ -314,6 +344,9 @@ int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask,
        if (!chip || !chip->irq_set_affinity)
                return -EINVAL;
 
+       if (irq_set_affinity_deactivated(data, mask, force))
+               return 0;
+
        if (irq_can_move_pcntxt(data) && !irqd_is_setaffinity_pending(data)) {
                ret = irq_try_set_affinity(data, mask, force);
        } else {
index 16c8c60..bb14e64 100644 (file)
@@ -644,19 +644,20 @@ static inline int kallsyms_for_perf(void)
  * Otherwise, require CAP_SYSLOG (assuming kptr_restrict isn't set to
  * block even that).
  */
-int kallsyms_show_value(void)
+bool kallsyms_show_value(const struct cred *cred)
 {
        switch (kptr_restrict) {
        case 0:
                if (kallsyms_for_perf())
-                       return 1;
+                       return true;
        /* fallthrough */
        case 1:
-               if (has_capability_noaudit(current, CAP_SYSLOG))
-                       return 1;
+               if (security_capable(cred, &init_user_ns, CAP_SYSLOG,
+                                    CAP_OPT_NOAUDIT) == 0)
+                       return true;
        /* fallthrough */
        default:
-               return 0;
+               return false;
        }
 }
 
@@ -673,7 +674,11 @@ static int kallsyms_open(struct inode *inode, struct file *file)
                return -ENOMEM;
        reset_iter(iter, 0);
 
-       iter->show_value = kallsyms_show_value();
+       /*
+        * Instead of checking this on every s_show() call, cache
+        * the result here at open time.
+        */
+       iter->show_value = kallsyms_show_value(file->f_cred);
        return 0;
 }
 
index bb05fd5..09cc78d 100644 (file)
@@ -181,34 +181,19 @@ void kimage_file_post_load_cleanup(struct kimage *image)
 static int
 kimage_validate_signature(struct kimage *image)
 {
-       const char *reason;
        int ret;
 
        ret = arch_kexec_kernel_verify_sig(image, image->kernel_buf,
                                           image->kernel_buf_len);
-       switch (ret) {
-       case 0:
-               break;
+       if (ret) {
 
-               /* Certain verification errors are non-fatal if we're not
-                * checking errors, provided we aren't mandating that there
-                * must be a valid signature.
-                */
-       case -ENODATA:
-               reason = "kexec of unsigned image";
-               goto decide;
-       case -ENOPKG:
-               reason = "kexec of image with unsupported crypto";
-               goto decide;
-       case -ENOKEY:
-               reason = "kexec of image with unavailable key";
-       decide:
                if (IS_ENABLED(CONFIG_KEXEC_SIG_FORCE)) {
-                       pr_notice("%s rejected\n", reason);
+                       pr_notice("Enforced kernel signature verification failed (%d).\n", ret);
                        return ret;
                }
 
-               /* If IMA is guaranteed to appraise a signature on the kexec
+               /*
+                * If IMA is guaranteed to appraise a signature on the kexec
                 * image, permit it even if the kernel is otherwise locked
                 * down.
                 */
@@ -216,17 +201,10 @@ kimage_validate_signature(struct kimage *image)
                    security_locked_down(LOCKDOWN_KEXEC))
                        return -EPERM;
 
-               return 0;
-
-               /* All other errors are fatal, including nomem, unparseable
-                * signatures and signature check failures - even if signatures
-                * aren't required.
-                */
-       default:
-               pr_notice("kernel signature verification failed (%d).\n", ret);
+               pr_debug("kernel signature verification failed (%d).\n", ret);
        }
 
-       return ret;
+       return 0;
 }
 #endif
 
index 50cd84f..2e97feb 100644 (file)
 
 
 static int kprobes_initialized;
+/* kprobe_table can be accessed by
+ * - Normal hlist traversal and RCU add/del under kprobe_mutex is held.
+ * Or
+ * - RCU hlist traversal under disabling preempt (breakpoint handlers)
+ */
 static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
 static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
 
@@ -326,7 +331,8 @@ struct kprobe *get_kprobe(void *addr)
        struct kprobe *p;
 
        head = &kprobe_table[hash_ptr(addr, KPROBE_HASH_BITS)];
-       hlist_for_each_entry_rcu(p, head, hlist) {
+       hlist_for_each_entry_rcu(p, head, hlist,
+                                lockdep_is_held(&kprobe_mutex)) {
                if (p->addr == addr)
                        return p;
        }
@@ -586,11 +592,12 @@ static void kprobe_optimizer(struct work_struct *work)
        mutex_unlock(&module_mutex);
        mutex_unlock(&text_mutex);
        cpus_read_unlock();
-       mutex_unlock(&kprobe_mutex);
 
        /* Step 5: Kick optimizer again if needed */
        if (!list_empty(&optimizing_list) || !list_empty(&unoptimizing_list))
                kick_kprobe_optimizer();
+
+       mutex_unlock(&kprobe_mutex);
 }
 
 /* Wait for completing optimization and unoptimization */
@@ -668,8 +675,6 @@ static void force_unoptimize_kprobe(struct optimized_kprobe *op)
        lockdep_assert_cpus_held();
        arch_unoptimize_kprobe(op);
        op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED;
-       if (kprobe_disabled(&op->kp))
-               arch_disarm_kprobe(&op->kp);
 }
 
 /* Unoptimize a kprobe if p is optimized */
@@ -849,7 +854,7 @@ static void optimize_all_kprobes(void)
        kprobes_allow_optimization = true;
        for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
                head = &kprobe_table[i];
-               hlist_for_each_entry_rcu(p, head, hlist)
+               hlist_for_each_entry(p, head, hlist)
                        if (!kprobe_disabled(p))
                                optimize_kprobe(p);
        }
@@ -876,7 +881,7 @@ static void unoptimize_all_kprobes(void)
        kprobes_allow_optimization = false;
        for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
                head = &kprobe_table[i];
-               hlist_for_each_entry_rcu(p, head, hlist) {
+               hlist_for_each_entry(p, head, hlist) {
                        if (!kprobe_disabled(p))
                                unoptimize_kprobe(p, false);
                }
@@ -1236,6 +1241,26 @@ __releases(hlist_lock)
 }
 NOKPROBE_SYMBOL(kretprobe_table_unlock);
 
+struct kprobe kprobe_busy = {
+       .addr = (void *) get_kprobe,
+};
+
+void kprobe_busy_begin(void)
+{
+       struct kprobe_ctlblk *kcb;
+
+       preempt_disable();
+       __this_cpu_write(current_kprobe, &kprobe_busy);
+       kcb = get_kprobe_ctlblk();
+       kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+}
+
+void kprobe_busy_end(void)
+{
+       __this_cpu_write(current_kprobe, NULL);
+       preempt_enable();
+}
+
 /*
  * This function is called from finish_task_switch when task tk becomes dead,
  * so that we can recycle any function-return probe instances associated
@@ -1253,6 +1278,8 @@ void kprobe_flush_task(struct task_struct *tk)
                /* Early boot.  kretprobe_table_locks not yet initialized. */
                return;
 
+       kprobe_busy_begin();
+
        INIT_HLIST_HEAD(&empty_rp);
        hash = hash_ptr(tk, KPROBE_HASH_BITS);
        head = &kretprobe_inst_table[hash];
@@ -1266,6 +1293,8 @@ void kprobe_flush_task(struct task_struct *tk)
                hlist_del(&ri->hlist);
                kfree(ri);
        }
+
+       kprobe_busy_end();
 }
 NOKPROBE_SYMBOL(kprobe_flush_task);
 
@@ -1499,12 +1528,14 @@ static struct kprobe *__get_valid_kprobe(struct kprobe *p)
 {
        struct kprobe *ap, *list_p;
 
+       lockdep_assert_held(&kprobe_mutex);
+
        ap = get_kprobe(p->addr);
        if (unlikely(!ap))
                return NULL;
 
        if (p != ap) {
-               list_for_each_entry_rcu(list_p, &ap->list, list)
+               list_for_each_entry(list_p, &ap->list, list)
                        if (list_p == p)
                        /* kprobe p is a valid probe */
                                goto valid;
@@ -1669,7 +1700,9 @@ static int aggr_kprobe_disabled(struct kprobe *ap)
 {
        struct kprobe *kp;
 
-       list_for_each_entry_rcu(kp, &ap->list, list)
+       lockdep_assert_held(&kprobe_mutex);
+
+       list_for_each_entry(kp, &ap->list, list)
                if (!kprobe_disabled(kp))
                        /*
                         * There is an active probe on the list.
@@ -1748,7 +1781,7 @@ static int __unregister_kprobe_top(struct kprobe *p)
        else {
                /* If disabling probe has special handlers, update aggrprobe */
                if (p->post_handler && !kprobe_gone(p)) {
-                       list_for_each_entry_rcu(list_p, &ap->list, list) {
+                       list_for_each_entry(list_p, &ap->list, list) {
                                if ((list_p != p) && (list_p->post_handler))
                                        goto noclean;
                        }
@@ -2062,13 +2095,15 @@ static void kill_kprobe(struct kprobe *p)
 {
        struct kprobe *kp;
 
+       lockdep_assert_held(&kprobe_mutex);
+
        p->flags |= KPROBE_FLAG_GONE;
        if (kprobe_aggrprobe(p)) {
                /*
                 * If this is an aggr_kprobe, we have to list all the
                 * chained probes and mark them GONE.
                 */
-               list_for_each_entry_rcu(kp, &p->list, list)
+               list_for_each_entry(kp, &p->list, list)
                        kp->flags |= KPROBE_FLAG_GONE;
                p->post_handler = NULL;
                kill_optimized_kprobe(p);
@@ -2312,7 +2347,7 @@ static int kprobes_module_callback(struct notifier_block *nb,
        mutex_lock(&kprobe_mutex);
        for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
                head = &kprobe_table[i];
-               hlist_for_each_entry_rcu(p, head, hlist)
+               hlist_for_each_entry(p, head, hlist)
                        if (within_module_init((unsigned long)p->addr, mod) ||
                            (checkcore &&
                             within_module_core((unsigned long)p->addr, mod))) {
@@ -2413,7 +2448,7 @@ static void report_probe(struct seq_file *pi, struct kprobe *p,
        else
                kprobe_type = "k";
 
-       if (!kallsyms_show_value())
+       if (!kallsyms_show_value(pi->file->f_cred))
                addr = NULL;
 
        if (sym)
@@ -2505,7 +2540,7 @@ static int kprobe_blacklist_seq_show(struct seq_file *m, void *v)
         * If /proc/kallsyms is not showing kernel address, we won't
         * show them here either.
         */
-       if (!kallsyms_show_value())
+       if (!kallsyms_show_value(m->file->f_cred))
                seq_printf(m, "0x%px-0x%px\t%ps\n", NULL, NULL,
                           (void *)ent->start_addr);
        else
@@ -2550,7 +2585,7 @@ static int arm_all_kprobes(void)
        for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
                head = &kprobe_table[i];
                /* Arm all kprobes on a best-effort basis */
-               hlist_for_each_entry_rcu(p, head, hlist) {
+               hlist_for_each_entry(p, head, hlist) {
                        if (!kprobe_disabled(p)) {
                                err = arm_kprobe(p);
                                if (err)  {
@@ -2593,7 +2628,7 @@ static int disarm_all_kprobes(void)
        for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
                head = &kprobe_table[i];
                /* Disarm all kprobes on a best-effort basis */
-               hlist_for_each_entry_rcu(p, head, hlist) {
+               hlist_for_each_entry(p, head, hlist) {
                        if (!arch_trampoline_kprobe(p) && !kprobe_disabled(p)) {
                                err = disarm_kprobe(p, false);
                                if (err) {
index 8e3d2d7..132f84a 100644 (file)
@@ -201,7 +201,7 @@ void *kthread_probe_data(struct task_struct *task)
        struct kthread *kthread = to_kthread(task);
        void *data = NULL;
 
-       probe_kernel_read(&data, &kthread->data, sizeof(data));
+       copy_from_kernel_nofault(&data, &kthread->data, sizeof(data));
        return data;
 }
 
index e8a1985..aa183c9 100644 (file)
@@ -1510,8 +1510,7 @@ static inline bool sect_empty(const Elf_Shdr *sect)
 }
 
 struct module_sect_attr {
-       struct module_attribute mattr;
-       char *name;
+       struct bin_attribute battr;
        unsigned long address;
 };
 
@@ -1521,13 +1520,18 @@ struct module_sect_attrs {
        struct module_sect_attr attrs[];
 };
 
-static ssize_t module_sect_show(struct module_attribute *mattr,
-                               struct module_kobject *mk, char *buf)
+static ssize_t module_sect_read(struct file *file, struct kobject *kobj,
+                               struct bin_attribute *battr,
+                               char *buf, loff_t pos, size_t count)
 {
        struct module_sect_attr *sattr =
-               container_of(mattr, struct module_sect_attr, mattr);
-       return sprintf(buf, "0x%px\n", kptr_restrict < 2 ?
-                      (void *)sattr->address : NULL);
+               container_of(battr, struct module_sect_attr, battr);
+
+       if (pos != 0)
+               return -EINVAL;
+
+       return sprintf(buf, "0x%px\n",
+                      kallsyms_show_value(file->f_cred) ? (void *)sattr->address : NULL);
 }
 
 static void free_sect_attrs(struct module_sect_attrs *sect_attrs)
@@ -1535,7 +1539,7 @@ static void free_sect_attrs(struct module_sect_attrs *sect_attrs)
        unsigned int section;
 
        for (section = 0; section < sect_attrs->nsections; section++)
-               kfree(sect_attrs->attrs[section].name);
+               kfree(sect_attrs->attrs[section].battr.attr.name);
        kfree(sect_attrs);
 }
 
@@ -1544,42 +1548,41 @@ static void add_sect_attrs(struct module *mod, const struct load_info *info)
        unsigned int nloaded = 0, i, size[2];
        struct module_sect_attrs *sect_attrs;
        struct module_sect_attr *sattr;
-       struct attribute **gattr;
+       struct bin_attribute **gattr;
 
        /* Count loaded sections and allocate structures */
        for (i = 0; i < info->hdr->e_shnum; i++)
                if (!sect_empty(&info->sechdrs[i]))
                        nloaded++;
        size[0] = ALIGN(struct_size(sect_attrs, attrs, nloaded),
-                       sizeof(sect_attrs->grp.attrs[0]));
-       size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.attrs[0]);
+                       sizeof(sect_attrs->grp.bin_attrs[0]));
+       size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.bin_attrs[0]);
        sect_attrs = kzalloc(size[0] + size[1], GFP_KERNEL);
        if (sect_attrs == NULL)
                return;
 
        /* Setup section attributes. */
        sect_attrs->grp.name = "sections";
-       sect_attrs->grp.attrs = (void *)sect_attrs + size[0];
+       sect_attrs->grp.bin_attrs = (void *)sect_attrs + size[0];
 
        sect_attrs->nsections = 0;
        sattr = &sect_attrs->attrs[0];
-       gattr = &sect_attrs->grp.attrs[0];
+       gattr = &sect_attrs->grp.bin_attrs[0];
        for (i = 0; i < info->hdr->e_shnum; i++) {
                Elf_Shdr *sec = &info->sechdrs[i];
                if (sect_empty(sec))
                        continue;
+               sysfs_bin_attr_init(&sattr->battr);
                sattr->address = sec->sh_addr;
-               sattr->name = kstrdup(info->secstrings + sec->sh_name,
-                                       GFP_KERNEL);
-               if (sattr->name == NULL)
+               sattr->battr.attr.name =
+                       kstrdup(info->secstrings + sec->sh_name, GFP_KERNEL);
+               if (sattr->battr.attr.name == NULL)
                        goto out;
                sect_attrs->nsections++;
-               sysfs_attr_init(&sattr->mattr.attr);
-               sattr->mattr.show = module_sect_show;
-               sattr->mattr.store = NULL;
-               sattr->mattr.attr.name = sattr->name;
-               sattr->mattr.attr.mode = S_IRUSR;
-               *(gattr++) = &(sattr++)->mattr.attr;
+               sattr->battr.read = module_sect_read;
+               sattr->battr.size = 3 /* "0x", "\n" */ + (BITS_PER_LONG / 4);
+               sattr->battr.attr.mode = 0400;
+               *(gattr++) = &(sattr++)->battr;
        }
        *gattr = NULL;
 
@@ -1669,7 +1672,7 @@ static void add_notes_attrs(struct module *mod, const struct load_info *info)
                        continue;
                if (info->sechdrs[i].sh_type == SHT_NOTE) {
                        sysfs_bin_attr_init(nattr);
-                       nattr->attr.name = mod->sect_attrs->attrs[loaded].name;
+                       nattr->attr.name = mod->sect_attrs->attrs[loaded].battr.attr.name;
                        nattr->attr.mode = S_IRUGO;
                        nattr->size = info->sechdrs[i].sh_size;
                        nattr->private = (void *) info->sechdrs[i].sh_addr;
@@ -2783,7 +2786,9 @@ static void dynamic_debug_remove(struct module *mod, struct _ddebug *debug)
 
 void * __weak module_alloc(unsigned long size)
 {
-       return vmalloc_exec(size);
+       return __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END,
+                       GFP_KERNEL, PAGE_KERNEL_EXEC, VM_FLUSH_RESET_PERMS,
+                       NUMA_NO_NODE, __builtin_return_address(0));
 }
 
 bool __weak module_init_section(const char *name)
@@ -4377,7 +4382,7 @@ static int modules_open(struct inode *inode, struct file *file)
 
        if (!err) {
                struct seq_file *m = file->private_data;
-               m->private = kallsyms_show_value() ? NULL : (void *)8ul;
+               m->private = kallsyms_show_value(file->f_cred) ? NULL : (void *)8ul;
        }
 
        return err;
index b03df67..cd35663 100644 (file)
@@ -531,7 +531,7 @@ SYSCALL_DEFINE2(setns, int, fd, int, flags)
        } else if (!IS_ERR(pidfd_pid(file))) {
                err = check_setns_flags(flags);
        } else {
-               err = -EBADF;
+               err = -EINVAL;
        }
        if (err)
                goto out;
index 29fc5d8..4373f7a 100644 (file)
@@ -335,7 +335,7 @@ static void padata_reorder(struct parallel_data *pd)
         *
         * Ensure reorder queue is read after pd->lock is dropped so we see
         * new objects from another task in padata_do_serial.  Pairs with
-        * smp_mb__after_atomic in padata_do_serial.
+        * smp_mb in padata_do_serial.
         */
        smp_mb();
 
@@ -418,7 +418,7 @@ void padata_do_serial(struct padata_priv *padata)
         * with the trylock of pd->lock in padata_reorder.  Pairs with smp_mb
         * in padata_reorder.
         */
-       smp_mb__after_atomic();
+       smp_mb();
 
        padata_reorder(pd);
 }
index 8c14835..b71eaf5 100644 (file)
@@ -974,16 +974,6 @@ static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence)
                user->idx = log_next_idx;
                user->seq = log_next_seq;
                break;
-       case SEEK_CUR:
-               /*
-                * It isn't supported due to the record nature of this
-                * interface: _SET _DATA and _END point to very specific
-                * record positions, while _CUR would be more useful in case
-                * of a byte-based log. Because of that, return the default
-                * errno value for invalid seek operation.
-                */
-               ret = -ESPIPE;
-               break;
        default:
                ret = -EINVAL;
        }
index 16dd1e6..9eb39c2 100644 (file)
@@ -723,7 +723,7 @@ kfree_perf_init(void)
                schedule_timeout_uninterruptible(1);
        }
 
-       pr_alert("kfree object size=%lu\n", kfree_mult * sizeof(struct kfree_obj));
+       pr_alert("kfree object size=%zu\n", kfree_mult * sizeof(struct kfree_obj));
 
        kfree_reader_tasks = kcalloc(kfree_nrealthreads, sizeof(kfree_reader_tasks[0]),
                               GFP_KERNEL);
index c716ead..6c6569e 100644 (file)
@@ -250,7 +250,7 @@ static noinstr void rcu_dynticks_eqs_enter(void)
         * next idle sojourn.
         */
        rcu_dynticks_task_trace_enter();  // Before ->dynticks update!
-       seq = atomic_add_return(RCU_DYNTICK_CTRL_CTR, &rdp->dynticks);
+       seq = arch_atomic_add_return(RCU_DYNTICK_CTRL_CTR, &rdp->dynticks);
        // RCU is no longer watching.  Better be in extended quiescent state!
        WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) &&
                     (seq & RCU_DYNTICK_CTRL_CTR));
@@ -274,13 +274,13 @@ static noinstr void rcu_dynticks_eqs_exit(void)
         * and we also must force ordering with the next RCU read-side
         * critical section.
         */
-       seq = atomic_add_return(RCU_DYNTICK_CTRL_CTR, &rdp->dynticks);
+       seq = arch_atomic_add_return(RCU_DYNTICK_CTRL_CTR, &rdp->dynticks);
        // RCU is now watching.  Better not be in an extended quiescent state!
        rcu_dynticks_task_trace_exit();  // After ->dynticks update!
        WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) &&
                     !(seq & RCU_DYNTICK_CTRL_CTR));
        if (seq & RCU_DYNTICK_CTRL_MASK) {
-               atomic_andnot(RCU_DYNTICK_CTRL_MASK, &rdp->dynticks);
+               arch_atomic_andnot(RCU_DYNTICK_CTRL_MASK, &rdp->dynticks);
                smp_mb__after_atomic(); /* _exit after clearing mask. */
        }
 }
@@ -313,7 +313,7 @@ static __always_inline bool rcu_dynticks_curr_cpu_in_eqs(void)
 {
        struct rcu_data *rdp = this_cpu_ptr(&rcu_data);
 
-       return !(atomic_read(&rdp->dynticks) & RCU_DYNTICK_CTRL_CTR);
+       return !(arch_atomic_read(&rdp->dynticks) & RCU_DYNTICK_CTRL_CTR);
 }
 
 /*
@@ -633,6 +633,10 @@ static noinstr void rcu_eqs_enter(bool user)
        do_nocb_deferred_wakeup(rdp);
        rcu_prepare_for_idle();
        rcu_preempt_deferred_qs(current);
+
+       // instrumentation for the noinstr rcu_dynticks_eqs_enter()
+       instrument_atomic_write(&rdp->dynticks, sizeof(rdp->dynticks));
+
        instrumentation_end();
        WRITE_ONCE(rdp->dynticks_nesting, 0); /* Avoid irq-access tearing. */
        // RCU is watching here ...
@@ -692,6 +696,7 @@ noinstr void rcu_nmi_exit(void)
 {
        struct rcu_data *rdp = this_cpu_ptr(&rcu_data);
 
+       instrumentation_begin();
        /*
         * Check for ->dynticks_nmi_nesting underflow and bad ->dynticks.
         * (We are exiting an NMI handler, so RCU better be paying attention
@@ -705,7 +710,6 @@ noinstr void rcu_nmi_exit(void)
         * leave it in non-RCU-idle state.
         */
        if (rdp->dynticks_nmi_nesting != 1) {
-               instrumentation_begin();
                trace_rcu_dyntick(TPS("--="), rdp->dynticks_nmi_nesting, rdp->dynticks_nmi_nesting - 2,
                                  atomic_read(&rdp->dynticks));
                WRITE_ONCE(rdp->dynticks_nmi_nesting, /* No store tearing. */
@@ -714,13 +718,15 @@ noinstr void rcu_nmi_exit(void)
                return;
        }
 
-       instrumentation_begin();
        /* This NMI interrupted an RCU-idle CPU, restore RCU-idleness. */
        trace_rcu_dyntick(TPS("Startirq"), rdp->dynticks_nmi_nesting, 0, atomic_read(&rdp->dynticks));
        WRITE_ONCE(rdp->dynticks_nmi_nesting, 0); /* Avoid store tearing. */
 
        if (!in_nmi())
                rcu_prepare_for_idle();
+
+       // instrumentation for the noinstr rcu_dynticks_eqs_enter()
+       instrument_atomic_write(&rdp->dynticks, sizeof(rdp->dynticks));
        instrumentation_end();
 
        // RCU is watching here ...
@@ -838,6 +844,10 @@ static void noinstr rcu_eqs_exit(bool user)
        rcu_dynticks_eqs_exit();
        // ... but is watching here.
        instrumentation_begin();
+
+       // instrumentation for the noinstr rcu_dynticks_eqs_exit()
+       instrument_atomic_write(&rdp->dynticks, sizeof(rdp->dynticks));
+
        rcu_cleanup_after_idle();
        trace_rcu_dyntick(TPS("End"), rdp->dynticks_nesting, 1, atomic_read(&rdp->dynticks));
        WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) && !user && !is_idle_task(current));
@@ -983,13 +993,21 @@ noinstr void rcu_nmi_enter(void)
                if (!in_nmi())
                        rcu_cleanup_after_idle();
 
+               instrumentation_begin();
+               // instrumentation for the noinstr rcu_dynticks_curr_cpu_in_eqs()
+               instrument_atomic_read(&rdp->dynticks, sizeof(rdp->dynticks));
+               // instrumentation for the noinstr rcu_dynticks_eqs_exit()
+               instrument_atomic_write(&rdp->dynticks, sizeof(rdp->dynticks));
+
                incby = 1;
        } else if (!in_nmi()) {
                instrumentation_begin();
                rcu_irq_enter_check_tick();
                instrumentation_end();
+       } else  {
+               instrumentation_begin();
        }
-       instrumentation_begin();
+
        trace_rcu_dyntick(incby == 1 ? TPS("Endirq") : TPS("++="),
                          rdp->dynticks_nmi_nesting,
                          rdp->dynticks_nmi_nesting + incby, atomic_read(&rdp->dynticks));
index 8f36032..2142c67 100644 (file)
@@ -1311,9 +1311,6 @@ static inline void dequeue_task(struct rq *rq, struct task_struct *p, int flags)
 
 void activate_task(struct rq *rq, struct task_struct *p, int flags)
 {
-       if (task_contributes_to_load(p))
-               rq->nr_uninterruptible--;
-
        enqueue_task(rq, p, flags);
 
        p->on_rq = TASK_ON_RQ_QUEUED;
@@ -1323,9 +1320,6 @@ void deactivate_task(struct rq *rq, struct task_struct *p, int flags)
 {
        p->on_rq = (flags & DEQUEUE_SLEEP) ? 0 : TASK_ON_RQ_MIGRATING;
 
-       if (task_contributes_to_load(p))
-               rq->nr_uninterruptible++;
-
        dequeue_task(rq, p, flags);
 }
 
@@ -1637,7 +1631,7 @@ static int __set_cpus_allowed_ptr(struct task_struct *p,
                goto out;
        }
 
-       if (cpumask_equal(p->cpus_ptr, new_mask))
+       if (cpumask_equal(&p->cpus_mask, new_mask))
                goto out;
 
        /*
@@ -2236,10 +2230,10 @@ ttwu_do_activate(struct rq *rq, struct task_struct *p, int wake_flags,
 
        lockdep_assert_held(&rq->lock);
 
-#ifdef CONFIG_SMP
        if (p->sched_contributes_to_load)
                rq->nr_uninterruptible--;
 
+#ifdef CONFIG_SMP
        if (wake_flags & WF_MIGRATED)
                en_flags |= ENQUEUE_MIGRATED;
 #endif
@@ -2293,8 +2287,15 @@ void sched_ttwu_pending(void *arg)
        rq_lock_irqsave(rq, &rf);
        update_rq_clock(rq);
 
-       llist_for_each_entry_safe(p, t, llist, wake_entry)
+       llist_for_each_entry_safe(p, t, llist, wake_entry.llist) {
+               if (WARN_ON_ONCE(p->on_cpu))
+                       smp_cond_load_acquire(&p->on_cpu, !VAL);
+
+               if (WARN_ON_ONCE(task_cpu(p) != cpu_of(rq)))
+                       set_task_cpu(p, cpu_of(rq));
+
                ttwu_do_activate(rq, p, p->sched_remote_wakeup ? WF_MIGRATED : 0, &rf);
+       }
 
        rq_unlock_irqrestore(rq, &rf);
 }
@@ -2322,7 +2323,7 @@ static void __ttwu_queue_wakelist(struct task_struct *p, int cpu, int wake_flags
        p->sched_remote_wakeup = !!(wake_flags & WF_MIGRATED);
 
        WRITE_ONCE(rq->ttwu_pending, 1);
-       __smp_call_single_queue(cpu, &p->wake_entry);
+       __smp_call_single_queue(cpu, &p->wake_entry.llist);
 }
 
 void wake_up_if_idle(int cpu)
@@ -2369,7 +2370,7 @@ static inline bool ttwu_queue_cond(int cpu, int wake_flags)
         * the soon-to-be-idle CPU as the current CPU is likely busy.
         * nr_running is checked to avoid unnecessary task stacking.
         */
-       if ((wake_flags & WF_ON_RQ) && cpu_rq(cpu)->nr_running <= 1)
+       if ((wake_flags & WF_ON_CPU) && cpu_rq(cpu)->nr_running <= 1)
                return true;
 
        return false;
@@ -2378,6 +2379,9 @@ static inline bool ttwu_queue_cond(int cpu, int wake_flags)
 static bool ttwu_queue_wakelist(struct task_struct *p, int cpu, int wake_flags)
 {
        if (sched_feat(TTWU_QUEUE) && ttwu_queue_cond(cpu, wake_flags)) {
+               if (WARN_ON_ONCE(cpu == smp_processor_id()))
+                       return false;
+
                sched_clock_cpu(cpu); /* Sync clocks across CPUs */
                __ttwu_queue_wakelist(p, cpu, wake_flags);
                return true;
@@ -2528,7 +2532,6 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
                        goto out;
 
                success = 1;
-               cpu = task_cpu(p);
                trace_sched_waking(p);
                p->state = TASK_RUNNING;
                trace_sched_wakeup(p);
@@ -2550,7 +2553,6 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
 
        /* We're going to change ->state: */
        success = 1;
-       cpu = task_cpu(p);
 
        /*
         * Ensure we load p->on_rq _after_ p->state, otherwise it would
@@ -2575,7 +2577,7 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
         * A similar smb_rmb() lives in try_invoke_on_locked_down_task().
         */
        smp_rmb();
-       if (p->on_rq && ttwu_remote(p, wake_flags))
+       if (READ_ONCE(p->on_rq) && ttwu_remote(p, wake_flags))
                goto unlock;
 
        if (p->in_iowait) {
@@ -2584,9 +2586,6 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
        }
 
 #ifdef CONFIG_SMP
-       p->sched_contributes_to_load = !!task_contributes_to_load(p);
-       p->state = TASK_WAKING;
-
        /*
         * Ensure we load p->on_cpu _after_ p->on_rq, otherwise it would be
         * possible to, falsely, observe p->on_cpu == 0.
@@ -2605,8 +2604,20 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
         *
         * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in
         * __schedule().  See the comment for smp_mb__after_spinlock().
+        *
+        * Form a control-dep-acquire with p->on_rq == 0 above, to ensure
+        * schedule()'s deactivate_task() has 'happened' and p will no longer
+        * care about it's own p->state. See the comment in __schedule().
         */
-       smp_rmb();
+       smp_acquire__after_ctrl_dep();
+
+       /*
+        * We're doing the wakeup (@success == 1), they did a dequeue (p->on_rq
+        * == 0), which means we need to do an enqueue, change p->state to
+        * TASK_WAKING such that we can unlock p->pi_lock before doing the
+        * enqueue, such as ttwu_queue_wakelist().
+        */
+       p->state = TASK_WAKING;
 
        /*
         * If the owning (remote) CPU is still in the middle of schedule() with
@@ -2614,8 +2625,21 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
         * which potentially sends an IPI instead of spinning on p->on_cpu to
         * let the waker make forward progress. This is safe because IRQs are
         * disabled and the IPI will deliver after on_cpu is cleared.
+        *
+        * Ensure we load task_cpu(p) after p->on_cpu:
+        *
+        * set_task_cpu(p, cpu);
+        *   STORE p->cpu = @cpu
+        * __schedule() (switch to task 'p')
+        *   LOCK rq->lock
+        *   smp_mb__after_spin_lock()          smp_cond_load_acquire(&p->on_cpu)
+        *   STORE p->on_cpu = 1                LOAD p->cpu
+        *
+        * to ensure we observe the correct CPU on which the task is currently
+        * scheduling.
         */
-       if (READ_ONCE(p->on_cpu) && ttwu_queue_wakelist(p, cpu, wake_flags | WF_ON_RQ))
+       if (smp_load_acquire(&p->on_cpu) &&
+           ttwu_queue_wakelist(p, task_cpu(p), wake_flags | WF_ON_CPU))
                goto unlock;
 
        /*
@@ -2635,6 +2659,8 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
                psi_ttwu_dequeue(p);
                set_task_cpu(p, cpu);
        }
+#else
+       cpu = task_cpu(p);
 #endif /* CONFIG_SMP */
 
        ttwu_queue(p, cpu, wake_flags);
@@ -2642,7 +2668,7 @@ unlock:
        raw_spin_unlock_irqrestore(&p->pi_lock, flags);
 out:
        if (success)
-               ttwu_stat(p, cpu, wake_flags);
+               ttwu_stat(p, task_cpu(p), wake_flags);
        preempt_enable();
 
        return success;
@@ -2763,7 +2789,7 @@ static void __sched_fork(unsigned long clone_flags, struct task_struct *p)
 #endif
        init_numa_balancing(clone_flags, p);
 #ifdef CONFIG_SMP
-       p->wake_entry_type = CSD_TYPE_TTWU;
+       p->wake_entry.u_flags = CSD_TYPE_TTWU;
 #endif
 }
 
@@ -2939,6 +2965,7 @@ int sched_fork(unsigned long clone_flags, struct task_struct *p)
         * Silence PROVE_RCU.
         */
        raw_spin_lock_irqsave(&p->pi_lock, flags);
+       rseq_migrate(p);
        /*
         * We're setting the CPU for the first time, we don't migrate,
         * so use __set_task_cpu().
@@ -3003,6 +3030,7 @@ void wake_up_new_task(struct task_struct *p)
         * as we're not fully set-up yet.
         */
        p->recent_used_cpu = task_cpu(p);
+       rseq_migrate(p);
        __set_task_cpu(p, select_task_rq(p, task_cpu(p), SD_BALANCE_FORK, 0));
 #endif
        rq = __task_rq_lock(p, &rf);
@@ -4074,6 +4102,7 @@ static void __sched notrace __schedule(bool preempt)
 {
        struct task_struct *prev, *next;
        unsigned long *switch_count;
+       unsigned long prev_state;
        struct rq_flags rf;
        struct rq *rq;
        int cpu;
@@ -4093,9 +4122,16 @@ static void __sched notrace __schedule(bool preempt)
        /*
         * Make sure that signal_pending_state()->signal_pending() below
         * can't be reordered with __set_current_state(TASK_INTERRUPTIBLE)
-        * done by the caller to avoid the race with signal_wake_up().
+        * done by the caller to avoid the race with signal_wake_up():
         *
-        * The membarrier system call requires a full memory barrier
+        * __set_current_state(@state)          signal_wake_up()
+        * schedule()                             set_tsk_thread_flag(p, TIF_SIGPENDING)
+        *                                        wake_up_state(p, state)
+        *   LOCK rq->lock                          LOCK p->pi_state
+        *   smp_mb__after_spinlock()               smp_mb__after_spinlock()
+        *     if (signal_pending_state())          if (p->state & @state)
+        *
+        * Also, the membarrier system call requires a full memory barrier
         * after coming from user-space, before storing to rq->curr.
         */
        rq_lock(rq, &rf);
@@ -4106,10 +4142,38 @@ static void __sched notrace __schedule(bool preempt)
        update_rq_clock(rq);
 
        switch_count = &prev->nivcsw;
-       if (!preempt && prev->state) {
-               if (signal_pending_state(prev->state, prev)) {
+
+       /*
+        * We must load prev->state once (task_struct::state is volatile), such
+        * that:
+        *
+        *  - we form a control dependency vs deactivate_task() below.
+        *  - ptrace_{,un}freeze_traced() can change ->state underneath us.
+        */
+       prev_state = prev->state;
+       if (!preempt && prev_state) {
+               if (signal_pending_state(prev_state, prev)) {
                        prev->state = TASK_RUNNING;
                } else {
+                       prev->sched_contributes_to_load =
+                               (prev_state & TASK_UNINTERRUPTIBLE) &&
+                               !(prev_state & TASK_NOLOAD) &&
+                               !(prev->flags & PF_FROZEN);
+
+                       if (prev->sched_contributes_to_load)
+                               rq->nr_uninterruptible++;
+
+                       /*
+                        * __schedule()                 ttwu()
+                        *   prev_state = prev->state;    if (p->on_rq && ...)
+                        *   if (prev_state)                goto out;
+                        *     p->on_rq = 0;              smp_acquire__after_ctrl_dep();
+                        *                                p->state = TASK_WAKING
+                        *
+                        * Where __schedule() and ttwu() have matching control dependencies.
+                        *
+                        * After this, schedule() must not care about p->state any more.
+                        */
                        deactivate_task(rq, prev, DEQUEUE_SLEEP | DEQUEUE_NOCLOCK);
 
                        if (prev->in_iowait) {
@@ -4421,6 +4485,7 @@ asmlinkage __visible void __sched preempt_schedule_irq(void)
 int default_wake_function(wait_queue_entry_t *curr, unsigned mode, int wake_flags,
                          void *key)
 {
+       WARN_ON_ONCE(IS_ENABLED(CONFIG_SCHED_DEBUG) && wake_flags & ~WF_SYNC);
        return try_to_wake_up(curr->private, mode, wake_flags);
 }
 EXPORT_SYMBOL(default_wake_function);
@@ -4533,7 +4598,8 @@ void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task)
         */
        if (dl_prio(prio)) {
                if (!dl_prio(p->normal_prio) ||
-                   (pi_task && dl_entity_preempt(&pi_task->dl, &p->dl))) {
+                   (pi_task && dl_prio(pi_task->prio) &&
+                    dl_entity_preempt(&pi_task->dl, &p->dl))) {
                        p->dl.dl_boosted = 1;
                        queue_flag |= ENQUEUE_REPLENISH;
                } else
index 504d2f5..f63f337 100644 (file)
@@ -2692,6 +2692,7 @@ void __dl_clear_params(struct task_struct *p)
        dl_se->dl_bw                    = 0;
        dl_se->dl_density               = 0;
 
+       dl_se->dl_boosted               = 0;
        dl_se->dl_throttled             = 0;
        dl_se->dl_yielded               = 0;
        dl_se->dl_non_contending        = 0;
index cbcb2f7..04fa8db 100644 (file)
@@ -806,7 +806,7 @@ void post_init_entity_util_avg(struct task_struct *p)
                }
        }
 
-       sa->runnable_avg = cpu_scale;
+       sa->runnable_avg = sa->util_avg;
 
        if (p->sched_class != &fair_sched_class) {
                /*
@@ -4039,7 +4039,11 @@ static inline void update_misfit_status(struct task_struct *p, struct rq *rq)
                return;
        }
 
-       rq->misfit_task_load = task_h_load(p);
+       /*
+        * Make sure that misfit_task_load will not be null even if
+        * task_h_load() returns 0.
+        */
+       rq->misfit_task_load = max_t(unsigned long, task_h_load(p), 1);
 }
 
 #else /* CONFIG_SMP */
@@ -7638,7 +7642,14 @@ static int detach_tasks(struct lb_env *env)
 
                switch (env->migration_type) {
                case migrate_load:
-                       load = task_h_load(p);
+                       /*
+                        * Depending of the number of CPUs and tasks and the
+                        * cgroup hierarchy, task_h_load() can return a null
+                        * value. Make sure that env->imbalance decreases
+                        * otherwise detach_tasks() will stop only after
+                        * detaching up to loop_max tasks.
+                        */
+                       load = max_t(unsigned long, task_h_load(p), 1);
 
                        if (sched_feat(LB_MIN) &&
                            load < 16 && !env->sd->nr_balance_failed)
index 05deb81..1ae95b9 100644 (file)
@@ -96,6 +96,15 @@ void __cpuidle default_idle_call(void)
        }
 }
 
+static int call_cpuidle_s2idle(struct cpuidle_driver *drv,
+                              struct cpuidle_device *dev)
+{
+       if (current_clr_polling_and_test())
+               return -EBUSY;
+
+       return cpuidle_enter_s2idle(drv, dev);
+}
+
 static int call_cpuidle(struct cpuidle_driver *drv, struct cpuidle_device *dev,
                      int next_state)
 {
@@ -171,11 +180,9 @@ static void cpuidle_idle_call(void)
                if (idle_should_enter_s2idle()) {
                        rcu_idle_enter();
 
-                       entered_state = cpuidle_enter_s2idle(drv, dev);
-                       if (entered_state > 0) {
-                               local_irq_enable();
+                       entered_state = call_cpuidle_s2idle(drv, dev);
+                       if (entered_state > 0)
                                goto exit_idle;
-                       }
 
                        rcu_idle_exit();
 
index 1d4e94c..877fb08 100644 (file)
@@ -1682,7 +1682,7 @@ static inline int task_on_rq_migrating(struct task_struct *p)
 #define WF_SYNC                        0x01            /* Waker goes to sleep after wakeup */
 #define WF_FORK                        0x02            /* Child wakeup after fork */
 #define WF_MIGRATED            0x04            /* Internal use, task got migrated */
-#define WF_ON_RQ               0x08            /* Wakee is on_rq */
+#define WF_ON_CPU              0x08            /* Wakee is on_cpu */
 
 /*
  * To aid in avoiding the subversion of "niceness" due to uneven distribution
index 5ca48cc..ee22ec7 100644 (file)
@@ -2529,9 +2529,6 @@ bool get_signal(struct ksignal *ksig)
        struct signal_struct *signal = current->signal;
        int signr;
 
-       if (unlikely(current->task_works))
-               task_work_run();
-
        if (unlikely(uprobe_deny_signal()))
                return false;
 
@@ -2544,6 +2541,13 @@ bool get_signal(struct ksignal *ksig)
 
 relock:
        spin_lock_irq(&sighand->siglock);
+       current->jobctl &= ~JOBCTL_TASK_WORK;
+       if (unlikely(current->task_works)) {
+               spin_unlock_irq(&sighand->siglock);
+               task_work_run();
+               goto relock;
+       }
+
        /*
         * Every stopped thread goes here after wakeup. Check to see if
         * we should notify the parent, prepare_signal(SIGCONT) encodes
index 472c2b2..aa17eed 100644 (file)
@@ -669,24 +669,6 @@ void __init smp_init(void)
 {
        int num_nodes, num_cpus;
 
-       /*
-        * Ensure struct irq_work layout matches so that
-        * flush_smp_call_function_queue() can do horrible things.
-        */
-       BUILD_BUG_ON(offsetof(struct irq_work, llnode) !=
-                    offsetof(struct __call_single_data, llist));
-       BUILD_BUG_ON(offsetof(struct irq_work, func) !=
-                    offsetof(struct __call_single_data, func));
-       BUILD_BUG_ON(offsetof(struct irq_work, flags) !=
-                    offsetof(struct __call_single_data, flags));
-
-       /*
-        * Assert the CSD_TYPE_TTWU layout is similar enough
-        * for task_struct to be on the @call_single_queue.
-        */
-       BUILD_BUG_ON(offsetof(struct task_struct, wake_entry_type) - offsetof(struct task_struct, wake_entry) !=
-                    offsetof(struct __call_single_data, flags) - offsetof(struct __call_single_data, llist));
-
        idle_threads_init();
        cpuhp_threads_init();
 
index 825f282..5c0848c 100644 (file)
@@ -25,9 +25,10 @@ static struct callback_head work_exited; /* all we need is ->next == NULL */
  * 0 if succeeds or -ESRCH.
  */
 int
-task_work_add(struct task_struct *task, struct callback_head *work, bool notify)
+task_work_add(struct task_struct *task, struct callback_head *work, int notify)
 {
        struct callback_head *head;
+       unsigned long flags;
 
        do {
                head = READ_ONCE(task->task_works);
@@ -36,8 +37,19 @@ task_work_add(struct task_struct *task, struct callback_head *work, bool notify)
                work->next = head;
        } while (cmpxchg(&task->task_works, head, work) != head);
 
-       if (notify)
+       switch (notify) {
+       case TWA_RESUME:
                set_notify_resume(task);
+               break;
+       case TWA_SIGNAL:
+               if (lock_task_sighand(task, &flags)) {
+                       task->jobctl |= JOBCTL_TASK_WORK;
+                       signal_wake_up(task, 0);
+                       unlock_task_sighand(task, &flags);
+               }
+               break;
+       }
+
        return 0;
 }
 
index 398e6ea..026ac01 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/sched/debug.h>
 #include <linux/slab.h>
 #include <linux/compat.h>
+#include <linux/random.h>
 
 #include <linux/uaccess.h>
 #include <asm/unistd.h>
@@ -521,8 +522,8 @@ static int calc_wheel_index(unsigned long expires, unsigned long clk)
                 * Force expire obscene large timeouts to expire at the
                 * capacity limit of the wheel.
                 */
-               if (expires >= WHEEL_TIMEOUT_CUTOFF)
-                       expires = WHEEL_TIMEOUT_MAX;
+               if (delta >= WHEEL_TIMEOUT_CUTOFF)
+                       expires = clk + WHEEL_TIMEOUT_MAX;
 
                idx = calc_index(expires, LVL_DEPTH - 1);
        }
@@ -584,7 +585,15 @@ trigger_dyntick_cpu(struct timer_base *base, struct timer_list *timer)
         * Set the next expiry time and kick the CPU so it can reevaluate the
         * wheel:
         */
-       base->next_expiry = timer->expires;
+       if (time_before(timer->expires, base->clk)) {
+               /*
+                * Prevent from forward_timer_base() moving the base->clk
+                * backward
+                */
+               base->next_expiry = base->clk;
+       } else {
+               base->next_expiry = timer->expires;
+       }
        wake_up_nohz_cpu(base->cpu);
 }
 
@@ -896,10 +905,13 @@ static inline void forward_timer_base(struct timer_base *base)
         * If the next expiry value is > jiffies, then we fast forward to
         * jiffies otherwise we forward to the next expiry value.
         */
-       if (time_after(base->next_expiry, jnow))
+       if (time_after(base->next_expiry, jnow)) {
                base->clk = jnow;
-       else
+       } else {
+               if (WARN_ON_ONCE(time_before(base->next_expiry, base->clk)))
+                       return;
                base->clk = base->next_expiry;
+       }
 #endif
 }
 
@@ -1731,6 +1743,13 @@ void update_process_times(int user_tick)
        scheduler_tick();
        if (IS_ENABLED(CONFIG_POSIX_TIMERS))
                run_posix_cpu_timers();
+
+       /* The current CPU might make use of net randoms without receiving IRQs
+        * to renew them often enough. Let's update the net_rand_state from a
+        * non-constant value that's not affine to the number of calls to make
+        * sure it's updated when there's some activity (we don't care in idle).
+        */
+       this_cpu_add(net_rand_state.s1, rol32(jiffies, 24) + user_tick);
 }
 
 /**
index 5773f0b..5ef0484 100644 (file)
@@ -3,6 +3,9 @@
  * Copyright (C) 2006 Jens Axboe <axboe@kernel.dk>
  *
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/blkdev.h>
 #include <linux/blktrace_api.h>
@@ -344,7 +347,8 @@ static int __blk_trace_remove(struct request_queue *q)
 {
        struct blk_trace *bt;
 
-       bt = xchg(&q->blk_trace, NULL);
+       bt = rcu_replace_pointer(q->blk_trace, NULL,
+                                lockdep_is_held(&q->blk_trace_mutex));
        if (!bt)
                return -EINVAL;
 
@@ -494,6 +498,17 @@ static int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
         */
        strreplace(buts->name, '/', '_');
 
+       /*
+        * bdev can be NULL, as with scsi-generic, this is a helpful as
+        * we can be.
+        */
+       if (rcu_dereference_protected(q->blk_trace,
+                                     lockdep_is_held(&q->blk_trace_mutex))) {
+               pr_warn("Concurrent blktraces are not allowed on %s\n",
+                       buts->name);
+               return -EBUSY;
+       }
+
        bt = kzalloc(sizeof(*bt), GFP_KERNEL);
        if (!bt)
                return -ENOMEM;
@@ -543,10 +558,7 @@ static int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
        bt->pid = buts->pid;
        bt->trace_state = Blktrace_setup;
 
-       ret = -EBUSY;
-       if (cmpxchg(&q->blk_trace, NULL, bt))
-               goto err;
-
+       rcu_assign_pointer(q->blk_trace, bt);
        get_probe_ref();
 
        ret = 0;
@@ -1629,7 +1641,8 @@ static int blk_trace_remove_queue(struct request_queue *q)
 {
        struct blk_trace *bt;
 
-       bt = xchg(&q->blk_trace, NULL);
+       bt = rcu_replace_pointer(q->blk_trace, NULL,
+                                lockdep_is_held(&q->blk_trace_mutex));
        if (bt == NULL)
                return -EINVAL;
 
@@ -1661,10 +1674,7 @@ static int blk_trace_setup_queue(struct request_queue *q,
 
        blk_trace_setup_lba(bt, bdev);
 
-       ret = -EBUSY;
-       if (cmpxchg(&q->blk_trace, NULL, bt))
-               goto free_bt;
-
+       rcu_assign_pointer(q->blk_trace, bt);
        get_probe_ref();
        return 0;
 
index e729c9e..7bc3d61 100644 (file)
@@ -141,7 +141,7 @@ bpf_probe_read_user_common(void *dst, u32 size, const void __user *unsafe_ptr)
 {
        int ret;
 
-       ret = probe_user_read(dst, unsafe_ptr, size);
+       ret = copy_from_user_nofault(dst, unsafe_ptr, size);
        if (unlikely(ret < 0))
                memset(dst, 0, size);
        return ret;
@@ -196,7 +196,7 @@ bpf_probe_read_kernel_common(void *dst, u32 size, const void *unsafe_ptr)
 
        if (unlikely(ret < 0))
                goto fail;
-       ret = probe_kernel_read(dst, unsafe_ptr, size);
+       ret = copy_from_kernel_nofault(dst, unsafe_ptr, size);
        if (unlikely(ret < 0))
                goto fail;
        return ret;
@@ -241,7 +241,7 @@ bpf_probe_read_kernel_str_common(void *dst, u32 size, const void *unsafe_ptr)
        if (unlikely(ret < 0))
                goto fail;
 
-       return 0;
+       return ret;
 fail:
        memset(dst, 0, size);
        return ret;
@@ -326,7 +326,7 @@ BPF_CALL_3(bpf_probe_write_user, void __user *, unsafe_ptr, const void *, src,
        if (unlikely(!nmi_uaccess_okay()))
                return -EPERM;
 
-       return probe_user_write(unsafe_ptr, src, size);
+       return copy_to_user_nofault(unsafe_ptr, src, size);
 }
 
 static const struct bpf_func_proto bpf_probe_write_user_proto = {
@@ -661,7 +661,7 @@ BPF_CALL_5(bpf_seq_printf, struct seq_file *, m, char *, fmt, u32, fmt_size,
 
                        copy_size = (fmt[i + 2] == '4') ? 4 : 16;
 
-                       err = probe_kernel_read(bufs->buf[memcpy_cnt],
+                       err = copy_from_kernel_nofault(bufs->buf[memcpy_cnt],
                                                (void *) (long) args[fmt_cnt],
                                                copy_size);
                        if (err < 0)
index c163c35..1903b80 100644 (file)
@@ -2260,7 +2260,7 @@ ftrace_find_tramp_ops_next(struct dyn_ftrace *rec,
 
                if (hash_contains_ip(ip, op->func_hash))
                        return op;
-       } 
+       }
 
        return NULL;
 }
@@ -3599,7 +3599,7 @@ static int t_show(struct seq_file *m, void *v)
                        if (direct)
                                seq_printf(m, "\n\tdirect-->%pS", (void *)direct);
                }
-       }       
+       }
 
        seq_putc(m, '\n');
 
@@ -7151,6 +7151,10 @@ static int pid_open(struct inode *inode, struct file *file, int type)
        case TRACE_NO_PIDS:
                seq_ops = &ftrace_no_pid_sops;
                break;
+       default:
+               trace_array_put(tr);
+               WARN_ON_ONCE(1);
+               return -EINVAL;
        }
 
        ret = seq_open(file, seq_ops);
@@ -7229,6 +7233,10 @@ pid_write(struct file *filp, const char __user *ubuf,
                other_pids = rcu_dereference_protected(tr->function_pids,
                                             lockdep_is_held(&ftrace_lock));
                break;
+       default:
+               ret = -EINVAL;
+               WARN_ON_ONCE(1);
+               goto out;
        }
 
        ret = trace_pid_write(filtered_pids, &pid_list, ubuf, cnt);
index b8e1ca4..00867ff 100644 (file)
@@ -2427,7 +2427,7 @@ rb_update_event(struct ring_buffer_per_cpu *cpu_buffer,
        if (unlikely(info->add_timestamp)) {
                bool abs = ring_buffer_time_stamp_abs(cpu_buffer->buffer);
 
-               event = rb_add_time_stamp(event, info->delta, abs);
+               event = rb_add_time_stamp(event, abs ? info->delta : delta, abs);
                length -= RB_LEN_TIME_EXTEND;
                delta = 0;
        }
index ec44b0e..bb62269 100644 (file)
@@ -3570,7 +3570,6 @@ static void *s_next(struct seq_file *m, void *v, loff_t *pos)
 
 void tracing_iter_reset(struct trace_iterator *iter, int cpu)
 {
-       struct ring_buffer_event *event;
        struct ring_buffer_iter *buf_iter;
        unsigned long entries = 0;
        u64 ts;
@@ -3588,7 +3587,7 @@ void tracing_iter_reset(struct trace_iterator *iter, int cpu)
         * that a reset never took place on a cpu. This is evident
         * by the timestamp being before the start of the buffer.
         */
-       while ((event = ring_buffer_iter_peek(buf_iter, &ts))) {
+       while (ring_buffer_iter_peek(buf_iter, &ts)) {
                if (ts >= iter->array_buffer->time_start)
                        break;
                entries++;
index def769d..13db400 100644 (file)
@@ -61,6 +61,9 @@ enum trace_type {
 #undef __field_desc
 #define __field_desc(type, container, item)
 
+#undef __field_packed
+#define __field_packed(type, container, item)
+
 #undef __array
 #define __array(type, item, size)      type    item[size];
 
index 9de29bb..fa0fc08 100644 (file)
@@ -101,12 +101,16 @@ trace_boot_add_kprobe_event(struct xbc_node *node, const char *event)
                kprobe_event_cmd_init(&cmd, buf, MAX_BUF_LEN);
 
                ret = kprobe_event_gen_cmd_start(&cmd, event, val);
-               if (ret)
+               if (ret) {
+                       pr_err("Failed to generate probe: %s\n", buf);
                        break;
+               }
 
                ret = kprobe_event_gen_cmd_end(&cmd);
-               if (ret)
+               if (ret) {
                        pr_err("Failed to add probe: %s\n", buf);
+                       break;
+               }
        }
 
        return ret;
@@ -120,7 +124,7 @@ trace_boot_add_kprobe_event(struct xbc_node *node, const char *event)
 }
 #endif
 
-#ifdef CONFIG_HIST_TRIGGERS
+#ifdef CONFIG_SYNTH_EVENTS
 static int __init
 trace_boot_add_synth_event(struct xbc_node *node, const char *event)
 {
index a523da0..18c4a58 100644 (file)
@@ -78,8 +78,8 @@ FTRACE_ENTRY_PACKED(funcgraph_entry, ftrace_graph_ent_entry,
 
        F_STRUCT(
                __field_struct( struct ftrace_graph_ent,        graph_ent       )
-               __field_desc(   unsigned long,  graph_ent,      func            )
-               __field_desc(   int,            graph_ent,      depth           )
+               __field_packed( unsigned long,  graph_ent,      func            )
+               __field_packed( int,            graph_ent,      depth           )
        ),
 
        F_printk("--> %ps (%d)", (void *)__entry->func, __entry->depth)
@@ -92,11 +92,11 @@ FTRACE_ENTRY_PACKED(funcgraph_exit, ftrace_graph_ret_entry,
 
        F_STRUCT(
                __field_struct( struct ftrace_graph_ret,        ret     )
-               __field_desc(   unsigned long,  ret,            func    )
-               __field_desc(   unsigned long,  ret,            overrun )
-               __field_desc(   unsigned long long, ret,        calltime)
-               __field_desc(   unsigned long long, ret,        rettime )
-               __field_desc(   int,            ret,            depth   )
+               __field_packed( unsigned long,  ret,            func    )
+               __field_packed( unsigned long,  ret,            overrun )
+               __field_packed( unsigned long long, ret,        calltime)
+               __field_packed( unsigned long long, ret,        rettime )
+               __field_packed( int,            ret,            depth   )
        ),
 
        F_printk("<-- %ps (%d) (start: %llx  end: %llx) over: %d",
index 3a74736..f725802 100644 (file)
@@ -216,11 +216,17 @@ static int event_trigger_regex_open(struct inode *inode, struct file *file)
 
 int trigger_process_regex(struct trace_event_file *file, char *buff)
 {
-       char *command, *next = buff;
+       char *command, *next;
        struct event_command *p;
        int ret = -EINVAL;
 
+       next = buff = skip_spaces(buff);
        command = strsep(&next, ": \t");
+       if (next) {
+               next = skip_spaces(next);
+               if (!*next)
+                       next = NULL;
+       }
        command = (command[0] != '!') ? command : command + 1;
 
        mutex_lock(&trigger_cmd_mutex);
@@ -630,8 +636,14 @@ event_trigger_callback(struct event_command *cmd_ops,
        int ret;
 
        /* separate the trigger from the filter (t:n [if filter]) */
-       if (param && isdigit(param[0]))
+       if (param && isdigit(param[0])) {
                trigger = strsep(&param, " \t");
+               if (param) {
+                       param = skip_spaces(param);
+                       if (!*param)
+                               param = NULL;
+               }
+       }
 
        trigger_ops = cmd_ops->get_trigger_ops(cmd, trigger);
 
@@ -1368,6 +1380,11 @@ int event_enable_trigger_func(struct event_command *cmd_ops,
        trigger = strsep(&param, " \t");
        if (!trigger)
                return -EINVAL;
+       if (param) {
+               param = skip_spaces(param);
+               if (!*param)
+                       param = NULL;
+       }
 
        system = strsep(&trigger, ":");
        if (!trigger)
index 77ce5a3..70d3d0a 100644 (file)
@@ -45,6 +45,9 @@ static int ftrace_event_register(struct trace_event_call *call,
 #undef __field_desc
 #define __field_desc(type, container, item)            type item;
 
+#undef __field_packed
+#define __field_packed(type, container, item)          type item;
+
 #undef __array
 #define __array(type, item, size)                      type item[size];
 
@@ -85,6 +88,13 @@ static void __always_unused ____ftrace_check_##name(void)            \
        .size = sizeof(_type), .align = __alignof__(_type),             \
        is_signed_type(_type), .filter_type = _filter_type },
 
+
+#undef __field_ext_packed
+#define __field_ext_packed(_type, _item, _filter_type) {       \
+       .type = #_type, .name = #_item,                         \
+       .size = sizeof(_type), .align = 1,                      \
+       is_signed_type(_type), .filter_type = _filter_type },
+
 #undef __field
 #define __field(_type, _item) __field_ext(_type, _item, FILTER_OTHER)
 
@@ -94,6 +104,9 @@ static void __always_unused ____ftrace_check_##name(void)            \
 #undef __field_desc
 #define __field_desc(_type, _container, _item) __field_ext(_type, _item, FILTER_OTHER)
 
+#undef __field_packed
+#define __field_packed(_type, _container, _item) __field_ext_packed(_type, _item, FILTER_OTHER)
+
 #undef __array
 #define __array(_type, _item, _len) {                                  \
        .type = #_type"["__stringify(_len)"]", .name = #_item,          \
@@ -129,6 +142,9 @@ static struct trace_event_fields ftrace_event_fields_##name[] = {   \
 #undef __field_desc
 #define __field_desc(type, container, item)
 
+#undef __field_packed
+#define __field_packed(type, container, item)
+
 #undef __array
 #define __array(type, item, len)
 
index 8a4c8d5..dd4dff7 100644 (file)
@@ -42,7 +42,7 @@ static int allocate_ftrace_ops(struct trace_array *tr)
        if (!ops)
                return -ENOMEM;
 
-       /* Currently only the non stack verision is supported */
+       /* Currently only the non stack version is supported */
        ops->func = function_trace_call;
        ops->flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_PID;
 
index 6048f1b..aefb606 100644 (file)
@@ -1222,7 +1222,7 @@ fetch_store_strlen(unsigned long addr)
 #endif
 
        do {
-               ret = probe_kernel_read(&c, (u8 *)addr + len, 1);
+               ret = copy_from_kernel_nofault(&c, (u8 *)addr + len, 1);
                len++;
        } while (c && ret == 0 && len < MAX_STRING_SIZE);
 
@@ -1290,7 +1290,7 @@ probe_mem_read_user(void *dest, void *src, size_t size)
 {
        const void __user *uaddr =  (__force const void __user *)src;
 
-       return probe_user_read(dest, uaddr, size);
+       return copy_from_user_nofault(dest, uaddr, size);
 }
 
 static nokprobe_inline int
@@ -1300,7 +1300,7 @@ probe_mem_read(void *dest, void *src, size_t size)
        if ((unsigned long)src < TASK_SIZE)
                return probe_mem_read_user(dest, src, size);
 #endif
-       return probe_kernel_read(dest, src, size);
+       return copy_from_kernel_nofault(dest, src, size);
 }
 
 /* Note that we don't verify it, since the code does not come from user space */
index b8a928e..d2867cc 100644 (file)
@@ -639,8 +639,8 @@ static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size,
                        ret = -EINVAL;
                        goto fail;
                }
-               if ((code->op == FETCH_OP_IMM || code->op == FETCH_OP_COMM) ||
-                    parg->count) {
+               if ((code->op == FETCH_OP_IMM || code->op == FETCH_OP_COMM ||
+                    code->op == FETCH_OP_DATA) || parg->count) {
                        /*
                         * IMM, DATA and COMM is pointing actual address, those
                         * must be kept, and if parg->count != 0, this is an
index a0ff9e2..a22b628 100644 (file)
@@ -236,7 +236,7 @@ struct trace_probe_event {
        struct trace_event_call         call;
        struct list_head                files;
        struct list_head                probes;
-       struct trace_uprobe_filter      filter[0];
+       struct trace_uprobe_filter      filter[];
 };
 
 struct trace_probe {
index 9fbe1e2..c41c3c1 100644 (file)
@@ -4638,11 +4638,11 @@ void print_worker_info(const char *log_lvl, struct task_struct *task)
         * Carefully copy the associated workqueue's workfn, name and desc.
         * Keep the original last '\0' in case the original is garbage.
         */
-       probe_kernel_read(&fn, &worker->current_func, sizeof(fn));
-       probe_kernel_read(&pwq, &worker->current_pwq, sizeof(pwq));
-       probe_kernel_read(&wq, &pwq->wq, sizeof(wq));
-       probe_kernel_read(name, wq->name, sizeof(name) - 1);
-       probe_kernel_read(desc, worker->desc, sizeof(desc) - 1);
+       copy_from_kernel_nofault(&fn, &worker->current_func, sizeof(fn));
+       copy_from_kernel_nofault(&pwq, &worker->current_pwq, sizeof(pwq));
+       copy_from_kernel_nofault(&wq, &pwq->wq, sizeof(wq));
+       copy_from_kernel_nofault(name, wq->name, sizeof(name) - 1);
+       copy_from_kernel_nofault(desc, worker->desc, sizeof(desc) - 1);
 
        if (fn || name[0] || desc[0]) {
                printk("%sWorkqueue: %s %ps", log_lvl, name, fn);
index d74ac0f..9ad9210 100644 (file)
@@ -229,7 +229,6 @@ config DEBUG_INFO_COMPRESSED
        bool "Compressed debugging information"
        depends on DEBUG_INFO
        depends on $(cc-option,-gz=zlib)
-       depends on $(as-option,-Wa$(comma)--compress-debug-sections=zlib)
        depends on $(ld-option,--compress-debug-sections=zlib)
        help
          Compress the debug information using zlib.  Requires GCC 5.0+ or Clang
index 81f5464..34b84bc 100644 (file)
@@ -15,11 +15,15 @@ config CC_HAS_KASAN_GENERIC
 config CC_HAS_KASAN_SW_TAGS
        def_bool $(cc-option, -fsanitize=kernel-hwaddress)
 
+config CC_HAS_WORKING_NOSANITIZE_ADDRESS
+       def_bool !CC_IS_GCC || GCC_VERSION >= 80300
+
 config KASAN
        bool "KASAN: runtime memory debugger"
        depends on (HAVE_ARCH_KASAN && CC_HAS_KASAN_GENERIC) || \
                   (HAVE_ARCH_KASAN_SW_TAGS && CC_HAS_KASAN_SW_TAGS)
        depends on (SLUB && SYSFS) || (SLAB && !DEBUG_SLAB)
+       depends on CC_HAS_WORKING_NOSANITIZE_ADDRESS
        help
          Enables KASAN (KernelAddressSANitizer) - runtime memory debugger,
          designed to find out-of-bounds accesses and use-after-free bugs.
index ffa7a76..256f248 100644 (file)
@@ -3,6 +3,11 @@
 config HAVE_ARCH_KGDB
        bool
 
+# set if architecture has the its kgdb_arch_handle_qxfer_pkt
+# function to enable gdb stub to address XML packet sent from GDB.
+config HAVE_ARCH_KGDB_QXFER_PKT
+       bool
+
 menuconfig KGDB
        bool "KGDB: kernel debugger"
        depends on HAVE_ARCH_KGDB
index 50d1e9f..6ed72dc 100644 (file)
@@ -73,6 +73,7 @@ static void adjust_for_msb_right_quirk(u64 *to_write, int *box_start_bit,
  * @endbit: The index (in logical notation, compensated for quirks) where
  *         the packed value ends within pbuf. Must be smaller than, or equal
  *         to, startbit.
+ * @pbuflen: The length in bytes of the packed buffer pointed to by @pbuf.
  * @op: If PACK, then uval will be treated as const pointer and copied (packed)
  *     into pbuf, between startbit and endbit.
  *     If UNPACK, then pbuf will be treated as const pointer and the logical
index 763b920..3d749ab 100644 (file)
@@ -48,7 +48,7 @@ static inline void prandom_state_selftest(void)
 }
 #endif
 
-static DEFINE_PER_CPU(struct rnd_state, net_rand_state) __latent_entropy;
+DEFINE_PER_CPU(struct rnd_state, net_rand_state);
 
 /**
  *     prandom_u32_state - seeded pseudo-random number generator.
index 4e865d4..707453f 100644 (file)
@@ -91,6 +91,7 @@ int seq_buf_printf(struct seq_buf *s, const char *fmt, ...)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(seq_buf_printf);
 
 #ifdef CONFIG_BINARY_PRINTF
 /**
index 2852828..a2a8226 100644 (file)
@@ -520,8 +520,7 @@ static bool dmirror_allocate_chunk(struct dmirror_device *mdevice,
 err_free:
        kfree(devmem);
 err_release:
-       release_mem_region(devmem->pagemap.res.start,
-                          resource_size(&devmem->pagemap.res));
+       release_mem_region(res->start, resource_size(res));
 err:
        mutex_unlock(&mdevice->devmem_lock);
        return false;
index f258743..bd7c7ff 100644 (file)
@@ -419,8 +419,8 @@ static bool test_kernel_ptr(unsigned long addr, int size)
        /* should be at least readable kernel address */
        if (access_ok(ptr, 1) ||
            access_ok(ptr + size - 1, 1) ||
-           probe_kernel_address(ptr, buf) ||
-           probe_kernel_address(ptr + size - 1, buf)) {
+           get_kernel_nofault(buf, ptr) ||
+           get_kernel_nofault(buf, ptr + size - 1)) {
                pr_err("invalid kernel ptr: %#lx\n", addr);
                return true;
        }
@@ -437,7 +437,7 @@ static bool __maybe_unused test_magic(unsigned long addr, int offset,
        if (!addr)
                return false;
 
-       if (probe_kernel_address(ptr, magic) || magic != expected) {
+       if (get_kernel_nofault(magic, ptr) || magic != expected) {
                pr_err("invalid magic at %#lx + %#x = %#x, expected %#x\n",
                       addr, offset, magic, expected);
                return true;
index 72c1abf..da13793 100644 (file)
@@ -979,10 +979,10 @@ err_check_expect_stats2:
 err_world2_obj_get:
        for (i--; i >= 0; i--)
                world_obj_put(&world2, objagg, hints_case->key_ids[i]);
-       objagg_hints_put(hints);
-       objagg_destroy(objagg2);
        i = hints_case->key_ids_count;
+       objagg_destroy(objagg2);
 err_check_expect_hints_stats:
+       objagg_hints_put(hints);
 err_hints_get:
 err_check_expect_stats:
 err_world_obj_get:
index 0463ad2..26ecff8 100644 (file)
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -339,13 +339,13 @@ int __init cma_declare_contiguous_nid(phys_addr_t base,
                 */
                if (base < highmem_start && limit > highmem_start) {
                        addr = memblock_alloc_range_nid(size, alignment,
-                                       highmem_start, limit, nid, false);
+                                       highmem_start, limit, nid, true);
                        limit = highmem_start;
                }
 
                if (!addr) {
                        addr = memblock_alloc_range_nid(size, alignment, base,
-                                       limit, nid, false);
+                                       limit, nid, true);
                        if (!addr) {
                                ret = -ENOMEM;
                                goto err;
index fd988b7..8637560 100644 (file)
@@ -2316,15 +2316,26 @@ static enum compact_result compact_zone_order(struct zone *zone, int order,
                .page = NULL,
        };
 
-       current->capture_control = &capc;
+       /*
+        * Make sure the structs are really initialized before we expose the
+        * capture control, in case we are interrupted and the interrupt handler
+        * frees a page.
+        */
+       barrier();
+       WRITE_ONCE(current->capture_control, &capc);
 
        ret = compact_zone(&cc, &capc);
 
        VM_BUG_ON(!list_empty(&cc.freepages));
        VM_BUG_ON(!list_empty(&cc.migratepages));
 
-       *capture = capc.page;
-       current->capture_control = NULL;
+       /*
+        * Make sure we hide capture control first before we read the captured
+        * page pointer, otherwise an interrupt could free and capture a page
+        * and we would leak it.
+        */
+       WRITE_ONCE(current->capture_control, NULL);
+       *capture = READ_ONCE(capc.page);
 
        return ret;
 }
index b5b1de8..4f37651 100644 (file)
@@ -120,9 +120,9 @@ void __dump_page(struct page *page, const char *reason)
                 * mapping can be invalid pointer and we don't want to crash
                 * accessing it, so probe everything depending on it carefully
                 */
-               if (probe_kernel_read(&host, &mapping->host,
+               if (copy_from_kernel_nofault(&host, &mapping->host,
                                        sizeof(struct inode *)) ||
-                   probe_kernel_read(&a_ops, &mapping->a_ops,
+                   copy_from_kernel_nofault(&a_ops, &mapping->a_ops,
                                sizeof(struct address_space_operations *))) {
                        pr_warn("failed to read mapping->host or a_ops, mapping not a valid kernel address?\n");
                        goto out_mapping;
@@ -133,7 +133,7 @@ void __dump_page(struct page *page, const char *reason)
                        goto out_mapping;
                }
 
-               if (probe_kernel_read(&dentry_first,
+               if (copy_from_kernel_nofault(&dentry_first,
                        &host->i_dentry.first, sizeof(struct hlist_node *))) {
                        pr_warn("mapping->a_ops:%ps with invalid mapping->host inode address %px\n",
                                a_ops, host);
@@ -146,7 +146,7 @@ void __dump_page(struct page *page, const char *reason)
                }
 
                dentry_ptr = container_of(dentry_first, struct dentry, d_u.d_alias);
-               if (probe_kernel_read(&dentry, dentry_ptr,
+               if (copy_from_kernel_nofault(&dentry, dentry_ptr,
                                                        sizeof(struct dentry))) {
                        pr_warn("mapping->aops:%ps with invalid mapping->host->i_dentry.first %px\n",
                                a_ops, dentry_ptr);
index e456230..61ab16f 100644 (file)
@@ -246,13 +246,13 @@ static void __init pgd_populate_tests(struct mm_struct *mm, pgd_t *pgdp,
 static void __init pte_clear_tests(struct mm_struct *mm, pte_t *ptep,
                                   unsigned long vaddr)
 {
-       pte_t pte = READ_ONCE(*ptep);
+       pte_t pte = ptep_get(ptep);
 
        pte = __pte(pte_val(pte) | RANDOM_ORVALUE);
        set_pte_at(mm, vaddr, ptep, pte);
        barrier();
        pte_clear(mm, vaddr, ptep);
-       pte = READ_ONCE(*ptep);
+       pte = ptep_get(ptep);
        WARN_ON(!pte_none(pte));
 }
 
index f0ae9a6..385759c 100644 (file)
@@ -2028,7 +2028,7 @@ find_page:
 
                page = find_get_page(mapping, index);
                if (!page) {
-                       if (iocb->ki_flags & IOCB_NOWAIT)
+                       if (iocb->ki_flags & (IOCB_NOWAIT | IOCB_NOIO))
                                goto would_block;
                        page_cache_sync_readahead(mapping,
                                        ra, filp,
@@ -2038,6 +2038,10 @@ find_page:
                                goto no_cached_page;
                }
                if (PageReadahead(page)) {
+                       if (iocb->ki_flags & IOCB_NOIO) {
+                               put_page(page);
+                               goto out;
+                       }
                        page_cache_async_readahead(mapping,
                                        ra, filp, page,
                                        index, last_index - index);
@@ -2160,6 +2164,11 @@ page_not_up_to_date_locked:
                }
 
 readpage:
+               if (iocb->ki_flags & IOCB_NOIO) {
+                       unlock_page(page);
+                       put_page(page);
+                       goto would_block;
+               }
                /*
                 * A previous I/O error may have been due to temporary
                 * failures, eg. multipath errors.
@@ -2249,9 +2258,19 @@ EXPORT_SYMBOL_GPL(generic_file_buffered_read);
  *
  * This is the "read_iter()" routine for all filesystems
  * that can use the page cache directly.
+ *
+ * The IOCB_NOWAIT flag in iocb->ki_flags indicates that -EAGAIN shall
+ * be returned when no data can be read without waiting for I/O requests
+ * to complete; it doesn't prevent readahead.
+ *
+ * The IOCB_NOIO flag in iocb->ki_flags indicates that no new I/O
+ * requests shall be made for the read or for readahead.  When no data
+ * can be read, -EAGAIN shall be returned.  When readahead would be
+ * triggered, a partial, possibly empty read shall be returned.
+ *
  * Return:
  * * number of bytes copied, even for partial reads
- * * negative error code if nothing was read
+ * * negative error code (or 0 if IOCB_NOIO) if nothing was read
  */
 ssize_t
 generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
index de9e362..6f47697 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -2196,7 +2196,7 @@ static inline pte_t gup_get_pte(pte_t *ptep)
  */
 static inline pte_t gup_get_pte(pte_t *ptep)
 {
-       return READ_ONCE(*ptep);
+       return ptep_get(ptep);
 }
 #endif /* CONFIG_GUP_GET_PTE_LOW_HIGH */
 
@@ -2425,7 +2425,7 @@ static int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr,
        if (pte_end < end)
                end = pte_end;
 
-       pte = READ_ONCE(*ptep);
+       pte = huge_ptep_get(ptep);
 
        if (!pte_access_permitted(pte, flags & FOLL_WRITE))
                return 0;
index 57ece74..590111e 100644 (file)
@@ -45,7 +45,10 @@ int hugetlb_max_hstate __read_mostly;
 unsigned int default_hstate_idx;
 struct hstate hstates[HUGE_MAX_HSTATE];
 
+#ifdef CONFIG_CMA
 static struct cma *hugetlb_cma[MAX_NUMNODES];
+#endif
+static unsigned long hugetlb_cma_size __initdata;
 
 /*
  * Minimum page order among possible hugepage sizes, set to a proper value
@@ -1235,9 +1238,10 @@ static void free_gigantic_page(struct page *page, unsigned int order)
         * If the page isn't allocated using the cma allocator,
         * cma_release() returns false.
         */
-       if (IS_ENABLED(CONFIG_CMA) &&
-           cma_release(hugetlb_cma[page_to_nid(page)], page, 1 << order))
+#ifdef CONFIG_CMA
+       if (cma_release(hugetlb_cma[page_to_nid(page)], page, 1 << order))
                return;
+#endif
 
        free_contig_range(page_to_pfn(page), 1 << order);
 }
@@ -1248,7 +1252,8 @@ static struct page *alloc_gigantic_page(struct hstate *h, gfp_t gfp_mask,
 {
        unsigned long nr_pages = 1UL << huge_page_order(h);
 
-       if (IS_ENABLED(CONFIG_CMA)) {
+#ifdef CONFIG_CMA
+       {
                struct page *page;
                int node;
 
@@ -1262,6 +1267,7 @@ static struct page *alloc_gigantic_page(struct hstate *h, gfp_t gfp_mask,
                                return page;
                }
        }
+#endif
 
        return alloc_contig_pages(nr_pages, gfp_mask, nid, nodemask);
 }
@@ -1593,7 +1599,7 @@ static struct address_space *_get_hugetlb_page_mapping(struct page *hpage)
 
        /* Use first found vma */
        pgoff_start = page_to_pgoff(hpage);
-       pgoff_end = pgoff_start + hpage_nr_pages(hpage) - 1;
+       pgoff_end = pgoff_start + pages_per_huge_page(page_hstate(hpage)) - 1;
        anon_vma_interval_tree_foreach(avc, &anon_vma->rb_root,
                                        pgoff_start, pgoff_end) {
                struct vm_area_struct *vma = avc->vma;
@@ -2571,7 +2577,7 @@ static void __init hugetlb_hstate_alloc_pages(struct hstate *h)
 
        for (i = 0; i < h->max_huge_pages; ++i) {
                if (hstate_is_gigantic(h)) {
-                       if (IS_ENABLED(CONFIG_CMA) && hugetlb_cma[0]) {
+                       if (hugetlb_cma_size) {
                                pr_warn_once("HugeTLB: hugetlb_cma is enabled, skip boot time allocation\n");
                                break;
                        }
@@ -5654,7 +5660,6 @@ void move_hugetlb_state(struct page *oldpage, struct page *newpage, int reason)
 }
 
 #ifdef CONFIG_CMA
-static unsigned long hugetlb_cma_size __initdata;
 static bool cma_reserve_called __initdata;
 
 static int __init cmdline_parse_hugetlb_cma(char *p)
index b043c40..700f516 100644 (file)
@@ -958,6 +958,9 @@ static int hugepage_vma_revalidate(struct mm_struct *mm, unsigned long address,
                return SCAN_ADDRESS_RANGE;
        if (!hugepage_vma_check(vma, vma->vm_flags))
                return SCAN_VMA_CHECK;
+       /* Anon VMA expected */
+       if (!vma->anon_vma || vma->vm_ops)
+               return SCAN_VMA_CHECK;
        return 0;
 }
 
index 88845ed..f98ff91 100644 (file)
@@ -6,14 +6,15 @@
 #include <linux/mm.h>
 #include <linux/uaccess.h>
 
-bool __weak probe_kernel_read_allowed(const void *unsafe_src, size_t size)
+bool __weak copy_from_kernel_nofault_allowed(const void *unsafe_src,
+               size_t size)
 {
        return true;
 }
 
 #ifdef HAVE_GET_KERNEL_NOFAULT
 
-#define probe_kernel_read_loop(dst, src, len, type, err_label)         \
+#define copy_from_kernel_nofault_loop(dst, src, len, type, err_label)  \
        while (len >= sizeof(type)) {                                   \
                __get_kernel_nofault(dst, src, type, err_label);                \
                dst += sizeof(type);                                    \
@@ -21,25 +22,25 @@ bool __weak probe_kernel_read_allowed(const void *unsafe_src, size_t size)
                len -= sizeof(type);                                    \
        }
 
-long probe_kernel_read(void *dst, const void *src, size_t size)
+long copy_from_kernel_nofault(void *dst, const void *src, size_t size)
 {
-       if (!probe_kernel_read_allowed(src, size))
+       if (!copy_from_kernel_nofault_allowed(src, size))
                return -ERANGE;
 
        pagefault_disable();
-       probe_kernel_read_loop(dst, src, size, u64, Efault);
-       probe_kernel_read_loop(dst, src, size, u32, Efault);
-       probe_kernel_read_loop(dst, src, size, u16, Efault);
-       probe_kernel_read_loop(dst, src, size, u8, Efault);
+       copy_from_kernel_nofault_loop(dst, src, size, u64, Efault);
+       copy_from_kernel_nofault_loop(dst, src, size, u32, Efault);
+       copy_from_kernel_nofault_loop(dst, src, size, u16, Efault);
+       copy_from_kernel_nofault_loop(dst, src, size, u8, Efault);
        pagefault_enable();
        return 0;
 Efault:
        pagefault_enable();
        return -EFAULT;
 }
-EXPORT_SYMBOL_GPL(probe_kernel_read);
+EXPORT_SYMBOL_GPL(copy_from_kernel_nofault);
 
-#define probe_kernel_write_loop(dst, src, len, type, err_label)                \
+#define copy_to_kernel_nofault_loop(dst, src, len, type, err_label)    \
        while (len >= sizeof(type)) {                                   \
                __put_kernel_nofault(dst, src, type, err_label);                \
                dst += sizeof(type);                                    \
@@ -47,13 +48,13 @@ EXPORT_SYMBOL_GPL(probe_kernel_read);
                len -= sizeof(type);                                    \
        }
 
-long probe_kernel_write(void *dst, const void *src, size_t size)
+long copy_to_kernel_nofault(void *dst, const void *src, size_t size)
 {
        pagefault_disable();
-       probe_kernel_write_loop(dst, src, size, u64, Efault);
-       probe_kernel_write_loop(dst, src, size, u32, Efault);
-       probe_kernel_write_loop(dst, src, size, u16, Efault);
-       probe_kernel_write_loop(dst, src, size, u8, Efault);
+       copy_to_kernel_nofault_loop(dst, src, size, u64, Efault);
+       copy_to_kernel_nofault_loop(dst, src, size, u32, Efault);
+       copy_to_kernel_nofault_loop(dst, src, size, u16, Efault);
+       copy_to_kernel_nofault_loop(dst, src, size, u8, Efault);
        pagefault_enable();
        return 0;
 Efault:
@@ -67,7 +68,7 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
 
        if (unlikely(count <= 0))
                return 0;
-       if (!probe_kernel_read_allowed(unsafe_addr, count))
+       if (!copy_from_kernel_nofault_allowed(unsafe_addr, count))
                return -ERANGE;
 
        pagefault_disable();
@@ -87,7 +88,7 @@ Efault:
 }
 #else /* HAVE_GET_KERNEL_NOFAULT */
 /**
- * probe_kernel_read(): safely attempt to read from kernel-space
+ * copy_from_kernel_nofault(): safely attempt to read from kernel-space
  * @dst: pointer to the buffer that shall take the data
  * @src: address to read from
  * @size: size of the data chunk
@@ -98,15 +99,15 @@ Efault:
  *
  * We ensure that the copy_from_user is executed in atomic context so that
  * do_page_fault() doesn't attempt to take mmap_lock.  This makes
- * probe_kernel_read() suitable for use within regions where the caller
+ * copy_from_kernel_nofault() suitable for use within regions where the caller
  * already holds mmap_lock, or other locks which nest inside mmap_lock.
  */
-long probe_kernel_read(void *dst, const void *src, size_t size)
+long copy_from_kernel_nofault(void *dst, const void *src, size_t size)
 {
        long ret;
        mm_segment_t old_fs = get_fs();
 
-       if (!probe_kernel_read_allowed(src, size))
+       if (!copy_from_kernel_nofault_allowed(src, size))
                return -ERANGE;
 
        set_fs(KERNEL_DS);
@@ -120,10 +121,10 @@ long probe_kernel_read(void *dst, const void *src, size_t size)
                return -EFAULT;
        return 0;
 }
-EXPORT_SYMBOL_GPL(probe_kernel_read);
+EXPORT_SYMBOL_GPL(copy_from_kernel_nofault);
 
 /**
- * probe_kernel_write(): safely attempt to write to a location
+ * copy_to_kernel_nofault(): safely attempt to write to a location
  * @dst: address to write to
  * @src: pointer to the data that shall be written
  * @size: size of the data chunk
@@ -131,7 +132,7 @@ EXPORT_SYMBOL_GPL(probe_kernel_read);
  * Safely write to address @dst from the buffer at @src.  If a kernel fault
  * happens, handle that and return -EFAULT.
  */
-long probe_kernel_write(void *dst, const void *src, size_t size)
+long copy_to_kernel_nofault(void *dst, const void *src, size_t size)
 {
        long ret;
        mm_segment_t old_fs = get_fs();
@@ -174,7 +175,7 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
 
        if (unlikely(count <= 0))
                return 0;
-       if (!probe_kernel_read_allowed(unsafe_addr, count))
+       if (!copy_from_kernel_nofault_allowed(unsafe_addr, count))
                return -ERANGE;
 
        set_fs(KERNEL_DS);
@@ -193,7 +194,7 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
 #endif /* HAVE_GET_KERNEL_NOFAULT */
 
 /**
- * probe_user_read(): safely attempt to read from a user-space location
+ * copy_from_user_nofault(): safely attempt to read from a user-space location
  * @dst: pointer to the buffer that shall take the data
  * @src: address to read from. This must be a user address.
  * @size: size of the data chunk
@@ -201,7 +202,7 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
  * Safely read from user address @src to the buffer at @dst. If a kernel fault
  * happens, handle that and return -EFAULT.
  */
-long probe_user_read(void *dst, const void __user *src, size_t size)
+long copy_from_user_nofault(void *dst, const void __user *src, size_t size)
 {
        long ret = -EFAULT;
        mm_segment_t old_fs = get_fs();
@@ -218,10 +219,10 @@ long probe_user_read(void *dst, const void __user *src, size_t size)
                return -EFAULT;
        return 0;
 }
-EXPORT_SYMBOL_GPL(probe_user_read);
+EXPORT_SYMBOL_GPL(copy_from_user_nofault);
 
 /**
- * probe_user_write(): safely attempt to write to a user-space location
+ * copy_to_user_nofault(): safely attempt to write to a user-space location
  * @dst: address to write to
  * @src: pointer to the data that shall be written
  * @size: size of the data chunk
@@ -229,7 +230,7 @@ EXPORT_SYMBOL_GPL(probe_user_read);
  * Safely write to address @dst from the buffer at @src.  If a kernel fault
  * happens, handle that and return -EFAULT.
  */
-long probe_user_write(void __user *dst, const void *src, size_t size)
+long copy_to_user_nofault(void __user *dst, const void *src, size_t size)
 {
        long ret = -EFAULT;
        mm_segment_t old_fs = get_fs();
@@ -246,7 +247,7 @@ long probe_user_write(void __user *dst, const void *src, size_t size)
                return -EFAULT;
        return 0;
 }
-EXPORT_SYMBOL_GPL(probe_user_write);
+EXPORT_SYMBOL_GPL(copy_to_user_nofault);
 
 /**
  * strncpy_from_user_nofault: - Copy a NUL terminated string from unsafe user
index 0b38b6a..13f559a 100644 (file)
@@ -2772,8 +2772,10 @@ static void memcg_schedule_kmem_cache_create(struct mem_cgroup *memcg,
                return;
 
        cw = kmalloc(sizeof(*cw), GFP_NOWAIT | __GFP_NOWARN);
-       if (!cw)
+       if (!cw) {
+               css_put(&memcg->css);
                return;
+       }
 
        cw->memcg = memcg;
        cw->cachep = cachep;
@@ -5667,7 +5669,6 @@ static void __mem_cgroup_clear_mc(void)
                if (!mem_cgroup_is_root(mc.to))
                        page_counter_uncharge(&mc.to->memory, mc.moved_swap);
 
-               mem_cgroup_id_get_many(mc.to, mc.moved_swap);
                css_put_many(&mc.to->css, mc.moved_swap);
 
                mc.moved_swap = 0;
@@ -5858,7 +5859,8 @@ put:                      /* get_mctgt_type() gets the page */
                        ent = target.ent;
                        if (!mem_cgroup_move_swap_account(ent, mc.from, mc.to)) {
                                mc.precharge--;
-                               /* we fixup refcnts and charges later. */
+                               mem_cgroup_id_get_many(mc.to, 1);
+                               /* we fixup other refcnts and charges later. */
                                mc.moved_swap++;
                        }
                        break;
@@ -6360,11 +6362,16 @@ static unsigned long effective_protection(unsigned long usage,
         * We're using unprotected memory for the weight so that if
         * some cgroups DO claim explicit protection, we don't protect
         * the same bytes twice.
+        *
+        * Check both usage and parent_usage against the respective
+        * protected values. One should imply the other, but they
+        * aren't read atomically - make sure the division is sane.
         */
        if (!(cgrp_dfl_root.flags & CGRP_ROOT_MEMORY_RECURSIVE_PROT))
                return ep;
-
-       if (parent_effective > siblings_protected && usage > protected) {
+       if (parent_effective > siblings_protected &&
+           parent_usage > siblings_protected &&
+           usage > protected) {
                unsigned long unclaimed;
 
                unclaimed = parent_effective - siblings_protected;
@@ -6416,7 +6423,7 @@ enum mem_cgroup_protection mem_cgroup_protected(struct mem_cgroup *root,
 
        if (parent == root) {
                memcg->memory.emin = READ_ONCE(memcg->memory.min);
-               memcg->memory.elow = memcg->memory.low;
+               memcg->memory.elow = READ_ONCE(memcg->memory.low);
                goto out;
        }
 
@@ -6428,7 +6435,8 @@ enum mem_cgroup_protection mem_cgroup_protected(struct mem_cgroup *root,
                        atomic_long_read(&parent->memory.children_min_usage)));
 
        WRITE_ONCE(memcg->memory.elow, effective_protection(usage, parent_usage,
-                       memcg->memory.low, READ_ONCE(parent->memory.elow),
+                       READ_ONCE(memcg->memory.low),
+                       READ_ONCE(parent->memory.elow),
                        atomic_long_read(&parent->memory.children_low_usage)));
 
 out:
@@ -7178,6 +7186,13 @@ static struct cftype memsw_files[] = {
        { },    /* terminate */
 };
 
+/*
+ * If mem_cgroup_swap_init() is implemented as a subsys_initcall()
+ * instead of a core_initcall(), this could mean cgroup_memory_noswap still
+ * remains set to false even when memcg is disabled via "cgroup_disable=memory"
+ * boot parameter. This may result in premature OOPS inside
+ * mem_cgroup_get_nr_swap_pages() function in corner cases.
+ */
 static int __init mem_cgroup_swap_init(void)
 {
        /* No memory control -> no swap control */
@@ -7192,6 +7207,6 @@ static int __init mem_cgroup_swap_init(void)
 
        return 0;
 }
-subsys_initcall(mem_cgroup_swap_init);
+core_initcall(mem_cgroup_swap_init);
 
 #endif /* CONFIG_MEMCG_SWAP */
index dc7f354..3ecad55 100644 (file)
@@ -1498,7 +1498,7 @@ out:
 }
 
 #ifdef pte_index
-static int insert_page_in_batch_locked(struct mm_struct *mm, pmd_t *pmd,
+static int insert_page_in_batch_locked(struct mm_struct *mm, pte_t *pte,
                        unsigned long addr, struct page *page, pgprot_t prot)
 {
        int err;
@@ -1506,8 +1506,9 @@ static int insert_page_in_batch_locked(struct mm_struct *mm, pmd_t *pmd,
        if (!page_count(page))
                return -EINVAL;
        err = validate_page_before_insert(page);
-       return err ? err : insert_page_into_pte_locked(
-               mm, pte_offset_map(pmd, addr), addr, page, prot);
+       if (err)
+               return err;
+       return insert_page_into_pte_locked(mm, pte, addr, page, prot);
 }
 
 /* insert_pages() amortizes the cost of spinlock operations
@@ -1517,7 +1518,8 @@ static int insert_pages(struct vm_area_struct *vma, unsigned long addr,
                        struct page **pages, unsigned long *num, pgprot_t prot)
 {
        pmd_t *pmd = NULL;
-       spinlock_t *pte_lock = NULL;
+       pte_t *start_pte, *pte;
+       spinlock_t *pte_lock;
        struct mm_struct *const mm = vma->vm_mm;
        unsigned long curr_page_idx = 0;
        unsigned long remaining_pages_total = *num;
@@ -1536,18 +1538,17 @@ more:
        ret = -ENOMEM;
        if (pte_alloc(mm, pmd))
                goto out;
-       pte_lock = pte_lockptr(mm, pmd);
 
        while (pages_to_write_in_pmd) {
                int pte_idx = 0;
                const int batch_size = min_t(int, pages_to_write_in_pmd, 8);
 
-               spin_lock(pte_lock);
-               for (; pte_idx < batch_size; ++pte_idx) {
-                       int err = insert_page_in_batch_locked(mm, pmd,
+               start_pte = pte_offset_map_lock(mm, pmd, addr, &pte_lock);
+               for (pte = start_pte; pte_idx < batch_size; ++pte, ++pte_idx) {
+                       int err = insert_page_in_batch_locked(mm, pte,
                                addr, pages[curr_page_idx], prot);
                        if (unlikely(err)) {
-                               spin_unlock(pte_lock);
+                               pte_unmap_unlock(start_pte, pte_lock);
                                ret = err;
                                remaining_pages_total -= pte_idx;
                                goto out;
@@ -1555,7 +1556,7 @@ more:
                        addr += PAGE_SIZE;
                        ++curr_page_idx;
                }
-               spin_unlock(pte_lock);
+               pte_unmap_unlock(start_pte, pte_lock);
                pages_to_write_in_pmd -= batch_size;
                remaining_pages_total -= batch_size;
        }
@@ -1600,7 +1601,7 @@ int vm_insert_pages(struct vm_area_struct *vma, unsigned long addr,
        return insert_pages(vma, addr, pages, num, vma->vm_page_prot);
 #else
        unsigned long idx = 0, pgcount = *num;
-       int err;
+       int err = -EINVAL;
 
        for (; idx < pgcount; ++idx) {
                err = vm_insert_page(vma, addr + (PAGE_SIZE * idx), pages[idx]);
@@ -3140,8 +3141,18 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
                                err = mem_cgroup_charge(page, vma->vm_mm,
                                                        GFP_KERNEL);
                                ClearPageSwapCache(page);
-                               if (err)
+                               if (err) {
+                                       ret = VM_FAULT_OOM;
                                        goto out_page;
+                               }
+
+                               /*
+                                * XXX: Move to lru_cache_add() when it
+                                * supports new vs putback
+                                */
+                               spin_lock_irq(&page_pgdat(page)->lru_lock);
+                               lru_note_cost_page(page);
+                               spin_unlock_irq(&page_pgdat(page)->lru_lock);
 
                                lru_cache_add(page);
                                swap_readpage(page, true);
index 9b34e03..da374cd 100644 (file)
@@ -471,11 +471,20 @@ void __ref remove_pfn_range_from_zone(struct zone *zone,
                                      unsigned long start_pfn,
                                      unsigned long nr_pages)
 {
+       const unsigned long end_pfn = start_pfn + nr_pages;
        struct pglist_data *pgdat = zone->zone_pgdat;
-       unsigned long flags;
+       unsigned long pfn, cur_nr_pages, flags;
 
        /* Poison struct pages because they are now uninitialized again. */
-       page_init_poison(pfn_to_page(start_pfn), sizeof(struct page) * nr_pages);
+       for (pfn = start_pfn; pfn < end_pfn; pfn += cur_nr_pages) {
+               cond_resched();
+
+               /* Select all remaining pages up to the next section boundary */
+               cur_nr_pages =
+                       min(end_pfn - pfn, SECTION_ALIGN_UP(pfn + 1) - pfn);
+               page_init_poison(pfn_to_page(pfn),
+                                sizeof(struct page) * cur_nr_pages);
+       }
 
 #ifdef CONFIG_ZONE_DEVICE
        /*
index f377296..40cd701 100644 (file)
@@ -1160,22 +1160,11 @@ out:
        return rc;
 }
 
-/*
- * gcc 4.7 and 4.8 on arm get an ICEs when inlining unmap_and_move().  Work
- * around it.
- */
-#if defined(CONFIG_ARM) && \
-       defined(GCC_VERSION) && GCC_VERSION < 40900 && GCC_VERSION >= 40700
-#define ICE_noinline noinline
-#else
-#define ICE_noinline
-#endif
-
 /*
  * Obtain the lock on page, remove all ptes and migrate the page
  * to the newly allocated page in newpage.
  */
-static ICE_noinline int unmap_and_move(new_page_t get_new_page,
+static int unmap_and_move(new_page_t get_new_page,
                                   free_page_t put_new_page,
                                   unsigned long private, struct page *page,
                                   int force, enum migrate_mode mode,
index 59a4682..8c7ca73 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2620,7 +2620,7 @@ static void unmap_region(struct mm_struct *mm,
  * Create a list of vma's touched by the unmap, removing them from the mm's
  * vma list as we go..
  */
-static void
+static bool
 detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma,
        struct vm_area_struct *prev, unsigned long end)
 {
@@ -2645,6 +2645,17 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma,
 
        /* Kill the cache */
        vmacache_invalidate(mm);
+
+       /*
+        * Do not downgrade mmap_lock if we are next to VM_GROWSDOWN or
+        * VM_GROWSUP VMA. Such VMAs can change their size under
+        * down_read(mmap_lock) and collide with the VMA we are about to unmap.
+        */
+       if (vma && (vma->vm_flags & VM_GROWSDOWN))
+               return false;
+       if (prev && (prev->vm_flags & VM_GROWSUP))
+               return false;
+       return true;
 }
 
 /*
@@ -2825,7 +2836,8 @@ int __do_munmap(struct mm_struct *mm, unsigned long start, size_t len,
        }
 
        /* Detach vmas from rbtree */
-       detach_vmas_to_be_unmapped(mm, vma, prev, end);
+       if (!detach_vmas_to_be_unmapped(mm, vma, prev, end))
+               downgrade = false;
 
        if (downgrade)
                mmap_write_downgrade(mm);
index 5dd572d..6b153dc 100644 (file)
@@ -206,9 +206,28 @@ static bool move_normal_pmd(struct vm_area_struct *vma, unsigned long old_addr,
 
        /*
         * The destination pmd shouldn't be established, free_pgtables()
-        * should have release it.
+        * should have released it.
+        *
+        * However, there's a case during execve() where we use mremap
+        * to move the initial stack, and in that case the target area
+        * may overlap the source area (always moving down).
+        *
+        * If everything is PMD-aligned, that works fine, as moving
+        * each pmd down will clear the source pmd. But if we first
+        * have a few 4kB-only pages that get moved down, and then
+        * hit the "now the rest is PMD-aligned, let's do everything
+        * one pmd at a time", we will still have the old (now empty
+        * of any 4kB pages, but still there) PMD in the page table
+        * tree.
+        *
+        * Warn on it once - because we really should try to figure
+        * out how to do this better - but then say "I won't move
+        * this pmd".
+        *
+        * One alternative might be to just unmap the target pmd at
+        * this point, and verify that it really is empty. We'll see.
         */
-       if (WARN_ON(!pmd_none(*new_pmd)))
+       if (WARN_ON_ONCE(!pmd_none(*new_pmd)))
                return false;
 
        /*
index cdcad5d..f32a690 100644 (file)
@@ -290,23 +290,6 @@ void *vzalloc_node(unsigned long size, int node)
 }
 EXPORT_SYMBOL(vzalloc_node);
 
-/**
- *     vmalloc_exec  -  allocate virtually contiguous, executable memory
- *     @size:          allocation size
- *
- *     Kernel-internal function to allocate enough pages to cover @size
- *     the page level allocator and map them into contiguous and
- *     executable kernel virtual space.
- *
- *     For tight control over page level allocator and protection flags
- *     use __vmalloc() instead.
- */
-
-void *vmalloc_exec(unsigned long size)
-{
-       return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM);
-}
-
 /**
  * vmalloc_32  -  allocate virtually contiguous memory (32bit addressable)
  *     @size:          allocation size
index 48eb0f1..e028b87 100644 (file)
@@ -7832,7 +7832,7 @@ void setup_per_zone_wmarks(void)
  * Initialise min_free_kbytes.
  *
  * For small machines we want it small (128k min).  For large machines
- * we want it large (64MB max).  But it is not linear, because network
+ * we want it large (256MB max).  But it is not linear, because network
  * bandwidth does not increase linearly with machine size.  We use
  *
  *     min_free_kbytes = 4 * sqrt(lowmem_kbytes), for better accuracy:
index 5e313fa..2a99df7 100644 (file)
@@ -25,7 +25,7 @@ void rodata_test(void)
        }
 
        /* test 2: write to the variable; this should fault */
-       if (!probe_kernel_write((void *)&rodata_test_data,
+       if (!copy_to_kernel_nofault((void *)&rodata_test_data,
                                (void *)&zero, sizeof(zero))) {
                pr_err("test data was not read only\n");
                return;
index a0dbe62..b2abca3 100644 (file)
@@ -3178,7 +3178,7 @@ static int shmem_initxattrs(struct inode *inode,
                new_xattr->name = kmalloc(XATTR_SECURITY_PREFIX_LEN + len,
                                          GFP_KERNEL);
                if (!new_xattr->name) {
-                       kfree(new_xattr);
+                       kvfree(new_xattr);
                        return -ENOMEM;
                }
 
index 207c83e..74f7e09 100644 (file)
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -348,7 +348,7 @@ static __always_inline int memcg_charge_slab(struct page *page,
                                             gfp_t gfp, int order,
                                             struct kmem_cache *s)
 {
-       unsigned int nr_pages = 1 << order;
+       int nr_pages = 1 << order;
        struct mem_cgroup *memcg;
        struct lruvec *lruvec;
        int ret;
@@ -388,7 +388,7 @@ out:
 static __always_inline void memcg_uncharge_slab(struct page *page, int order,
                                                struct kmem_cache *s)
 {
-       unsigned int nr_pages = 1 << order;
+       int nr_pages = 1 << order;
        struct mem_cgroup *memcg;
        struct lruvec *lruvec;
 
index 9e72ba2..fe8b684 100644 (file)
@@ -326,6 +326,14 @@ int slab_unmergeable(struct kmem_cache *s)
        if (s->refcount < 0)
                return 1;
 
+#ifdef CONFIG_MEMCG_KMEM
+       /*
+        * Skip the dying kmem_cache.
+        */
+       if (s->memcg_params.dying)
+               return 1;
+#endif
+
        return 0;
 }
 
@@ -886,12 +894,15 @@ static int shutdown_memcg_caches(struct kmem_cache *s)
        return 0;
 }
 
-static void flush_memcg_workqueue(struct kmem_cache *s)
+static void memcg_set_kmem_cache_dying(struct kmem_cache *s)
 {
        spin_lock_irq(&memcg_kmem_wq_lock);
        s->memcg_params.dying = true;
        spin_unlock_irq(&memcg_kmem_wq_lock);
+}
 
+static void flush_memcg_workqueue(struct kmem_cache *s)
+{
        /*
         * SLAB and SLUB deactivate the kmem_caches through call_rcu. Make
         * sure all registered rcu callbacks have been invoked.
@@ -923,10 +934,6 @@ static inline int shutdown_memcg_caches(struct kmem_cache *s)
 {
        return 0;
 }
-
-static inline void flush_memcg_workqueue(struct kmem_cache *s)
-{
-}
 #endif /* CONFIG_MEMCG_KMEM */
 
 void slab_kmem_cache_release(struct kmem_cache *s)
@@ -944,8 +951,6 @@ void kmem_cache_destroy(struct kmem_cache *s)
        if (unlikely(!s))
                return;
 
-       flush_memcg_workqueue(s);
-
        get_online_cpus();
        get_online_mems();
 
@@ -955,6 +960,22 @@ void kmem_cache_destroy(struct kmem_cache *s)
        if (s->refcount)
                goto out_unlock;
 
+#ifdef CONFIG_MEMCG_KMEM
+       memcg_set_kmem_cache_dying(s);
+
+       mutex_unlock(&slab_mutex);
+
+       put_online_mems();
+       put_online_cpus();
+
+       flush_memcg_workqueue(s);
+
+       get_online_cpus();
+       get_online_mems();
+
+       mutex_lock(&slab_mutex);
+#endif
+
        err = shutdown_memcg_caches(s);
        if (!err)
                err = shutdown_cache(s);
@@ -1726,7 +1747,7 @@ void kzfree(const void *p)
        if (unlikely(ZERO_OR_NULL_PTR(mem)))
                return;
        ks = ksize(mem);
-       memset(mem, 0, ks);
+       memzero_explicit(mem, ks);
        kfree(mem);
 }
 EXPORT_SYMBOL(kzfree);
index b8f798b..ef30307 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -292,7 +292,7 @@ static inline void *get_freepointer_safe(struct kmem_cache *s, void *object)
                return get_freepointer(s, object);
 
        freepointer_addr = (unsigned long)object + s->offset;
-       probe_kernel_read(&p, (void **)freepointer_addr, sizeof(p));
+       copy_from_kernel_nofault(&p, (void **)freepointer_addr, sizeof(p));
        return freelist_ptr(s, p, freepointer_addr);
 }
 
@@ -3766,15 +3766,13 @@ error:
 }
 
 static void list_slab_objects(struct kmem_cache *s, struct page *page,
-                             const char *text, unsigned long *map)
+                             const char *text)
 {
 #ifdef CONFIG_SLUB_DEBUG
        void *addr = page_address(page);
+       unsigned long *map;
        void *p;
 
-       if (!map)
-               return;
-
        slab_err(s, page, text, s->name);
        slab_lock(page);
 
@@ -3786,6 +3784,7 @@ static void list_slab_objects(struct kmem_cache *s, struct page *page,
                        print_tracking(s, p);
                }
        }
+       put_map(map);
        slab_unlock(page);
 #endif
 }
@@ -3799,11 +3798,6 @@ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n)
 {
        LIST_HEAD(discard);
        struct page *page, *h;
-       unsigned long *map = NULL;
-
-#ifdef CONFIG_SLUB_DEBUG
-       map = bitmap_alloc(oo_objects(s->max), GFP_KERNEL);
-#endif
 
        BUG_ON(irqs_disabled());
        spin_lock_irq(&n->list_lock);
@@ -3813,16 +3807,11 @@ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n)
                        list_add(&page->slab_list, &discard);
                } else {
                        list_slab_objects(s, page,
-                         "Objects remaining in %s on __kmem_cache_shutdown()",
-                         map);
+                         "Objects remaining in %s on __kmem_cache_shutdown()");
                }
        }
        spin_unlock_irq(&n->list_lock);
 
-#ifdef CONFIG_SLUB_DEBUG
-       bitmap_free(map);
-#endif
-
        list_for_each_entry_safe(page, h, &discard, slab_list)
                discard_slab(s, page);
 }
index dbcab84..a82efc3 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -443,8 +443,7 @@ void mark_page_accessed(struct page *page)
                else
                        __lru_cache_activate_page(page);
                ClearPageReferenced(page);
-               if (page_is_file_lru(page))
-                       workingset_activation(page);
+               workingset_activation(page);
        }
        if (page_is_idle(page))
                clear_page_idle(page);
index e98ff46..05889e8 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/vmalloc.h>
 #include <linux/swap_slots.h>
 #include <linux/huge_mm.h>
-
+#include "internal.h"
 
 /*
  * swapper_space is a fiction, retained to simplify the path through
@@ -429,7 +429,7 @@ struct page *__read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
        __SetPageSwapBacked(page);
 
        /* May fail (-ENOMEM) if XArray node allocation failed. */
-       if (add_to_swap_cache(page, entry, gfp_mask & GFP_KERNEL)) {
+       if (add_to_swap_cache(page, entry, gfp_mask & GFP_RECLAIM_MASK)) {
                put_swap_page(page, entry);
                goto fail_unlock;
        }
index 3091c2c..5a2b55c 100644 (file)
@@ -1862,7 +1862,6 @@ EXPORT_SYMBOL(vm_unmap_ram);
  * @pages: an array of pointers to the pages to be mapped
  * @count: number of pages
  * @node: prefer to allocate data structures on this node
- * @prot: memory protection to use. PAGE_KERNEL for regular RAM
  *
  * If you use this function for less than VMAP_MAX_ALLOC pages, it could be
  * faster than vmap so it's good.  But if you mix long-life and short-life
@@ -2696,26 +2695,6 @@ void *vzalloc_node(unsigned long size, int node)
 }
 EXPORT_SYMBOL(vzalloc_node);
 
-/**
- * vmalloc_exec - allocate virtually contiguous, executable memory
- * @size:        allocation size
- *
- * Kernel-internal function to allocate enough pages to cover @size
- * the page level allocator and map them into contiguous and
- * executable kernel virtual space.
- *
- * For tight control over page level allocator and protection flags
- * use __vmalloc() instead.
- *
- * Return: pointer to the allocated memory or %NULL on error
- */
-void *vmalloc_exec(unsigned long size)
-{
-       return __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END,
-                       GFP_KERNEL, PAGE_KERNEL_EXEC, VM_FLUSH_RESET_PERMS,
-                       NUMA_NO_NODE, __builtin_return_address(0));
-}
-
 #if defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA32)
 #define GFP_VMALLOC32 (GFP_DMA32 | GFP_KERNEL)
 #elif defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA)
index b6d8432..749d239 100644 (file)
@@ -904,6 +904,7 @@ static int __remove_mapping(struct address_space *mapping, struct page *page,
                __delete_from_swap_cache(page, swap);
                xa_unlock_irqrestore(&mapping->i_pages, flags);
                put_swap_page(page, swap);
+               workingset_eviction(page, target_memcg);
        } else {
                void (*freepage)(struct page *);
                void *shadow = NULL;
@@ -1884,6 +1885,8 @@ static unsigned noinline_for_stack move_pages_to_lru(struct lruvec *lruvec,
                                list_add(&page->lru, &pages_to_free);
                } else {
                        nr_moved += nr_pages;
+                       if (PageActive(page))
+                               workingset_age_nonresident(lruvec, nr_pages);
                }
        }
 
index d481ea4..50b7937 100644 (file)
  *
  *             Implementation
  *
- * For each node's file LRU lists, a counter for inactive evictions
- * and activations is maintained (node->inactive_age).
+ * For each node's LRU lists, a counter for inactive evictions and
+ * activations is maintained (node->nonresident_age).
  *
  * On eviction, a snapshot of this counter (along with some bits to
  * identify the node) is stored in the now empty page cache
@@ -213,7 +213,17 @@ static void unpack_shadow(void *shadow, int *memcgidp, pg_data_t **pgdat,
        *workingsetp = workingset;
 }
 
-static void advance_inactive_age(struct mem_cgroup *memcg, pg_data_t *pgdat)
+/**
+ * workingset_age_nonresident - age non-resident entries as LRU ages
+ * @memcg: the lruvec that was aged
+ * @nr_pages: the number of pages to count
+ *
+ * As in-memory pages are aged, non-resident pages need to be aged as
+ * well, in order for the refault distances later on to be comparable
+ * to the in-memory dimensions. This function allows reclaim and LRU
+ * operations to drive the non-resident aging along in parallel.
+ */
+void workingset_age_nonresident(struct lruvec *lruvec, unsigned long nr_pages)
 {
        /*
         * Reclaiming a cgroup means reclaiming all its children in a
@@ -227,11 +237,8 @@ static void advance_inactive_age(struct mem_cgroup *memcg, pg_data_t *pgdat)
         * the root cgroup's, age as well.
         */
        do {
-               struct lruvec *lruvec;
-
-               lruvec = mem_cgroup_lruvec(memcg, pgdat);
-               atomic_long_inc(&lruvec->inactive_age);
-       } while (memcg && (memcg = parent_mem_cgroup(memcg)));
+               atomic_long_add(nr_pages, &lruvec->nonresident_age);
+       } while ((lruvec = parent_lruvec(lruvec)));
 }
 
 /**
@@ -254,12 +261,11 @@ void *workingset_eviction(struct page *page, struct mem_cgroup *target_memcg)
        VM_BUG_ON_PAGE(page_count(page), page);
        VM_BUG_ON_PAGE(!PageLocked(page), page);
 
-       advance_inactive_age(page_memcg(page), pgdat);
-
        lruvec = mem_cgroup_lruvec(target_memcg, pgdat);
+       workingset_age_nonresident(lruvec, hpage_nr_pages(page));
        /* XXX: target_memcg can be NULL, go through lruvec */
        memcgid = mem_cgroup_id(lruvec_memcg(lruvec));
-       eviction = atomic_long_read(&lruvec->inactive_age);
+       eviction = atomic_long_read(&lruvec->nonresident_age);
        return pack_shadow(memcgid, pgdat, eviction, PageWorkingset(page));
 }
 
@@ -309,20 +315,20 @@ void workingset_refault(struct page *page, void *shadow)
        if (!mem_cgroup_disabled() && !eviction_memcg)
                goto out;
        eviction_lruvec = mem_cgroup_lruvec(eviction_memcg, pgdat);
-       refault = atomic_long_read(&eviction_lruvec->inactive_age);
+       refault = atomic_long_read(&eviction_lruvec->nonresident_age);
 
        /*
         * Calculate the refault distance
         *
         * The unsigned subtraction here gives an accurate distance
-        * across inactive_age overflows in most cases. There is a
+        * across nonresident_age overflows in most cases. There is a
         * special case: usually, shadow entries have a short lifetime
         * and are either refaulted or reclaimed along with the inode
         * before they get too old.  But it is not impossible for the
-        * inactive_age to lap a shadow entry in the field, which can
-        * then result in a false small refault distance, leading to a
-        * false activation should this old entry actually refault
-        * again.  However, earlier kernels used to deactivate
+        * nonresident_age to lap a shadow entry in the field, which
+        * can then result in a false small refault distance, leading
+        * to a false activation should this old entry actually
+        * refault again.  However, earlier kernels used to deactivate
         * unconditionally with *every* reclaim invocation for the
         * longest time, so the occasional inappropriate activation
         * leading to pressure on the active list is not a problem.
@@ -359,7 +365,7 @@ void workingset_refault(struct page *page, void *shadow)
                goto out;
 
        SetPageActive(page);
-       advance_inactive_age(memcg, pgdat);
+       workingset_age_nonresident(lruvec, hpage_nr_pages(page));
        inc_lruvec_state(lruvec, WORKINGSET_ACTIVATE);
 
        /* Page was active prior to eviction */
@@ -382,6 +388,7 @@ out:
 void workingset_activation(struct page *page)
 {
        struct mem_cgroup *memcg;
+       struct lruvec *lruvec;
 
        rcu_read_lock();
        /*
@@ -394,7 +401,8 @@ void workingset_activation(struct page *page)
        memcg = page_memcg_rcu(page);
        if (!mem_cgroup_disabled() && !memcg)
                goto out;
-       advance_inactive_age(memcg, page_pgdat(page));
+       lruvec = mem_cgroup_page_lruvec(page, page_pgdat(page));
+       workingset_age_nonresident(lruvec, hpage_nr_pages(page));
 out:
        rcu_read_unlock();
 }
index c8d6a07..3dd7c97 100644 (file)
@@ -503,11 +503,10 @@ static void vlan_dev_set_lockdep_one(struct net_device *dev,
        lockdep_set_class(&txq->_xmit_lock, &vlan_netdev_xmit_lock_key);
 }
 
-static void vlan_dev_set_lockdep_class(struct net_device *dev, int subclass)
+static void vlan_dev_set_lockdep_class(struct net_device *dev)
 {
-       lockdep_set_class_and_subclass(&dev->addr_list_lock,
-                                      &vlan_netdev_addr_lock_key,
-                                      subclass);
+       lockdep_set_class(&dev->addr_list_lock,
+                         &vlan_netdev_addr_lock_key);
        netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, NULL);
 }
 
@@ -601,7 +600,7 @@ static int vlan_dev_init(struct net_device *dev)
 
        SET_NETDEV_DEVTYPE(dev, &vlan_type);
 
-       vlan_dev_set_lockdep_class(dev, dev->lower_level);
+       vlan_dev_set_lockdep_class(dev);
 
        vlan->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats);
        if (!vlan->vlan_pcpu_stats)
index c1b6242..5126566 100644 (file)
@@ -189,3 +189,4 @@ MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>");
 MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
 MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>");
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Plan 9 Resource Sharing Support (9P2000)");
index 13cd683..12ecacf 100644 (file)
@@ -362,6 +362,10 @@ static void p9_read_work(struct work_struct *work)
                if (m->rreq->status == REQ_STATUS_SENT) {
                        list_del(&m->rreq->req_list);
                        p9_client_cb(m->client, m->rreq, REQ_STATUS_RCVD);
+               } else if (m->rreq->status == REQ_STATUS_FLSHD) {
+                       /* Ignore replies associated with a cancelled request. */
+                       p9_debug(P9_DEBUG_TRANS,
+                                "Ignore replies associated with a cancelled request\n");
                } else {
                        spin_unlock(&m->client->lock);
                        p9_debug(P9_DEBUG_ERROR,
@@ -703,11 +707,20 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req)
 {
        p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req);
 
+       spin_lock(&client->lock);
+       /* Ignore cancelled request if message has been received
+        * before lock.
+        */
+       if (req->status == REQ_STATUS_RCVD) {
+               spin_unlock(&client->lock);
+               return 0;
+       }
+
        /* we haven't received a response for oldreq,
         * remove it from the list.
         */
-       spin_lock(&client->lock);
        list_del(&req->req_list);
+       req->status = REQ_STATUS_FLSHD;
        spin_unlock(&client->lock);
        p9_req_put(req);
 
@@ -803,20 +816,28 @@ static int p9_fd_open(struct p9_client *client, int rfd, int wfd)
                return -ENOMEM;
 
        ts->rd = fget(rfd);
+       if (!ts->rd)
+               goto out_free_ts;
+       if (!(ts->rd->f_mode & FMODE_READ))
+               goto out_put_rd;
        ts->wr = fget(wfd);
-       if (!ts->rd || !ts->wr) {
-               if (ts->rd)
-                       fput(ts->rd);
-               if (ts->wr)
-                       fput(ts->wr);
-               kfree(ts);
-               return -EIO;
-       }
+       if (!ts->wr)
+               goto out_put_rd;
+       if (!(ts->wr->f_mode & FMODE_WRITE))
+               goto out_put_wr;
 
        client->trans = ts;
        client->status = Connected;
 
        return 0;
+
+out_put_wr:
+       fput(ts->wr);
+out_put_rd:
+       fput(ts->rd);
+out_free_ts:
+       kfree(ts);
+       return -EIO;
 }
 
 static int p9_socket_open(struct p9_client *client, struct socket *csocket)
index fd91cd3..dec3f35 100644 (file)
@@ -1187,7 +1187,10 @@ static int __must_check ax25_connect(struct socket *sock,
        if (addr_len > sizeof(struct sockaddr_ax25) &&
            fsa->fsa_ax25.sax25_ndigis != 0) {
                /* Valid number of digipeaters ? */
-               if (fsa->fsa_ax25.sax25_ndigis < 1 || fsa->fsa_ax25.sax25_ndigis > AX25_MAX_DIGIS) {
+               if (fsa->fsa_ax25.sax25_ndigis < 1 ||
+                   fsa->fsa_ax25.sax25_ndigis > AX25_MAX_DIGIS ||
+                   addr_len < sizeof(struct sockaddr_ax25) +
+                   sizeof(ax25_address) * fsa->fsa_ax25.sax25_ndigis) {
                        err = -EINVAL;
                        goto out_release;
                }
@@ -1507,7 +1510,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
                        struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)usax;
 
                        /* Valid number of digipeaters ? */
-                       if (usax->sax25_ndigis < 1 || usax->sax25_ndigis > AX25_MAX_DIGIS) {
+                       if (usax->sax25_ndigis < 1 ||
+                           usax->sax25_ndigis > AX25_MAX_DIGIS ||
+                           addr_len < sizeof(struct sockaddr_ax25) +
+                           sizeof(ax25_address) * usax->sax25_ndigis) {
                                err = -EINVAL;
                                goto out;
                        }
index cfeaee3..af9d7f2 100644 (file)
@@ -1338,6 +1338,9 @@ static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr,
 {
        struct discovery_state *d = &hdev->discovery;
 
+       if (len > HCI_MAX_AD_LENGTH)
+               return;
+
        bacpy(&d->last_adv_addr, bdaddr);
        d->last_adv_addr_type = bdaddr_type;
        d->last_adv_rssi = rssi;
@@ -5355,7 +5358,8 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
 
 static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
                               u8 bdaddr_type, bdaddr_t *direct_addr,
-                              u8 direct_addr_type, s8 rssi, u8 *data, u8 len)
+                              u8 direct_addr_type, s8 rssi, u8 *data, u8 len,
+                              bool ext_adv)
 {
        struct discovery_state *d = &hdev->discovery;
        struct smp_irk *irk;
@@ -5377,6 +5381,11 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
                return;
        }
 
+       if (!ext_adv && len > HCI_MAX_AD_LENGTH) {
+               bt_dev_err_ratelimited(hdev, "legacy adv larger than 31 bytes");
+               return;
+       }
+
        /* Find the end of the data in case the report contains padded zero
         * bytes at the end causing an invalid length value.
         *
@@ -5437,7 +5446,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
         */
        conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, type,
                                                                direct_addr);
-       if (conn && type == LE_ADV_IND) {
+       if (!ext_adv && conn && type == LE_ADV_IND && len <= HCI_MAX_AD_LENGTH) {
                /* Store report for later inclusion by
                 * mgmt_device_connected
                 */
@@ -5491,7 +5500,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
         * event or send an immediate device found event if the data
         * should not be stored for later.
         */
-       if (!has_pending_adv_report(hdev)) {
+       if (!ext_adv && !has_pending_adv_report(hdev)) {
                /* If the report will trigger a SCAN_REQ store it for
                 * later merging.
                 */
@@ -5526,7 +5535,8 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
                /* If the new report will trigger a SCAN_REQ store it for
                 * later merging.
                 */
-               if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
+               if (!ext_adv && (type == LE_ADV_IND ||
+                                type == LE_ADV_SCAN_IND)) {
                        store_pending_adv_report(hdev, bdaddr, bdaddr_type,
                                                 rssi, flags, data, len);
                        return;
@@ -5566,7 +5576,7 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
                        rssi = ev->data[ev->length];
                        process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
                                           ev->bdaddr_type, NULL, 0, rssi,
-                                          ev->data, ev->length);
+                                          ev->data, ev->length, false);
                } else {
                        bt_dev_err(hdev, "Dropping invalid advertising data");
                }
@@ -5638,7 +5648,8 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
                if (legacy_evt_type != LE_ADV_INVALID) {
                        process_adv_report(hdev, legacy_evt_type, &ev->bdaddr,
                                           ev->bdaddr_type, NULL, 0, ev->rssi,
-                                          ev->data, ev->length);
+                                          ev->data, ev->length,
+                                          !(evt_type & LE_EXT_ADV_LEGACY_PDU));
                }
 
                ptr += sizeof(*ev) + ev->length;
@@ -5836,7 +5847,8 @@ static void hci_le_direct_adv_report_evt(struct hci_dev *hdev,
 
                process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
                                   ev->bdaddr_type, &ev->direct_addr,
-                                  ev->direct_addr_type, ev->rssi, NULL, 0);
+                                  ev->direct_addr_type, ev->rssi, NULL, 0,
+                                  false);
 
                ptr += sizeof(*ev);
        }
index bfd4ccd..b03c469 100644 (file)
@@ -147,6 +147,20 @@ int noinline bpf_fentry_test6(u64 a, void *b, short c, int d, void *e, u64 f)
        return a + (long)b + c + d + (long)e + f;
 }
 
+struct bpf_fentry_test_t {
+       struct bpf_fentry_test_t *a;
+};
+
+int noinline bpf_fentry_test7(struct bpf_fentry_test_t *arg)
+{
+       return (long)arg;
+}
+
+int noinline bpf_fentry_test8(struct bpf_fentry_test_t *arg)
+{
+       return (long)arg->a;
+}
+
 int noinline bpf_modify_return_test(int a, int *b)
 {
        *b += 1;
@@ -185,6 +199,7 @@ int bpf_prog_test_run_tracing(struct bpf_prog *prog,
                              const union bpf_attr *kattr,
                              union bpf_attr __user *uattr)
 {
+       struct bpf_fentry_test_t arg = {};
        u16 side_effect = 0, ret = 0;
        int b = 2, err = -EFAULT;
        u32 retval = 0;
@@ -197,7 +212,9 @@ int bpf_prog_test_run_tracing(struct bpf_prog *prog,
                    bpf_fentry_test3(4, 5, 6) != 15 ||
                    bpf_fentry_test4((void *)7, 8, 9, 10) != 34 ||
                    bpf_fentry_test5(11, (void *)12, 13, 14, 15) != 65 ||
-                   bpf_fentry_test6(16, (void *)17, 18, 19, (void *)20, 21) != 111)
+                   bpf_fentry_test6(16, (void *)17, 18, 19, (void *)20, 21) != 111 ||
+                   bpf_fentry_test7((struct bpf_fentry_test_t *)0) != 0 ||
+                   bpf_fentry_test8(&arg) != 0)
                        goto out;
                break;
        case BPF_MODIFY_RETURN:
index c0f0990..1905e01 100644 (file)
@@ -50,7 +50,7 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname,
        req.len = optlen;
        if (!bpfilter_ops.info.pid)
                goto out;
-       n = __kernel_write(bpfilter_ops.info.pipe_to_umh, &req, sizeof(req),
+       n = kernel_write(bpfilter_ops.info.pipe_to_umh, &req, sizeof(req),
                           &pos);
        if (n != sizeof(req)) {
                pr_err("write fail %zd\n", n);
index 24986ec..90592af 100644 (file)
@@ -86,7 +86,7 @@ static struct sk_buff *br_mrp_skb_alloc(struct net_bridge_port *p,
 {
        struct ethhdr *eth_hdr;
        struct sk_buff *skb;
-       u16 *version;
+       __be16 *version;
 
        skb = dev_alloc_skb(MRP_MAX_FRAME_LENGTH);
        if (!skb)
@@ -411,10 +411,16 @@ int br_mrp_set_port_role(struct net_bridge_port *p,
        if (!mrp)
                return -EINVAL;
 
-       if (role == BR_MRP_PORT_ROLE_PRIMARY)
+       switch (role) {
+       case BR_MRP_PORT_ROLE_PRIMARY:
                rcu_assign_pointer(mrp->p_port, p);
-       else
+               break;
+       case BR_MRP_PORT_ROLE_SECONDARY:
                rcu_assign_pointer(mrp->s_port, p);
+               break;
+       default:
+               return -EINVAL;
+       }
 
        br_mrp_port_switchdev_set_role(p, role);
 
index 83490bf..4c4a93a 100644 (file)
@@ -1007,7 +1007,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
                nsrcs_offset = len + offsetof(struct mld2_grec, grec_nsrcs);
 
                if (skb_transport_offset(skb) + ipv6_transport_len(skb) <
-                   nsrcs_offset + sizeof(_nsrcs))
+                   nsrcs_offset + sizeof(__nsrcs))
                        return -EINVAL;
 
                _nsrcs = skb_header_pointer(skb, nsrcs_offset,
index 7501be4..e0ea6db 100644 (file)
@@ -217,8 +217,8 @@ struct net_bridge_port_group {
        struct rcu_head                 rcu;
        struct timer_list               timer;
        struct br_ip                    addr;
+       unsigned char                   eth_addr[ETH_ALEN] __aligned(2);
        unsigned char                   flags;
-       unsigned char                   eth_addr[ETH_ALEN];
 };
 
 struct net_bridge_mdb_entry {
@@ -430,7 +430,7 @@ struct net_bridge {
        struct hlist_head               fdb_list;
 
 #if IS_ENABLED(CONFIG_BRIDGE_MRP)
-       struct list_head                __rcu mrp_list;
+       struct list_head                mrp_list;
 #endif
 };
 
index 33b255e..315eb37 100644 (file)
@@ -8,7 +8,7 @@
 
 struct br_mrp {
        /* list of mrp instances */
-       struct list_head                __rcu list;
+       struct list_head                list;
 
        struct net_bridge_port __rcu    *p_port;
        struct net_bridge_port __rcu    *s_port;
index 7c9e92b..8e8ffac 100644 (file)
@@ -155,3 +155,4 @@ module_exit(nft_meta_bridge_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("wenxu <wenxu@ucloud.cn>");
 MODULE_ALIAS_NFT_AF_EXPR(AF_BRIDGE, "meta");
+MODULE_DESCRIPTION("Support for bridge dedicated meta key");
index f48cf4c..deae2c9 100644 (file)
@@ -455,3 +455,4 @@ module_exit(nft_reject_bridge_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
 MODULE_ALIAS_NFT_AF_EXPR(AF_BRIDGE, "reject");
+MODULE_DESCRIPTION("Reject packets from bridge via nftables");
index afe0e81..4e7edd7 100644 (file)
@@ -332,6 +332,7 @@ struct ceph_options *ceph_alloc_options(void)
        opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT;
        opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT;
        opt->osd_request_timeout = CEPH_OSD_REQUEST_TIMEOUT_DEFAULT;
+       opt->read_from_replica = CEPH_READ_FROM_REPLICA_DEFAULT;
        return opt;
 }
 EXPORT_SYMBOL(ceph_alloc_options);
@@ -490,16 +491,13 @@ int ceph_parse_param(struct fs_parameter *param, struct ceph_options *opt,
        case Opt_read_from_replica:
                switch (result.uint_32) {
                case Opt_read_from_replica_no:
-                       opt->osd_req_flags &= ~(CEPH_OSD_FLAG_BALANCE_READS |
-                                               CEPH_OSD_FLAG_LOCALIZE_READS);
+                       opt->read_from_replica = 0;
                        break;
                case Opt_read_from_replica_balance:
-                       opt->osd_req_flags |= CEPH_OSD_FLAG_BALANCE_READS;
-                       opt->osd_req_flags &= ~CEPH_OSD_FLAG_LOCALIZE_READS;
+                       opt->read_from_replica = CEPH_OSD_FLAG_BALANCE_READS;
                        break;
                case Opt_read_from_replica_localize:
-                       opt->osd_req_flags |= CEPH_OSD_FLAG_LOCALIZE_READS;
-                       opt->osd_req_flags &= ~CEPH_OSD_FLAG_BALANCE_READS;
+                       opt->read_from_replica = CEPH_OSD_FLAG_LOCALIZE_READS;
                        break;
                default:
                        BUG();
@@ -613,9 +611,9 @@ int ceph_print_client_options(struct seq_file *m, struct ceph_client *client,
                }
                seq_putc(m, ',');
        }
-       if (opt->osd_req_flags & CEPH_OSD_FLAG_BALANCE_READS) {
+       if (opt->read_from_replica == CEPH_OSD_FLAG_BALANCE_READS) {
                seq_puts(m, "read_from_replica=balance,");
-       } else if (opt->osd_req_flags & CEPH_OSD_FLAG_LOCALIZE_READS) {
+       } else if (opt->read_from_replica == CEPH_OSD_FLAG_LOCALIZE_READS) {
                seq_puts(m, "read_from_replica=localize,");
        }
 
index 4fea3c3..2db8b44 100644 (file)
@@ -445,8 +445,10 @@ static void target_copy(struct ceph_osd_request_target *dest,
        dest->size = src->size;
        dest->min_size = src->min_size;
        dest->sort_bitwise = src->sort_bitwise;
+       dest->recovery_deletes = src->recovery_deletes;
 
        dest->flags = src->flags;
+       dest->used_replica = src->used_replica;
        dest->paused = src->paused;
 
        dest->epoch = src->epoch;
@@ -1117,10 +1119,10 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
                                       truncate_size, truncate_seq);
        }
 
-       req->r_flags = flags;
        req->r_base_oloc.pool = layout->pool_id;
        req->r_base_oloc.pool_ns = ceph_try_get_string(layout->pool_ns);
        ceph_oid_printf(&req->r_base_oid, "%llx.%08llx", vino.ino, objnum);
+       req->r_flags = flags | osdc->client->options->read_from_replica;
 
        req->r_snapid = vino.snap;
        if (flags & CEPH_OSD_FLAG_WRITE)
@@ -2431,14 +2433,11 @@ promote:
 
 static void account_request(struct ceph_osd_request *req)
 {
-       struct ceph_osd_client *osdc = req->r_osdc;
-
        WARN_ON(req->r_flags & (CEPH_OSD_FLAG_ACK | CEPH_OSD_FLAG_ONDISK));
        WARN_ON(!(req->r_flags & (CEPH_OSD_FLAG_READ | CEPH_OSD_FLAG_WRITE)));
 
        req->r_flags |= CEPH_OSD_FLAG_ONDISK;
-       req->r_flags |= osdc->client->options->osd_req_flags;
-       atomic_inc(&osdc->num_requests);
+       atomic_inc(&req->r_osdc->num_requests);
 
        req->r_start_stamp = jiffies;
        req->r_start_latency = ktime_get();
index 6bc2388..7a774eb 100644 (file)
@@ -4192,10 +4192,12 @@ int dev_direct_xmit(struct sk_buff *skb, u16 queue_id)
 
        local_bh_disable();
 
+       dev_xmit_recursion_inc();
        HARD_TX_LOCK(dev, txq, smp_processor_id());
        if (!netif_xmit_frozen_or_drv_stopped(txq))
                ret = netdev_start_xmit(skb, dev, txq, false);
        HARD_TX_UNLOCK(dev, txq);
+       dev_xmit_recursion_dec();
 
        local_bh_enable();
 
@@ -5599,7 +5601,7 @@ static void flush_backlog(struct work_struct *work)
        skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) {
                if (skb->dev->reg_state == NETREG_UNREGISTERING) {
                        __skb_unlink(skb, &sd->input_pkt_queue);
-                       kfree_skb(skb);
+                       dev_kfree_skb_irq(skb);
                        input_queue_head_incr(sd);
                }
        }
@@ -9547,6 +9549,13 @@ int register_netdevice(struct net_device *dev)
                rcu_barrier();
 
                dev->reg_state = NETREG_UNREGISTERED;
+               /* We should put the kobject that hold in
+                * netdev_unregister_kobject(), otherwise
+                * the net device cannot be freed when
+                * driver calls free_netdev(), because the
+                * kobject is being hold.
+                */
+               kobject_put(&dev->dev.kobj);
        }
        /*
         *      Prevent userspace races by waiting until the network
index 6393ba9..54cd568 100644 (file)
@@ -690,6 +690,15 @@ void dev_uc_unsync(struct net_device *to, struct net_device *from)
        if (to->addr_len != from->addr_len)
                return;
 
+       /* netif_addr_lock_bh() uses lockdep subclass 0, this is okay for two
+        * reasons:
+        * 1) This is always called without any addr_list_lock, so as the
+        *    outermost one here, it must be 0.
+        * 2) This is called by some callers after unlinking the upper device,
+        *    so the dev->lower_level becomes 1 again.
+        * Therefore, the subclass for 'from' is 0, for 'to' is either 1 or
+        * larger.
+        */
        netif_addr_lock_bh(from);
        netif_addr_lock_nested(to);
        __hw_addr_unsync(&to->uc, &from->uc, to->addr_len);
@@ -911,6 +920,7 @@ void dev_mc_unsync(struct net_device *to, struct net_device *from)
        if (to->addr_len != from->addr_len)
                return;
 
+       /* See the above comments inside dev_uc_unsync(). */
        netif_addr_lock_bh(from);
        netif_addr_lock_nested(to);
        __hw_addr_unsync(&to->mc, &from->mc, to->addr_len);
index 2ee7bc4..b09bebe 100644 (file)
@@ -1721,3 +1721,4 @@ module_exit(exit_net_drop_monitor);
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Neil Horman <nhorman@tuxdriver.com>");
 MODULE_ALIAS_GENL_FAMILY("NET_DM");
+MODULE_DESCRIPTION("Monitoring code for network dropped packet alerts");
index 7339538..82e1b5b 100644 (file)
@@ -5853,12 +5853,16 @@ BPF_CALL_1(bpf_skb_ecn_set_ce, struct sk_buff *, skb)
 {
        unsigned int iphdr_len;
 
-       if (skb->protocol == cpu_to_be16(ETH_P_IP))
+       switch (skb_protocol(skb, true)) {
+       case cpu_to_be16(ETH_P_IP):
                iphdr_len = sizeof(struct iphdr);
-       else if (skb->protocol == cpu_to_be16(ETH_P_IPV6))
+               break;
+       case cpu_to_be16(ETH_P_IPV6):
                iphdr_len = sizeof(struct ipv6hdr);
-       else
+               break;
+       default:
                return 0;
+       }
 
        if (skb_headlen(skb) < iphdr_len)
                return 0;
index d02df0b..142a882 100644 (file)
@@ -70,10 +70,10 @@ void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
 EXPORT_SYMBOL(skb_flow_dissector_init);
 
 #ifdef CONFIG_BPF_SYSCALL
-int flow_dissector_bpf_prog_attach(struct net *net, struct bpf_prog *prog)
+int flow_dissector_bpf_prog_attach_check(struct net *net,
+                                        struct bpf_prog *prog)
 {
        enum netns_bpf_attach_type type = NETNS_BPF_FLOW_DISSECTOR;
-       struct bpf_prog *attached;
 
        if (net == &init_net) {
                /* BPF flow dissector in the root namespace overrides
@@ -86,26 +86,17 @@ int flow_dissector_bpf_prog_attach(struct net *net, struct bpf_prog *prog)
                for_each_net(ns) {
                        if (ns == &init_net)
                                continue;
-                       if (rcu_access_pointer(ns->bpf.progs[type]))
+                       if (rcu_access_pointer(ns->bpf.run_array[type]))
                                return -EEXIST;
                }
        } else {
                /* Make sure root flow dissector is not attached
                 * when attaching to the non-root namespace.
                 */
-               if (rcu_access_pointer(init_net.bpf.progs[type]))
+               if (rcu_access_pointer(init_net.bpf.run_array[type]))
                        return -EEXIST;
        }
 
-       attached = rcu_dereference_protected(net->bpf.progs[type],
-                                            lockdep_is_held(&netns_bpf_mutex));
-       if (attached == prog)
-               /* The same program cannot be attached twice */
-               return -EINVAL;
-
-       rcu_assign_pointer(net->bpf.progs[type], prog);
-       if (attached)
-               bpf_prog_put(attached);
        return 0;
 }
 #endif /* CONFIG_BPF_SYSCALL */
@@ -903,7 +894,6 @@ bool __skb_flow_dissect(const struct net *net,
        struct flow_dissector_key_addrs *key_addrs;
        struct flow_dissector_key_tags *key_tags;
        struct flow_dissector_key_vlan *key_vlan;
-       struct bpf_prog *attached = NULL;
        enum flow_dissect_ret fdret;
        enum flow_dissector_key_id dissector_vlan = FLOW_DISSECTOR_KEY_MAX;
        bool mpls_el = false;
@@ -960,14 +950,14 @@ bool __skb_flow_dissect(const struct net *net,
        WARN_ON_ONCE(!net);
        if (net) {
                enum netns_bpf_attach_type type = NETNS_BPF_FLOW_DISSECTOR;
+               struct bpf_prog_array *run_array;
 
                rcu_read_lock();
-               attached = rcu_dereference(init_net.bpf.progs[type]);
-
-               if (!attached)
-                       attached = rcu_dereference(net->bpf.progs[type]);
+               run_array = rcu_dereference(init_net.bpf.run_array[type]);
+               if (!run_array)
+                       run_array = rcu_dereference(net->bpf.run_array[type]);
 
-               if (attached) {
+               if (run_array) {
                        struct bpf_flow_keys flow_keys;
                        struct bpf_flow_dissector ctx = {
                                .flow_keys = &flow_keys,
@@ -975,6 +965,7 @@ bool __skb_flow_dissect(const struct net *net,
                                .data_end = data + hlen,
                        };
                        __be16 n_proto = proto;
+                       struct bpf_prog *prog;
 
                        if (skb) {
                                ctx.skb = skb;
@@ -985,7 +976,8 @@ bool __skb_flow_dissect(const struct net *net,
                                n_proto = skb->protocol;
                        }
 
-                       ret = bpf_flow_dissect(attached, &ctx, n_proto, nhoff,
+                       prog = READ_ONCE(run_array->items[0].prog);
+                       ret = bpf_flow_dissect(prog, &ctx, n_proto, nhoff,
                                               hlen, flags);
                        __skb_flow_bpf_to_target(&flow_keys, flow_dissector,
                                                 target_container);
index 0cfc35e..2076219 100644 (file)
@@ -4,6 +4,7 @@
 #include <net/flow_offload.h>
 #include <linux/rtnetlink.h>
 #include <linux/mutex.h>
+#include <linux/rhashtable.h>
 
 struct flow_rule *flow_rule_alloc(unsigned int num_actions)
 {
@@ -372,14 +373,15 @@ int flow_indr_dev_register(flow_indr_block_bind_cb_t *cb, void *cb_priv)
 }
 EXPORT_SYMBOL(flow_indr_dev_register);
 
-static void __flow_block_indr_cleanup(flow_setup_cb_t *setup_cb, void *cb_priv,
+static void __flow_block_indr_cleanup(void (*release)(void *cb_priv),
+                                     void *cb_priv,
                                      struct list_head *cleanup_list)
 {
        struct flow_block_cb *this, *next;
 
        list_for_each_entry_safe(this, next, &flow_block_indr_list, indr.list) {
-               if (this->cb == setup_cb &&
-                   this->cb_priv == cb_priv) {
+               if (this->release == release &&
+                   this->indr.cb_priv == cb_priv) {
                        list_move(&this->indr.list, cleanup_list);
                        return;
                }
@@ -397,7 +399,7 @@ static void flow_block_indr_notify(struct list_head *cleanup_list)
 }
 
 void flow_indr_dev_unregister(flow_indr_block_bind_cb_t *cb, void *cb_priv,
-                             flow_setup_cb_t *setup_cb)
+                             void (*release)(void *cb_priv))
 {
        struct flow_indr_dev *this, *next, *indr_dev = NULL;
        LIST_HEAD(cleanup_list);
@@ -418,7 +420,7 @@ void flow_indr_dev_unregister(flow_indr_block_bind_cb_t *cb, void *cb_priv,
                return;
        }
 
-       __flow_block_indr_cleanup(setup_cb, cb_priv, &cleanup_list);
+       __flow_block_indr_cleanup(release, cb_priv, &cleanup_list);
        mutex_unlock(&flow_indr_block_lock);
 
        flow_block_indr_notify(&cleanup_list);
@@ -429,32 +431,37 @@ EXPORT_SYMBOL(flow_indr_dev_unregister);
 static void flow_block_indr_init(struct flow_block_cb *flow_block,
                                 struct flow_block_offload *bo,
                                 struct net_device *dev, void *data,
+                                void *cb_priv,
                                 void (*cleanup)(struct flow_block_cb *block_cb))
 {
        flow_block->indr.binder_type = bo->binder_type;
        flow_block->indr.data = data;
+       flow_block->indr.cb_priv = cb_priv;
        flow_block->indr.dev = dev;
        flow_block->indr.cleanup = cleanup;
 }
 
-static void __flow_block_indr_binding(struct flow_block_offload *bo,
-                                     struct net_device *dev, void *data,
-                                     void (*cleanup)(struct flow_block_cb *block_cb))
+struct flow_block_cb *flow_indr_block_cb_alloc(flow_setup_cb_t *cb,
+                                              void *cb_ident, void *cb_priv,
+                                              void (*release)(void *cb_priv),
+                                              struct flow_block_offload *bo,
+                                              struct net_device *dev, void *data,
+                                              void *indr_cb_priv,
+                                              void (*cleanup)(struct flow_block_cb *block_cb))
 {
        struct flow_block_cb *block_cb;
 
-       list_for_each_entry(block_cb, &bo->cb_list, list) {
-               switch (bo->command) {
-               case FLOW_BLOCK_BIND:
-                       flow_block_indr_init(block_cb, bo, dev, data, cleanup);
-                       list_add(&block_cb->indr.list, &flow_block_indr_list);
-                       break;
-               case FLOW_BLOCK_UNBIND:
-                       list_del(&block_cb->indr.list);
-                       break;
-               }
-       }
+       block_cb = flow_block_cb_alloc(cb, cb_ident, cb_priv, release);
+       if (IS_ERR(block_cb))
+               goto out;
+
+       flow_block_indr_init(block_cb, bo, dev, data, indr_cb_priv, cleanup);
+       list_add(&block_cb->indr.list, &flow_block_indr_list);
+
+out:
+       return block_cb;
 }
+EXPORT_SYMBOL(flow_indr_block_cb_alloc);
 
 int flow_indr_dev_setup_offload(struct net_device *dev,
                                enum tc_setup_type type, void *data,
@@ -465,9 +472,8 @@ int flow_indr_dev_setup_offload(struct net_device *dev,
 
        mutex_lock(&flow_indr_block_lock);
        list_for_each_entry(this, &flow_block_indr_dev_list, list)
-               this->cb(dev, this->cb_priv, type, bo);
+               this->cb(dev, this->cb_priv, type, bo, data, cleanup);
 
-       __flow_block_indr_binding(bo, dev, data, cleanup);
        mutex_unlock(&flow_indr_block_lock);
 
        return list_empty(&bo->cb_list) ? -EOPNOTSUPP : 0;
index e353b82..7bd6440 100644 (file)
@@ -1108,7 +1108,7 @@ static ssize_t tx_timeout_show(struct netdev_queue *queue, char *buf)
        trans_timeout = queue->trans_timeout;
        spin_unlock_irq(&queue->_xmit_lock);
 
-       return sprintf(buf, "%lu", trans_timeout);
+       return sprintf(buf, fmt_ulong, trans_timeout);
 }
 
 static unsigned int get_netdev_queue_index(struct netdev_queue *queue)
index 9aedc15..85a4b01 100644 (file)
@@ -3343,7 +3343,8 @@ replay:
                 */
                if (err < 0) {
                        /* If device is not registered at all, free it now */
-                       if (dev->reg_state == NETREG_UNINITIALIZED)
+                       if (dev->reg_state == NETREG_UNINITIALIZED ||
+                           dev->reg_state == NETREG_UNREGISTERED)
                                free_netdev(dev);
                        goto out;
                }
index 351afbf..6a32a1f 100644 (file)
@@ -683,7 +683,7 @@ static struct sk_psock *sk_psock_from_strp(struct strparser *strp)
        return container_of(parser, struct sk_psock, parser);
 }
 
-static void sk_psock_skb_redirect(struct sk_psock *psock, struct sk_buff *skb)
+static void sk_psock_skb_redirect(struct sk_buff *skb)
 {
        struct sk_psock *psock_other;
        struct sock *sk_other;
@@ -715,12 +715,11 @@ static void sk_psock_skb_redirect(struct sk_psock *psock, struct sk_buff *skb)
        }
 }
 
-static void sk_psock_tls_verdict_apply(struct sk_psock *psock,
-                                      struct sk_buff *skb, int verdict)
+static void sk_psock_tls_verdict_apply(struct sk_buff *skb, int verdict)
 {
        switch (verdict) {
        case __SK_REDIRECT:
-               sk_psock_skb_redirect(psock, skb);
+               sk_psock_skb_redirect(skb);
                break;
        case __SK_PASS:
        case __SK_DROP:
@@ -741,8 +740,8 @@ int sk_psock_tls_strp_read(struct sk_psock *psock, struct sk_buff *skb)
                ret = sk_psock_bpf_run(psock, prog, skb);
                ret = sk_psock_map_verd(ret, tcp_skb_bpf_redirect_fetch(skb));
        }
+       sk_psock_tls_verdict_apply(skb, ret);
        rcu_read_unlock();
-       sk_psock_tls_verdict_apply(psock, skb, ret);
        return ret;
 }
 EXPORT_SYMBOL_GPL(sk_psock_tls_strp_read);
@@ -770,7 +769,7 @@ static void sk_psock_verdict_apply(struct sk_psock *psock,
                }
                goto out_free;
        case __SK_REDIRECT:
-               sk_psock_skb_redirect(psock, skb);
+               sk_psock_skb_redirect(skb);
                break;
        case __SK_DROP:
                /* fall-through */
@@ -782,11 +781,18 @@ out_free:
 
 static void sk_psock_strp_read(struct strparser *strp, struct sk_buff *skb)
 {
-       struct sk_psock *psock = sk_psock_from_strp(strp);
+       struct sk_psock *psock;
        struct bpf_prog *prog;
        int ret = __SK_DROP;
+       struct sock *sk;
 
        rcu_read_lock();
+       sk = strp->sk;
+       psock = sk_psock(sk);
+       if (unlikely(!psock)) {
+               kfree_skb(skb);
+               goto out;
+       }
        prog = READ_ONCE(psock->progs.skb_verdict);
        if (likely(prog)) {
                skb_orphan(skb);
@@ -794,8 +800,9 @@ static void sk_psock_strp_read(struct strparser *strp, struct sk_buff *skb)
                ret = sk_psock_bpf_run(psock, prog, skb);
                ret = sk_psock_map_verd(ret, tcp_skb_bpf_redirect_fetch(skb));
        }
-       rcu_read_unlock();
        sk_psock_verdict_apply(psock, skb, ret);
+out:
+       rcu_read_unlock();
 }
 
 static int sk_psock_strp_read_done(struct strparser *strp, int err)
index 6c4acf1..2e5b787 100644 (file)
@@ -718,7 +718,7 @@ bool sk_mc_loop(struct sock *sk)
                return inet6_sk(sk)->mc_loop;
 #endif
        }
-       WARN_ON(1);
+       WARN_ON_ONCE(1);
        return true;
 }
 EXPORT_SYMBOL(sk_mc_loop);
@@ -1767,6 +1767,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
                cgroup_sk_alloc(&sk->sk_cgrp_data);
                sock_update_classid(&sk->sk_cgrp_data);
                sock_update_netprioidx(&sk->sk_cgrp_data);
+               sk_tx_queue_clear(sk);
        }
 
        return sk;
@@ -1925,7 +1926,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
                /* sk->sk_memcg will be populated at accept() time */
                newsk->sk_memcg = NULL;
 
-               cgroup_sk_alloc(&newsk->sk_cgrp_data);
+               cgroup_sk_clone(&newsk->sk_cgrp_data);
 
                rcu_read_lock();
                filter = rcu_dereference(sk->sk_filter);
@@ -1990,6 +1991,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
                 */
                sk_refcnt_debug_inc(newsk);
                sk_set_socket(newsk, NULL);
+               sk_tx_queue_clear(newsk);
                RCU_INIT_POINTER(newsk->sk_wq, NULL);
 
                if (newsk->sk_prot->sockets_allocated)
index 4059f94..0971f17 100644 (file)
@@ -70,11 +70,49 @@ int sock_map_get_from_fd(const union bpf_attr *attr, struct bpf_prog *prog)
        struct fd f;
        int ret;
 
+       if (attr->attach_flags || attr->replace_bpf_fd)
+               return -EINVAL;
+
        f = fdget(ufd);
        map = __bpf_map_get(f);
        if (IS_ERR(map))
                return PTR_ERR(map);
-       ret = sock_map_prog_update(map, prog, attr->attach_type);
+       ret = sock_map_prog_update(map, prog, NULL, attr->attach_type);
+       fdput(f);
+       return ret;
+}
+
+int sock_map_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype)
+{
+       u32 ufd = attr->target_fd;
+       struct bpf_prog *prog;
+       struct bpf_map *map;
+       struct fd f;
+       int ret;
+
+       if (attr->attach_flags || attr->replace_bpf_fd)
+               return -EINVAL;
+
+       f = fdget(ufd);
+       map = __bpf_map_get(f);
+       if (IS_ERR(map))
+               return PTR_ERR(map);
+
+       prog = bpf_prog_get(attr->attach_bpf_fd);
+       if (IS_ERR(prog)) {
+               ret = PTR_ERR(prog);
+               goto put_map;
+       }
+
+       if (prog->type != ptype) {
+               ret = -EINVAL;
+               goto put_prog;
+       }
+
+       ret = sock_map_prog_update(map, NULL, prog, attr->attach_type);
+put_prog:
+       bpf_prog_put(prog);
+put_map:
        fdput(f);
        return ret;
 }
@@ -1203,27 +1241,32 @@ static struct sk_psock_progs *sock_map_progs(struct bpf_map *map)
 }
 
 int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog,
-                        u32 which)
+                        struct bpf_prog *old, u32 which)
 {
        struct sk_psock_progs *progs = sock_map_progs(map);
+       struct bpf_prog **pprog;
 
        if (!progs)
                return -EOPNOTSUPP;
 
        switch (which) {
        case BPF_SK_MSG_VERDICT:
-               psock_set_prog(&progs->msg_parser, prog);
+               pprog = &progs->msg_parser;
                break;
        case BPF_SK_SKB_STREAM_PARSER:
-               psock_set_prog(&progs->skb_parser, prog);
+               pprog = &progs->skb_parser;
                break;
        case BPF_SK_SKB_STREAM_VERDICT:
-               psock_set_prog(&progs->skb_verdict, prog);
+               pprog = &progs->skb_verdict;
                break;
        default:
                return -EOPNOTSUPP;
        }
 
+       if (old)
+               return psock_replace_prog(pprog, prog, old);
+
+       psock_set_prog(pprog, prog);
        return 0;
 }
 
index adcb3ae..bbdd3c7 100644 (file)
@@ -101,6 +101,7 @@ static struct sock_reuseport *reuseport_grow(struct sock_reuseport *reuse)
        more_reuse->prog = reuse->prog;
        more_reuse->reuseport_id = reuse->reuseport_id;
        more_reuse->bind_inany = reuse->bind_inany;
+       more_reuse->has_conns = reuse->has_conns;
 
        memcpy(more_reuse->socks, reuse->socks,
               reuse->num_socks * sizeof(struct sock *));
index f93f8ac..6ada114 100644 (file)
@@ -274,7 +274,7 @@ static int proc_dointvec_minmax_bpf_enable(struct ctl_table *table, int write,
        ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
        if (write && !ret) {
                if (jit_enable < 2 ||
-                   (jit_enable == 2 && bpf_dump_raw_ok())) {
+                   (jit_enable == 2 && bpf_dump_raw_ok(current_cred()))) {
                        *(int *)table->data = jit_enable;
                        if (jit_enable == 2)
                                pr_warn("bpf_jit_enable = 2 was set! NEVER use this in production, only for JIT debugging!\n");
index 90f44f3..3c45f99 100644 (file)
@@ -462,6 +462,7 @@ struct xdp_frame *xdp_convert_zc_to_xdp_frame(struct xdp_buff *xdp)
        xdpf->len = totsize - metasize;
        xdpf->headroom = 0;
        xdpf->metasize = metasize;
+       xdpf->frame_sz = PAGE_SIZE;
        xdpf->mem.type = MEM_TYPE_PAGE_ORDER0;
 
        xsk_buff_free(xdp);
index e8eaa80..d6200ff 100644 (file)
 #define DSA_HLEN       4
 #define EDSA_HLEN      8
 
+#define FRAME_TYPE_TO_CPU      0x00
+#define FRAME_TYPE_FORWARD     0x03
+
+#define TO_CPU_CODE_MGMT_TRAP          0x00
+#define TO_CPU_CODE_FRAME2REG          0x01
+#define TO_CPU_CODE_IGMP_MLD_TRAP      0x02
+#define TO_CPU_CODE_POLICY_TRAP                0x03
+#define TO_CPU_CODE_ARP_MIRROR         0x04
+#define TO_CPU_CODE_POLICY_MIRROR      0x05
+
 static struct sk_buff *edsa_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct dsa_port *dp = dsa_slave_to_port(dev);
@@ -77,6 +87,8 @@ static struct sk_buff *edsa_rcv(struct sk_buff *skb, struct net_device *dev,
                                struct packet_type *pt)
 {
        u8 *edsa_header;
+       int frame_type;
+       int code;
        int source_device;
        int source_port;
 
@@ -91,8 +103,29 @@ static struct sk_buff *edsa_rcv(struct sk_buff *skb, struct net_device *dev,
        /*
         * Check that frame type is either TO_CPU or FORWARD.
         */
-       if ((edsa_header[0] & 0xc0) != 0x00 && (edsa_header[0] & 0xc0) != 0xc0)
+       frame_type = edsa_header[0] >> 6;
+
+       switch (frame_type) {
+       case FRAME_TYPE_TO_CPU:
+               code = (edsa_header[1] & 0x6) | ((edsa_header[2] >> 4) & 1);
+
+               /*
+                * Mark the frame to never egress on any port of the same switch
+                * unless it's a trapped IGMP/MLD packet, in which case the
+                * bridge might want to forward it.
+                */
+               if (code != TO_CPU_CODE_IGMP_MLD_TRAP)
+                       skb->offload_fwd_mark = 1;
+
+               break;
+
+       case FRAME_TYPE_FORWARD:
+               skb->offload_fwd_mark = 1;
+               break;
+
+       default:
                return NULL;
+       }
 
        /*
         * Determine source device and port.
@@ -156,8 +189,6 @@ static struct sk_buff *edsa_rcv(struct sk_buff *skb, struct net_device *dev,
                        2 * ETH_ALEN);
        }
 
-       skb->offload_fwd_mark = 1;
-
        return skb;
 }
 
index 7b7a045..7194956 100644 (file)
@@ -234,6 +234,14 @@ static int ethnl_act_cable_test_tdr_cfg(const struct nlattr *nest,
        struct nlattr *tb[ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX + 1];
        int ret;
 
+       cfg->first = 100;
+       cfg->step = 100;
+       cfg->last = MAX_CABLE_LENGTH_CM;
+       cfg->pair = PHY_PAIR_ALL;
+
+       if (!nest)
+               return 0;
+
        ret = nla_parse_nested(tb, ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX, nest,
                               cable_test_tdr_act_cfg_policy, info->extack);
        if (ret < 0)
@@ -242,17 +250,12 @@ static int ethnl_act_cable_test_tdr_cfg(const struct nlattr *nest,
        if (tb[ETHTOOL_A_CABLE_TEST_TDR_CFG_FIRST])
                cfg->first = nla_get_u32(
                        tb[ETHTOOL_A_CABLE_TEST_TDR_CFG_FIRST]);
-       else
-               cfg->first = 100;
+
        if (tb[ETHTOOL_A_CABLE_TEST_TDR_CFG_LAST])
                cfg->last = nla_get_u32(tb[ETHTOOL_A_CABLE_TEST_TDR_CFG_LAST]);
-       else
-               cfg->last = MAX_CABLE_LENGTH_CM;
 
        if (tb[ETHTOOL_A_CABLE_TEST_TDR_CFG_STEP])
                cfg->step = nla_get_u32(tb[ETHTOOL_A_CABLE_TEST_TDR_CFG_STEP]);
-       else
-               cfg->step = 100;
 
        if (tb[ETHTOOL_A_CABLE_TEST_TDR_CFG_PAIR]) {
                cfg->pair = nla_get_u8(tb[ETHTOOL_A_CABLE_TEST_TDR_CFG_PAIR]);
@@ -263,8 +266,6 @@ static int ethnl_act_cable_test_tdr_cfg(const struct nlattr *nest,
                                "invalid pair parameter");
                        return -EINVAL;
                }
-       } else {
-               cfg->pair = PHY_PAIR_ALL;
        }
 
        if (cfg->first > MAX_CABLE_LENGTH_CM) {
index 423e640..aaecfc9 100644 (file)
@@ -40,9 +40,11 @@ const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] = {
        [NETIF_F_GSO_UDP_TUNNEL_BIT] =   "tx-udp_tnl-segmentation",
        [NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT] = "tx-udp_tnl-csum-segmentation",
        [NETIF_F_GSO_PARTIAL_BIT] =      "tx-gso-partial",
+       [NETIF_F_GSO_TUNNEL_REMCSUM_BIT] = "tx-tunnel-remcsum-segmentation",
        [NETIF_F_GSO_SCTP_BIT] =         "tx-sctp-segmentation",
        [NETIF_F_GSO_ESP_BIT] =          "tx-esp-segmentation",
        [NETIF_F_GSO_UDP_L4_BIT] =       "tx-udp-segmentation",
+       [NETIF_F_GSO_FRAGLIST_BIT] =     "tx-gso-list",
 
        [NETIF_F_FCOE_CRC_BIT] =         "tx-checksum-fcoe-crc",
        [NETIF_F_SCTP_CRC_BIT] =        "tx-checksum-sctp",
index b5df90c..21d5fc0 100644 (file)
@@ -2978,7 +2978,7 @@ ethtool_rx_flow_rule_create(const struct ethtool_rx_flow_spec_input *input)
                               sizeof(match->mask.ipv6.dst));
                }
                if (memcmp(v6_m_spec->ip6src, &zero_addr, sizeof(zero_addr)) ||
-                   memcmp(v6_m_spec->ip6src, &zero_addr, sizeof(zero_addr))) {
+                   memcmp(v6_m_spec->ip6dst, &zero_addr, sizeof(zero_addr))) {
                        match->dissector.used_keys |=
                                BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS);
                        match->dissector.offset[FLOW_DISSECTOR_KEY_IPV6_ADDRS] =
index 7f47ba8..afe5ac8 100644 (file)
@@ -78,19 +78,18 @@ static int linkstate_prepare_data(const struct ethnl_req_info *req_base,
 
        ret = linkstate_get_sqi(dev);
        if (ret < 0 && ret != -EOPNOTSUPP)
-               return ret;
-
+               goto out;
        data->sqi = ret;
 
        ret = linkstate_get_sqi_max(dev);
        if (ret < 0 && ret != -EOPNOTSUPP)
-               return ret;
-
+               goto out;
        data->sqi_max = ret;
 
+       ret = 0;
+out:
        ethnl_ops_complete(dev);
-
-       return 0;
+       return ret;
 }
 
 static int linkstate_reply_size(const struct ethnl_req_info *req_base,
index 88fd07f..dd8a1c1 100644 (file)
@@ -376,10 +376,17 @@ err_dev:
 }
 
 static int ethnl_default_dump_one(struct sk_buff *skb, struct net_device *dev,
-                                 const struct ethnl_dump_ctx *ctx)
+                                 const struct ethnl_dump_ctx *ctx,
+                                 struct netlink_callback *cb)
 {
+       void *ehdr;
        int ret;
 
+       ehdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
+                          &ethtool_genl_family, 0, ctx->ops->reply_cmd);
+       if (!ehdr)
+               return -EMSGSIZE;
+
        ethnl_init_reply_data(ctx->reply_data, ctx->ops, dev);
        rtnl_lock();
        ret = ctx->ops->prepare_data(ctx->req_info, ctx->reply_data, NULL);
@@ -395,6 +402,10 @@ out:
        if (ctx->ops->cleanup_data)
                ctx->ops->cleanup_data(ctx->reply_data);
        ctx->reply_data->dev = NULL;
+       if (ret < 0)
+               genlmsg_cancel(skb, ehdr);
+       else
+               genlmsg_end(skb, ehdr);
        return ret;
 }
 
@@ -411,7 +422,6 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
        int s_idx = ctx->pos_idx;
        int h, idx = 0;
        int ret = 0;
-       void *ehdr;
 
        rtnl_lock();
        for (h = ctx->pos_hash; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
@@ -431,26 +441,15 @@ restart_chain:
                        dev_hold(dev);
                        rtnl_unlock();
 
-                       ehdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
-                                          cb->nlh->nlmsg_seq,
-                                          &ethtool_genl_family, 0,
-                                          ctx->ops->reply_cmd);
-                       if (!ehdr) {
-                               dev_put(dev);
-                               ret = -EMSGSIZE;
-                               goto out;
-                       }
-                       ret = ethnl_default_dump_one(skb, dev, ctx);
+                       ret = ethnl_default_dump_one(skb, dev, ctx, cb);
                        dev_put(dev);
                        if (ret < 0) {
-                               genlmsg_cancel(skb, ehdr);
                                if (ret == -EOPNOTSUPP)
                                        goto lock_and_cont;
                                if (likely(skb->len))
                                        ret = skb->len;
                                goto out;
                        }
-                       genlmsg_end(skb, ehdr);
 lock_and_cont:
                        rtnl_lock();
                        if (net->dev_base_seq != seq) {
index cd99f54..a6f4e9f 100644 (file)
@@ -339,7 +339,7 @@ static void hsr_announce(struct timer_list *t)
        rcu_read_unlock();
 }
 
-static void hsr_del_ports(struct hsr_priv *hsr)
+void hsr_del_ports(struct hsr_priv *hsr)
 {
        struct hsr_port *port;
 
@@ -356,31 +356,12 @@ static void hsr_del_ports(struct hsr_priv *hsr)
                hsr_del_port(port);
 }
 
-/* This has to be called after all the readers are gone.
- * Otherwise we would have to check the return value of
- * hsr_port_get_hsr().
- */
-static void hsr_dev_destroy(struct net_device *hsr_dev)
-{
-       struct hsr_priv *hsr = netdev_priv(hsr_dev);
-
-       hsr_debugfs_term(hsr);
-       hsr_del_ports(hsr);
-
-       del_timer_sync(&hsr->prune_timer);
-       del_timer_sync(&hsr->announce_timer);
-
-       hsr_del_self_node(hsr);
-       hsr_del_nodes(&hsr->node_db);
-}
-
 static const struct net_device_ops hsr_device_ops = {
        .ndo_change_mtu = hsr_dev_change_mtu,
        .ndo_open = hsr_dev_open,
        .ndo_stop = hsr_dev_close,
        .ndo_start_xmit = hsr_dev_xmit,
        .ndo_fix_features = hsr_fix_features,
-       .ndo_uninit = hsr_dev_destroy,
 };
 
 static struct device_type hsr_type = {
@@ -434,6 +415,7 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
                     unsigned char multicast_spec, u8 protocol_version,
                     struct netlink_ext_ack *extack)
 {
+       bool unregister = false;
        struct hsr_priv *hsr;
        int res;
 
@@ -485,25 +467,27 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
        if (res)
                goto err_unregister;
 
+       unregister = true;
+
        res = hsr_add_port(hsr, slave[0], HSR_PT_SLAVE_A, extack);
        if (res)
-               goto err_add_slaves;
+               goto err_unregister;
 
        res = hsr_add_port(hsr, slave[1], HSR_PT_SLAVE_B, extack);
        if (res)
-               goto err_add_slaves;
+               goto err_unregister;
 
        hsr_debugfs_init(hsr, hsr_dev);
        mod_timer(&hsr->prune_timer, jiffies + msecs_to_jiffies(PRUNE_PERIOD));
 
        return 0;
 
-err_add_slaves:
-       unregister_netdevice(hsr_dev);
 err_unregister:
        hsr_del_ports(hsr);
 err_add_master:
        hsr_del_self_node(hsr);
 
+       if (unregister)
+               unregister_netdevice(hsr_dev);
        return res;
 }
index a099d7d..b8f9262 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/netdevice.h>
 #include "hsr_main.h"
 
+void hsr_del_ports(struct hsr_priv *hsr);
 void hsr_dev_setup(struct net_device *dev);
 int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
                     unsigned char multicast_spec, u8 protocol_version,
@@ -18,5 +19,4 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
 void hsr_check_carrier_and_operstate(struct hsr_priv *hsr);
 bool is_hsr_master(struct net_device *dev);
 int hsr_get_max_mtu(struct hsr_priv *hsr);
-
 #endif /* __HSR_DEVICE_H */
index ed13760..1ea1775 100644 (file)
@@ -120,13 +120,18 @@ static struct sk_buff *frame_get_stripped_skb(struct hsr_frame_info *frame,
        return skb_clone(frame->skb_std, GFP_ATOMIC);
 }
 
-static void hsr_fill_tag(struct sk_buff *skb, struct hsr_frame_info *frame,
-                        struct hsr_port *port, u8 proto_version)
+static struct sk_buff *hsr_fill_tag(struct sk_buff *skb,
+                                   struct hsr_frame_info *frame,
+                                   struct hsr_port *port, u8 proto_version)
 {
        struct hsr_ethhdr *hsr_ethhdr;
        int lane_id;
        int lsdu_size;
 
+       /* pad to minimum packet size which is 60 + 6 (HSR tag) */
+       if (skb_put_padto(skb, ETH_ZLEN + HSR_HLEN))
+               return NULL;
+
        if (port->type == HSR_PT_SLAVE_A)
                lane_id = 0;
        else
@@ -144,6 +149,8 @@ static void hsr_fill_tag(struct sk_buff *skb, struct hsr_frame_info *frame,
        hsr_ethhdr->hsr_tag.encap_proto = hsr_ethhdr->ethhdr.h_proto;
        hsr_ethhdr->ethhdr.h_proto = htons(proto_version ?
                        ETH_P_HSR : ETH_P_PRP);
+
+       return skb;
 }
 
 static struct sk_buff *create_tagged_skb(struct sk_buff *skb_o,
@@ -172,9 +179,10 @@ static struct sk_buff *create_tagged_skb(struct sk_buff *skb_o,
        memmove(dst, src, movelen);
        skb_reset_mac_header(skb);
 
-       hsr_fill_tag(skb, frame, port, port->hsr->prot_version);
-
-       return skb;
+       /* skb_put_padto free skb on error and hsr_fill_tag returns NULL in
+        * that case
+        */
+       return hsr_fill_tag(skb, frame, port, port->hsr->prot_version);
 }
 
 /* If the original frame was an HSR tagged frame, just clone it to be sent
index 03b8919..530de24 100644 (file)
@@ -325,7 +325,8 @@ void hsr_addr_subst_dest(struct hsr_node *node_src, struct sk_buff *skb,
        if (port->type != node_dst->addr_B_port)
                return;
 
-       ether_addr_copy(eth_hdr(skb)->h_dest, node_dst->macaddress_B);
+       if (is_valid_ether_addr(node_dst->macaddress_B))
+               ether_addr_copy(eth_hdr(skb)->h_dest, node_dst->macaddress_B);
 }
 
 void hsr_register_frame_in(struct hsr_node *node, struct hsr_port *port,
index e2564de..144da15 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <linux/netdevice.h>
+#include <net/rtnetlink.h>
 #include <linux/rculist.h>
 #include <linux/timer.h>
 #include <linux/etherdevice.h>
@@ -100,8 +101,10 @@ static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event,
                        master = hsr_port_get_hsr(port->hsr, HSR_PT_MASTER);
                        hsr_del_port(port);
                        if (hsr_slave_empty(master->hsr)) {
-                               unregister_netdevice_queue(master->dev,
-                                                          &list_kill);
+                               const struct rtnl_link_ops *ops;
+
+                               ops = master->dev->rtnl_link_ops;
+                               ops->dellink(master->dev, &list_kill);
                                unregister_netdevice_many(&list_kill);
                        }
                }
@@ -144,9 +147,9 @@ static int __init hsr_init(void)
 
 static void __exit hsr_exit(void)
 {
-       unregister_netdevice_notifier(&hsr_nb);
        hsr_netlink_exit();
        hsr_debugfs_remove_root();
+       unregister_netdevice_notifier(&hsr_nb);
 }
 
 module_init(hsr_init);
index 1decb25..6e14b7d 100644 (file)
@@ -83,6 +83,22 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev,
        return hsr_dev_finalize(dev, link, multicast_spec, hsr_version, extack);
 }
 
+static void hsr_dellink(struct net_device *dev, struct list_head *head)
+{
+       struct hsr_priv *hsr = netdev_priv(dev);
+
+       del_timer_sync(&hsr->prune_timer);
+       del_timer_sync(&hsr->announce_timer);
+
+       hsr_debugfs_term(hsr);
+       hsr_del_ports(hsr);
+
+       hsr_del_self_node(hsr);
+       hsr_del_nodes(&hsr->node_db);
+
+       unregister_netdevice_queue(dev, head);
+}
+
 static int hsr_fill_info(struct sk_buff *skb, const struct net_device *dev)
 {
        struct hsr_priv *hsr = netdev_priv(dev);
@@ -118,6 +134,7 @@ static struct rtnl_link_ops hsr_link_ops __read_mostly = {
        .priv_size      = sizeof(struct hsr_priv),
        .setup          = hsr_dev_setup,
        .newlink        = hsr_newlink,
+       .dellink        = hsr_dellink,
        .fill_info      = hsr_fill_info,
 };
 
index 6ecbb0c..e64e59b 100644 (file)
@@ -340,29 +340,31 @@ config NET_FOU_IP_TUNNELS
 
 config INET_AH
        tristate "IP: AH transformation"
-       select XFRM_ALGO
-       select CRYPTO
-       select CRYPTO_HMAC
-       select CRYPTO_MD5
-       select CRYPTO_SHA1
+       select XFRM_AH
        help
-         Support for IPsec AH.
+         Support for IPsec AH (Authentication Header).
+
+         AH can be used with various authentication algorithms.  Besides
+         enabling AH support itself, this option enables the generic
+         implementations of the algorithms that RFC 8221 lists as MUST be
+         implemented.  If you need any other algorithms, you'll need to enable
+         them in the crypto API.  You should also enable accelerated
+         implementations of any needed algorithms when available.
 
          If unsure, say Y.
 
 config INET_ESP
        tristate "IP: ESP transformation"
-       select XFRM_ALGO
-       select CRYPTO
-       select CRYPTO_AUTHENC
-       select CRYPTO_HMAC
-       select CRYPTO_MD5
-       select CRYPTO_CBC
-       select CRYPTO_SHA1
-       select CRYPTO_DES
-       select CRYPTO_ECHAINIV
+       select XFRM_ESP
        help
-         Support for IPsec ESP.
+         Support for IPsec ESP (Encapsulating Security Payload).
+
+         ESP can be used with various encryption and authentication algorithms.
+         Besides enabling ESP support itself, this option enables the generic
+         implementations of the algorithms that RFC 8221 lists as MUST be
+         implemented.  If you need any other algorithms, you'll need to enable
+         them in the crypto API.  You should also enable accelerated
+         implementations of any needed algorithms when available.
 
          If unsure, say Y.
 
index d14133e..5bda5ae 100644 (file)
@@ -361,3 +361,4 @@ module_exit(esp4_offload_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
 MODULE_ALIAS_XFRM_OFFLOAD_TYPE(AF_INET, XFRM_PROTO_ESP);
+MODULE_DESCRIPTION("IPV4 GSO/GRO offload support");
index e53871e..1f75dc6 100644 (file)
@@ -1109,7 +1109,7 @@ static int fib_check_nh_v4_gw(struct net *net, struct fib_nh *nh, u32 table,
                if (fl4.flowi4_scope < RT_SCOPE_LINK)
                        fl4.flowi4_scope = RT_SCOPE_LINK;
 
-               if (table)
+               if (table && table != RT_TABLE_MAIN)
                        tbl = fib_get_table(net, table);
 
                if (tbl)
index dcc79ff..abd0834 100644 (file)
@@ -1304,3 +1304,4 @@ module_init(fou_init);
 module_exit(fou_fini);
 MODULE_AUTHOR("Tom Herbert <therbert@google.com>");
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Foo over UDP");
index 956a806..e30515f 100644 (file)
@@ -427,7 +427,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
 
        ipcm_init(&ipc);
        inet->tos = ip_hdr(skb)->tos;
-       sk->sk_mark = mark;
+       ipc.sockc.mark = mark;
        daddr = ipc.addr = ip_hdr(skb)->saddr;
        saddr = fib_compute_spec_dst(skb);
 
@@ -710,10 +710,10 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info,
        icmp_param.skb    = skb_in;
        icmp_param.offset = skb_network_offset(skb_in);
        inet_sk(sk)->tos = tos;
-       sk->sk_mark = mark;
        ipcm_init(&ipc);
        ipc.addr = iph->saddr;
        ipc.opt = &icmp_param.replyopts.opt;
+       ipc.sockc.mark = mark;
 
        rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos, mark,
                               type, code, &icmp_param);
index 090d309..1720667 100644 (file)
@@ -1702,7 +1702,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
        sk->sk_protocol = ip_hdr(skb)->protocol;
        sk->sk_bound_dev_if = arg->bound_dev_if;
        sk->sk_sndbuf = sysctl_wmem_default;
-       sk->sk_mark = fl4.flowi4_mark;
+       ipc.sockc.mark = fl4.flowi4_mark;
        err = ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base,
                             len, 0, &ipc, &rt, MSG_DONTWAIT);
        if (unlikely(err)) {
index f4f1d11..0c1f364 100644 (file)
@@ -85,9 +85,10 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn,
                                   __be32 remote, __be32 local,
                                   __be32 key)
 {
-       unsigned int hash;
        struct ip_tunnel *t, *cand = NULL;
        struct hlist_head *head;
+       struct net_device *ndev;
+       unsigned int hash;
 
        hash = ip_tunnel_hash(key, remote);
        head = &itn->tunnels[hash];
@@ -162,8 +163,9 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn,
        if (t && t->dev->flags & IFF_UP)
                return t;
 
-       if (itn->fb_tunnel_dev && itn->fb_tunnel_dev->flags & IFF_UP)
-               return netdev_priv(itn->fb_tunnel_dev);
+       ndev = READ_ONCE(itn->fb_tunnel_dev);
+       if (ndev && ndev->flags & IFF_UP)
+               return netdev_priv(ndev);
 
        return NULL;
 }
@@ -1259,9 +1261,9 @@ void ip_tunnel_uninit(struct net_device *dev)
        struct ip_tunnel_net *itn;
 
        itn = net_generic(net, tunnel->ip_tnl_net_id);
-       /* fb_tunnel_dev will be unregisted in net-exit call. */
-       if (itn->fb_tunnel_dev != dev)
-               ip_tunnel_del(itn, netdev_priv(dev));
+       ip_tunnel_del(itn, netdev_priv(dev));
+       if (itn->fb_tunnel_dev == dev)
+               WRITE_ONCE(itn->fb_tunnel_dev, NULL);
 
        dst_cache_reset(&tunnel->dst_cache);
 }
index 181b7a2..f8b419e 100644 (file)
@@ -844,3 +844,21 @@ void ip_tunnel_unneed_metadata(void)
        static_branch_dec(&ip_tunnel_metadata_cnt);
 }
 EXPORT_SYMBOL_GPL(ip_tunnel_unneed_metadata);
+
+/* Returns either the correct skb->protocol value, or 0 if invalid. */
+__be16 ip_tunnel_parse_protocol(const struct sk_buff *skb)
+{
+       if (skb_network_header(skb) >= skb->head &&
+           (skb_network_header(skb) + sizeof(struct iphdr)) <= skb_tail_pointer(skb) &&
+           ip_hdr(skb)->version == 4)
+               return htons(ETH_P_IP);
+       if (skb_network_header(skb) >= skb->head &&
+           (skb_network_header(skb) + sizeof(struct ipv6hdr)) <= skb_tail_pointer(skb) &&
+           ipv6_hdr(skb)->version == 6)
+               return htons(ETH_P_IPV6);
+       return 0;
+}
+EXPORT_SYMBOL(ip_tunnel_parse_protocol);
+
+const struct header_ops ip_tunnel_header_ops = { .parse_protocol = ip_tunnel_parse_protocol };
+EXPORT_SYMBOL(ip_tunnel_header_ops);
index 1d9c8cf..460ca10 100644 (file)
@@ -441,6 +441,7 @@ static const struct net_device_ops vti_netdev_ops = {
 static void vti_tunnel_setup(struct net_device *dev)
 {
        dev->netdev_ops         = &vti_netdev_ops;
+       dev->header_ops         = &ip_tunnel_header_ops;
        dev->type               = ARPHRD_TUNNEL;
        ip_tunnel_setup(dev, vti_net_id);
 }
index 40fea52..75d35e7 100644 (file)
@@ -361,6 +361,7 @@ static const struct net_device_ops ipip_netdev_ops = {
 static void ipip_tunnel_setup(struct net_device *dev)
 {
        dev->netdev_ops         = &ipip_netdev_ops;
+       dev->header_ops         = &ip_tunnel_header_ops;
 
        dev->type               = ARPHRD_TUNNEL;
        dev->flags              = IFF_NOARP;
index c2670ea..5bf9fa0 100644 (file)
@@ -1797,11 +1797,22 @@ out_free:
        return ret;
 }
 
+void ipt_unregister_table_pre_exit(struct net *net, struct xt_table *table,
+                                  const struct nf_hook_ops *ops)
+{
+       nf_unregister_net_hooks(net, ops, hweight32(table->valid_hooks));
+}
+
+void ipt_unregister_table_exit(struct net *net, struct xt_table *table)
+{
+       __ipt_unregister_table(net, table);
+}
+
 void ipt_unregister_table(struct net *net, struct xt_table *table,
                          const struct nf_hook_ops *ops)
 {
        if (ops)
-               nf_unregister_net_hooks(net, ops, hweight32(table->valid_hooks));
+               ipt_unregister_table_pre_exit(net, table, ops);
        __ipt_unregister_table(net, table);
 }
 
@@ -1958,6 +1969,8 @@ static void __exit ip_tables_fini(void)
 
 EXPORT_SYMBOL(ipt_register_table);
 EXPORT_SYMBOL(ipt_unregister_table);
+EXPORT_SYMBOL(ipt_unregister_table_pre_exit);
+EXPORT_SYMBOL(ipt_unregister_table_exit);
 EXPORT_SYMBOL(ipt_do_table);
 module_init(ip_tables_init);
 module_exit(ip_tables_fini);
index 748dc3c..f2984c7 100644 (file)
@@ -118,3 +118,4 @@ module_exit(synproxy_tg4_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("Intercept TCP connections and establish them using syncookies");
index 9d54b40..8f7bc1e 100644 (file)
@@ -72,16 +72,24 @@ static int __net_init iptable_filter_net_init(struct net *net)
        return 0;
 }
 
+static void __net_exit iptable_filter_net_pre_exit(struct net *net)
+{
+       if (net->ipv4.iptable_filter)
+               ipt_unregister_table_pre_exit(net, net->ipv4.iptable_filter,
+                                             filter_ops);
+}
+
 static void __net_exit iptable_filter_net_exit(struct net *net)
 {
        if (!net->ipv4.iptable_filter)
                return;
-       ipt_unregister_table(net, net->ipv4.iptable_filter, filter_ops);
+       ipt_unregister_table_exit(net, net->ipv4.iptable_filter);
        net->ipv4.iptable_filter = NULL;
 }
 
 static struct pernet_operations iptable_filter_net_ops = {
        .init = iptable_filter_net_init,
+       .pre_exit = iptable_filter_net_pre_exit,
        .exit = iptable_filter_net_exit,
 };
 
index bb9266e..f703a71 100644 (file)
@@ -100,15 +100,23 @@ static int __net_init iptable_mangle_table_init(struct net *net)
        return ret;
 }
 
+static void __net_exit iptable_mangle_net_pre_exit(struct net *net)
+{
+       if (net->ipv4.iptable_mangle)
+               ipt_unregister_table_pre_exit(net, net->ipv4.iptable_mangle,
+                                             mangle_ops);
+}
+
 static void __net_exit iptable_mangle_net_exit(struct net *net)
 {
        if (!net->ipv4.iptable_mangle)
                return;
-       ipt_unregister_table(net, net->ipv4.iptable_mangle, mangle_ops);
+       ipt_unregister_table_exit(net, net->ipv4.iptable_mangle);
        net->ipv4.iptable_mangle = NULL;
 }
 
 static struct pernet_operations iptable_mangle_net_ops = {
+       .pre_exit = iptable_mangle_net_pre_exit,
        .exit = iptable_mangle_net_exit,
 };
 
index ad33687..b0143b1 100644 (file)
@@ -113,16 +113,22 @@ static int __net_init iptable_nat_table_init(struct net *net)
        return ret;
 }
 
+static void __net_exit iptable_nat_net_pre_exit(struct net *net)
+{
+       if (net->ipv4.nat_table)
+               ipt_nat_unregister_lookups(net);
+}
+
 static void __net_exit iptable_nat_net_exit(struct net *net)
 {
        if (!net->ipv4.nat_table)
                return;
-       ipt_nat_unregister_lookups(net);
-       ipt_unregister_table(net, net->ipv4.nat_table, NULL);
+       ipt_unregister_table_exit(net, net->ipv4.nat_table);
        net->ipv4.nat_table = NULL;
 }
 
 static struct pernet_operations iptable_nat_net_ops = {
+       .pre_exit = iptable_nat_net_pre_exit,
        .exit   = iptable_nat_net_exit,
 };
 
index 69697eb..9abfe6b 100644 (file)
@@ -67,15 +67,23 @@ static int __net_init iptable_raw_table_init(struct net *net)
        return ret;
 }
 
+static void __net_exit iptable_raw_net_pre_exit(struct net *net)
+{
+       if (net->ipv4.iptable_raw)
+               ipt_unregister_table_pre_exit(net, net->ipv4.iptable_raw,
+                                             rawtable_ops);
+}
+
 static void __net_exit iptable_raw_net_exit(struct net *net)
 {
        if (!net->ipv4.iptable_raw)
                return;
-       ipt_unregister_table(net, net->ipv4.iptable_raw, rawtable_ops);
+       ipt_unregister_table_exit(net, net->ipv4.iptable_raw);
        net->ipv4.iptable_raw = NULL;
 }
 
 static struct pernet_operations iptable_raw_net_ops = {
+       .pre_exit = iptable_raw_net_pre_exit,
        .exit = iptable_raw_net_exit,
 };
 
index ac633c1..415c197 100644 (file)
@@ -62,16 +62,23 @@ static int __net_init iptable_security_table_init(struct net *net)
        return ret;
 }
 
+static void __net_exit iptable_security_net_pre_exit(struct net *net)
+{
+       if (net->ipv4.iptable_security)
+               ipt_unregister_table_pre_exit(net, net->ipv4.iptable_security,
+                                             sectbl_ops);
+}
+
 static void __net_exit iptable_security_net_exit(struct net *net)
 {
        if (!net->ipv4.iptable_security)
                return;
-
-       ipt_unregister_table(net, net->ipv4.iptable_security, sectbl_ops);
+       ipt_unregister_table_exit(net, net->ipv4.iptable_security);
        net->ipv4.iptable_security = NULL;
 }
 
 static struct pernet_operations iptable_security_net_ops = {
+       .pre_exit = iptable_security_net_pre_exit,
        .exit = iptable_security_net_exit,
 };
 
index e32e41b..aba65fe 100644 (file)
@@ -34,3 +34,4 @@ module_exit(nf_flow_ipv4_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
 MODULE_ALIAS_NF_FLOWTABLE(AF_INET);
+MODULE_DESCRIPTION("Netfilter flow table support");
index abf89b9..bcdb37f 100644 (file)
@@ -107,3 +107,4 @@ module_exit(nft_dup_ipv4_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
 MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "dup");
+MODULE_DESCRIPTION("IPv4 nftables packet duplication support");
index ce29411..03df986 100644 (file)
@@ -210,3 +210,4 @@ module_exit(nft_fib4_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
 MODULE_ALIAS_NFT_AF_EXPR(2, "fib");
+MODULE_DESCRIPTION("nftables fib / ip route lookup support");
index 7e6fd5c..e408f81 100644 (file)
@@ -71,3 +71,4 @@ module_exit(nft_reject_ipv4_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
 MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "reject");
+MODULE_DESCRIPTION("IPv4 packet rejection for nftables");
index 5354272..df6fbef 100644 (file)
@@ -786,6 +786,9 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
                           inet_sk_flowi_flags(sk), faddr, saddr, 0, 0,
                           sk->sk_uid);
 
+       fl4.fl4_icmp_type = user_icmph.type;
+       fl4.fl4_icmp_code = user_icmph.code;
+
        security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
        rt = ip_route_output_flow(net, &fl4, sk);
        if (IS_ERR(rt)) {
index 1d7076b..a01efa0 100644 (file)
@@ -2027,7 +2027,7 @@ int ip_route_use_hint(struct sk_buff *skb, __be32 daddr, __be32 saddr,
                      const struct sk_buff *hint)
 {
        struct in_device *in_dev = __in_dev_get_rcu(dev);
-       struct rtable *rt = (struct rtable *)hint;
+       struct rtable *rt = skb_rtable(hint);
        struct net *net = dev_net(dev);
        int err = -EINVAL;
        u32 tag = 0;
index 810cc16..6f0caf9 100644 (file)
@@ -2691,6 +2691,9 @@ int tcp_disconnect(struct sock *sk, int flags)
        tp->window_clamp = 0;
        tp->delivered = 0;
        tp->delivered_ce = 0;
+       if (icsk->icsk_ca_ops->release)
+               icsk->icsk_ca_ops->release(sk);
+       memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv));
        tcp_set_ca_state(sk, TCP_CA_Open);
        tp->is_sack_reneg = 0;
        tcp_clear_retrans(tp);
@@ -3246,10 +3249,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
 #ifdef CONFIG_TCP_MD5SIG
        case TCP_MD5SIG:
        case TCP_MD5SIG_EXT:
-               if ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))
-                       err = tp->af_specific->md5_parse(sk, optname, optval, optlen);
-               else
-                       err = -EINVAL;
+               err = tp->af_specific->md5_parse(sk, optname, optval, optlen);
                break;
 #endif
        case TCP_USER_TIMEOUT:
@@ -4033,11 +4033,14 @@ EXPORT_SYMBOL(tcp_md5_hash_skb_data);
 
 int tcp_md5_hash_key(struct tcp_md5sig_pool *hp, const struct tcp_md5sig_key *key)
 {
+       u8 keylen = READ_ONCE(key->keylen); /* paired with WRITE_ONCE() in tcp_md5_do_add */
        struct scatterlist sg;
 
-       sg_init_one(&sg, key->key, key->keylen);
-       ahash_request_set_crypt(hp->md5_req, &sg, NULL, key->keylen);
-       return crypto_ahash_update(hp->md5_req);
+       sg_init_one(&sg, key->key, keylen);
+       ahash_request_set_crypt(hp->md5_req, &sg, NULL, keylen);
+
+       /* We use data_race() because tcp_md5_do_add() might change key->key under us */
+       return data_race(crypto_ahash_update(hp->md5_req));
 }
 EXPORT_SYMBOL(tcp_md5_hash_key);
 
index 3172e31..62878cf 100644 (file)
@@ -197,7 +197,7 @@ static void tcp_reinit_congestion_control(struct sock *sk,
        icsk->icsk_ca_setsockopt = 1;
        memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv));
 
-       if (sk->sk_state != TCP_CLOSE)
+       if (!((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)))
                tcp_init_congestion_control(sk);
 }
 
index 8f8eefd..c7bf5b2 100644 (file)
@@ -432,10 +432,9 @@ static void hystart_update(struct sock *sk, u32 delay)
 
        if (hystart_detect & HYSTART_DELAY) {
                /* obtain the minimum delay of more than sampling packets */
+               if (ca->curr_rtt > delay)
+                       ca->curr_rtt = delay;
                if (ca->sample_cnt < HYSTART_MIN_SAMPLES) {
-                       if (ca->curr_rtt > delay)
-                               ca->curr_rtt = delay;
-
                        ca->sample_cnt++;
                } else {
                        if (ca->curr_rtt > ca->delay_min +
index 83330a6..518f043 100644 (file)
@@ -261,7 +261,8 @@ static void tcp_ecn_accept_cwr(struct sock *sk, const struct sk_buff *skb)
                 * cwnd may be very low (even just 1 packet), so we should ACK
                 * immediately.
                 */
-               inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_NOW;
+               if (TCP_SKB_CB(skb)->seq != TCP_SKB_CB(skb)->end_seq)
+                       inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_NOW;
        }
 }
 
@@ -3487,10 +3488,8 @@ static void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq)
        }
 }
 
-/* This routine deals with acks during a TLP episode.
- * We mark the end of a TLP episode on receiving TLP dupack or when
- * ack is after tlp_high_seq.
- * Ref: loss detection algorithm in draft-dukkipati-tcpm-tcp-loss-probe.
+/* This routine deals with acks during a TLP episode and ends an episode by
+ * resetting tlp_high_seq. Ref: TLP algorithm in draft-ietf-tcpm-rack
  */
 static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag)
 {
@@ -3499,7 +3498,10 @@ static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag)
        if (before(ack, tp->tlp_high_seq))
                return;
 
-       if (flag & FLAG_DSACKING_ACK) {
+       if (!tp->tlp_retrans) {
+               /* TLP of new data has been acknowledged */
+               tp->tlp_high_seq = 0;
+       } else if (flag & FLAG_DSACKING_ACK) {
                /* This DSACK means original and TLP probe arrived; no loss */
                tp->tlp_high_seq = 0;
        } else if (after(ack, tp->tlp_high_seq)) {
@@ -3665,6 +3667,15 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
                tcp_in_ack_event(sk, ack_ev_flags);
        }
 
+       /* This is a deviation from RFC3168 since it states that:
+        * "When the TCP data sender is ready to set the CWR bit after reducing
+        * the congestion window, it SHOULD set the CWR bit only on the first
+        * new data packet that it transmits."
+        * We accept CWR on pure ACKs to be more robust
+        * with widely-deployed TCP implementations that do this.
+        */
+       tcp_ecn_accept_cwr(sk, skb);
+
        /* We passed data and got it acked, remove any soft error
         * log. Something worked...
         */
@@ -4572,6 +4583,7 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb)
 
        if (unlikely(tcp_try_rmem_schedule(sk, skb, skb->truesize))) {
                NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPOFODROP);
+               sk->sk_data_ready(sk);
                tcp_drop(sk, skb);
                return;
        }
@@ -4605,7 +4617,11 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb)
        if (tcp_ooo_try_coalesce(sk, tp->ooo_last_skb,
                                 skb, &fragstolen)) {
 coalesce_done:
-               tcp_grow_window(sk, skb);
+               /* For non sack flows, do not grow window to force DUPACK
+                * and trigger fast retransmit.
+                */
+               if (tcp_is_sack(tp))
+                       tcp_grow_window(sk, skb);
                kfree_skb_partial(skb, fragstolen);
                skb = NULL;
                goto add_sack;
@@ -4689,7 +4705,11 @@ add_sack:
                tcp_sack_new_ofo_skb(sk, seq, end_seq);
 end:
        if (skb) {
-               tcp_grow_window(sk, skb);
+               /* For non sack flows, do not grow window to force DUPACK
+                * and trigger fast retransmit.
+                */
+               if (tcp_is_sack(tp))
+                       tcp_grow_window(sk, skb);
                skb_condense(skb);
                skb_set_owner_r(skb, sk);
        }
@@ -4792,8 +4812,6 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
        skb_dst_drop(skb);
        __skb_pull(skb, tcp_hdr(skb)->doff * 4);
 
-       tcp_ecn_accept_cwr(sk, skb);
-
        tp->rx_opt.dsack = 0;
 
        /*  Queue data for delivery to the user.
@@ -4812,6 +4830,7 @@ queue_and_out:
                        sk_forced_mem_schedule(sk, skb->truesize);
                else if (tcp_try_rmem_schedule(sk, skb, skb->truesize)) {
                        NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPRCVQDROP);
+                       sk->sk_data_ready(sk);
                        goto drop;
                }
 
index ad6435b..04bfcbb 100644 (file)
@@ -1111,9 +1111,21 @@ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
 
        key = tcp_md5_do_lookup_exact(sk, addr, family, prefixlen, l3index);
        if (key) {
-               /* Pre-existing entry - just update that one. */
-               memcpy(key->key, newkey, newkeylen);
-               key->keylen = newkeylen;
+               /* Pre-existing entry - just update that one.
+                * Note that the key might be used concurrently.
+                * data_race() is telling kcsan that we do not care of
+                * key mismatches, since changing MD5 key on live flows
+                * can lead to packet drops.
+                */
+               data_race(memcpy(key->key, newkey, newkeylen));
+
+               /* Pairs with READ_ONCE() in tcp_md5_hash_key().
+                * Also note that a reader could catch new key->keylen value
+                * but old key->key[], this is the reason we use __GFP_ZERO
+                * at sock_kmalloc() time below these lines.
+                */
+               WRITE_ONCE(key->keylen, newkeylen);
+
                return 0;
        }
 
@@ -1129,7 +1141,7 @@ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
                rcu_assign_pointer(tp->md5sig_info, md5sig);
        }
 
-       key = sock_kmalloc(sk, sizeof(*key), gfp);
+       key = sock_kmalloc(sk, sizeof(*key), gfp | __GFP_ZERO);
        if (!key)
                return -ENOMEM;
        if (!tcp_alloc_md5sig_pool()) {
index a50e199..0bc05d6 100644 (file)
@@ -700,7 +700,8 @@ static unsigned int tcp_synack_options(const struct sock *sk,
                                       unsigned int mss, struct sk_buff *skb,
                                       struct tcp_out_options *opts,
                                       const struct tcp_md5sig_key *md5,
-                                      struct tcp_fastopen_cookie *foc)
+                                      struct tcp_fastopen_cookie *foc,
+                                      enum tcp_synack_type synack_type)
 {
        struct inet_request_sock *ireq = inet_rsk(req);
        unsigned int remaining = MAX_TCP_OPTION_SPACE;
@@ -715,7 +716,8 @@ static unsigned int tcp_synack_options(const struct sock *sk,
                 * rather than TS in order to fit in better with old,
                 * buggy kernels, but that was deemed to be unnecessary.
                 */
-               ireq->tstamp_ok &= !ireq->sack_ok;
+               if (synack_type != TCP_SYNACK_COOKIE)
+                       ireq->tstamp_ok &= !ireq->sack_ok;
        }
 #endif
 
@@ -2622,6 +2624,11 @@ void tcp_send_loss_probe(struct sock *sk)
        int pcount;
        int mss = tcp_current_mss(sk);
 
+       /* At most one outstanding TLP */
+       if (tp->tlp_high_seq)
+               goto rearm_timer;
+
+       tp->tlp_retrans = 0;
        skb = tcp_send_head(sk);
        if (skb && tcp_snd_wnd_test(tp, skb, mss)) {
                pcount = tp->packets_out;
@@ -2639,10 +2646,6 @@ void tcp_send_loss_probe(struct sock *sk)
                return;
        }
 
-       /* At most one outstanding TLP retransmission. */
-       if (tp->tlp_high_seq)
-               goto rearm_timer;
-
        if (skb_still_in_host_queue(sk, skb))
                goto rearm_timer;
 
@@ -2664,10 +2667,12 @@ void tcp_send_loss_probe(struct sock *sk)
        if (__tcp_retransmit_skb(sk, skb, 1))
                goto rearm_timer;
 
+       tp->tlp_retrans = 1;
+
+probe_sent:
        /* Record snd_nxt for loss detection. */
        tp->tlp_high_seq = tp->snd_nxt;
 
-probe_sent:
        NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPLOSSPROBES);
        /* Reset s.t. tcp_rearm_rto will restart timer from now */
        inet_csk(sk)->icsk_pending = 0;
@@ -3394,7 +3399,7 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst,
 #endif
        skb_set_hash(skb, tcp_rsk(req)->txhash, PKT_HASH_TYPE_L4);
        tcp_header_size = tcp_synack_options(sk, req, mss, skb, &opts, md5,
-                                            foc) + sizeof(*th);
+                                            foc, synack_type) + sizeof(*th);
 
        skb_push(skb, tcp_header_size);
        skb_reset_transport_header(skb);
index 1b7ebbc..4077d58 100644 (file)
@@ -416,7 +416,7 @@ static struct sock *udp4_lib_lookup2(struct net *net,
                                     struct udp_hslot *hslot2,
                                     struct sk_buff *skb)
 {
-       struct sock *sk, *result;
+       struct sock *sk, *result, *reuseport_result;
        int score, badness;
        u32 hash = 0;
 
@@ -426,17 +426,20 @@ static struct sock *udp4_lib_lookup2(struct net *net,
                score = compute_score(sk, net, saddr, sport,
                                      daddr, hnum, dif, sdif);
                if (score > badness) {
+                       reuseport_result = NULL;
+
                        if (sk->sk_reuseport &&
                            sk->sk_state != TCP_ESTABLISHED) {
                                hash = udp_ehashfn(net, daddr, hnum,
                                                   saddr, sport);
-                               result = reuseport_select_sock(sk, hash, skb,
-                                                       sizeof(struct udphdr));
-                               if (result && !reuseport_has_conns(sk, false))
-                                       return result;
+                               reuseport_result = reuseport_select_sock(sk, hash, skb,
+                                                                        sizeof(struct udphdr));
+                               if (reuseport_result && !reuseport_has_conns(sk, false))
+                                       return reuseport_result;
                        }
+
+                       result = reuseport_result ? : sk;
                        badness = score;
-                       result = sk;
                }
        }
        return result;
@@ -2051,7 +2054,7 @@ static int udp_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
        /*
         *      UDP-Lite specific tests, ignored on UDP sockets
         */
-       if ((is_udplite & UDPLITE_RECV_CC)  &&  UDP_SKB_CB(skb)->partial_cov) {
+       if ((up->pcflag & UDPLITE_RECV_CC)  &&  UDP_SKB_CB(skb)->partial_cov) {
 
                /*
                 * MIB statistics other than incrementing the error count are
index 992cf45..f4f19e8 100644 (file)
@@ -49,29 +49,31 @@ config IPV6_OPTIMISTIC_DAD
 
 config INET6_AH
        tristate "IPv6: AH transformation"
-       select XFRM_ALGO
-       select CRYPTO
-       select CRYPTO_HMAC
-       select CRYPTO_MD5
-       select CRYPTO_SHA1
+       select XFRM_AH
        help
-         Support for IPsec AH.
+         Support for IPsec AH (Authentication Header).
+
+         AH can be used with various authentication algorithms.  Besides
+         enabling AH support itself, this option enables the generic
+         implementations of the algorithms that RFC 8221 lists as MUST be
+         implemented.  If you need any other algorithms, you'll need to enable
+         them in the crypto API.  You should also enable accelerated
+         implementations of any needed algorithms when available.
 
          If unsure, say Y.
 
 config INET6_ESP
        tristate "IPv6: ESP transformation"
-       select XFRM_ALGO
-       select CRYPTO
-       select CRYPTO_AUTHENC
-       select CRYPTO_HMAC
-       select CRYPTO_MD5
-       select CRYPTO_CBC
-       select CRYPTO_SHA1
-       select CRYPTO_DES
-       select CRYPTO_ECHAINIV
+       select XFRM_ESP
        help
-         Support for IPsec ESP.
+         Support for IPsec ESP (Encapsulating Security Payload).
+
+         ESP can be used with various encryption and authentication algorithms.
+         Besides enabling ESP support itself, this option enables the generic
+         implementations of the algorithms that RFC 8221 lists as MUST be
+         implemented.  If you need any other algorithms, you'll need to enable
+         them in the crypto API.  You should also enable accelerated
+         implementations of any needed algorithms when available.
 
          If unsure, say Y.
 
index 55addea..1ca516f 100644 (file)
@@ -395,3 +395,4 @@ module_exit(esp6_offload_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
 MODULE_ALIAS_XFRM_OFFLOAD_TYPE(AF_INET6, XFRM_PROTO_ESP);
+MODULE_DESCRIPTION("IPV6 GSO/GRO offload support");
index 091f941..430518a 100644 (file)
@@ -224,3 +224,4 @@ module_init(fou6_init);
 module_exit(fou6_fini);
 MODULE_AUTHOR("Tom Herbert <therbert@google.com>");
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Foo over UDP (IPv6)");
index fc50003..9df8737 100644 (file)
@@ -566,7 +566,6 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
        fl6.mp_hash = rt6_multipath_hash(net, &fl6, skb, NULL);
        security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
 
-       sk->sk_mark = mark;
        np = inet6_sk(sk);
 
        if (!icmpv6_xrlim_allow(sk, type, &fl6))
@@ -583,6 +582,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
                fl6.flowi6_oif = np->ucast_oif;
 
        ipcm6_init_sk(&ipc6, np);
+       ipc6.sockc.mark = mark;
        fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel);
 
        dst = icmpv6_route_lookup(net, skb, sk, &fl6);
@@ -751,7 +751,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
        sk = icmpv6_xmit_lock(net);
        if (!sk)
                goto out_bh_enable;
-       sk->sk_mark = mark;
        np = inet6_sk(sk);
 
        if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
@@ -779,6 +778,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
        ipcm6_init_sk(&ipc6, np);
        ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
        ipc6.tclass = ipv6_get_dsfield(ipv6_hdr(skb));
+       ipc6.sockc.mark = mark;
 
        if (ip6_append_data(sk, icmpv6_getfrag, &msg,
                            skb->len + sizeof(struct icmp6hdr),
index 257d2b6..36c58aa 100644 (file)
@@ -120,3 +120,4 @@ module_init(ila_init);
 module_exit(ila_fini);
 MODULE_AUTHOR("Tom Herbert <tom@herbertland.com>");
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("IPv6: Identifier Locator Addressing (ILA)");
index 781ca8c..3a57fb9 100644 (file)
@@ -127,6 +127,7 @@ static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev,
                        gre_proto == htons(ETH_P_ERSPAN2)) ?
                       ARPHRD_ETHER : ARPHRD_IP6GRE;
        int score, cand_score = 4;
+       struct net_device *ndev;
 
        for_each_ip_tunnel_rcu(t, ign->tunnels_r_l[h0 ^ h1]) {
                if (!ipv6_addr_equal(local, &t->parms.laddr) ||
@@ -238,9 +239,9 @@ static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev,
        if (t && t->dev->flags & IFF_UP)
                return t;
 
-       dev = ign->fb_tunnel_dev;
-       if (dev && dev->flags & IFF_UP)
-               return netdev_priv(dev);
+       ndev = READ_ONCE(ign->fb_tunnel_dev);
+       if (ndev && ndev->flags & IFF_UP)
+               return netdev_priv(ndev);
 
        return NULL;
 }
@@ -413,6 +414,8 @@ static void ip6gre_tunnel_uninit(struct net_device *dev)
 
        ip6gre_tunnel_unlink_md(ign, t);
        ip6gre_tunnel_unlink(ign, t);
+       if (ign->fb_tunnel_dev == dev)
+               WRITE_ONCE(ign->fb_tunnel_dev, NULL);
        dst_cache_reset(&t->dst_cache);
        dev_put(dev);
 }
@@ -1559,17 +1562,18 @@ static void ip6gre_destroy_tunnels(struct net *net, struct list_head *head)
 static int __net_init ip6gre_init_net(struct net *net)
 {
        struct ip6gre_net *ign = net_generic(net, ip6gre_net_id);
+       struct net_device *ndev;
        int err;
 
        if (!net_has_fallback_tunnels(net))
                return 0;
-       ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0",
-                                         NET_NAME_UNKNOWN,
-                                         ip6gre_tunnel_setup);
-       if (!ign->fb_tunnel_dev) {
+       ndev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0",
+                           NET_NAME_UNKNOWN, ip6gre_tunnel_setup);
+       if (!ndev) {
                err = -ENOMEM;
                goto err_alloc_dev;
        }
+       ign->fb_tunnel_dev = ndev;
        dev_net_set(ign->fb_tunnel_dev, net);
        /* FB netdevice is special: we have one, and only one per netns.
         * Allowing to move it to another netns is clearly unsafe.
@@ -1589,7 +1593,7 @@ static int __net_init ip6gre_init_net(struct net *net)
        return 0;
 
 err_reg_dev:
-       free_netdev(ign->fb_tunnel_dev);
+       free_netdev(ndev);
 err_alloc_dev:
        return err;
 }
index 821d96c..a18c378 100644 (file)
@@ -1846,6 +1846,7 @@ static const struct net_device_ops ip6_tnl_netdev_ops = {
 static void ip6_tnl_dev_setup(struct net_device *dev)
 {
        dev->netdev_ops = &ip6_tnl_netdev_ops;
+       dev->header_ops = &ip_tunnel_header_ops;
        dev->needs_free_netdev = true;
        dev->priv_destructor = ip6_dev_free;
 
index 1147f64..0d96416 100644 (file)
@@ -905,6 +905,7 @@ static const struct net_device_ops vti6_netdev_ops = {
 static void vti6_dev_setup(struct net_device *dev)
 {
        dev->netdev_ops = &vti6_netdev_ops;
+       dev->header_ops = &ip_tunnel_header_ops;
        dev->needs_free_netdev = true;
        dev->priv_destructor = vti6_dev_free;
 
index 7e12d21..8cd2782 100644 (file)
@@ -2615,6 +2615,7 @@ void ipv6_mc_destroy_dev(struct inet6_dev *idev)
                idev->mc_list = i->next;
 
                write_unlock_bh(&idev->lock);
+               ip6_mc_clear_src(i);
                ma_put(i);
                write_lock_bh(&idev->lock);
        }
index e273934..e96a431 100644 (file)
@@ -1807,11 +1807,22 @@ out_free:
        return ret;
 }
 
+void ip6t_unregister_table_pre_exit(struct net *net, struct xt_table *table,
+                                   const struct nf_hook_ops *ops)
+{
+       nf_unregister_net_hooks(net, ops, hweight32(table->valid_hooks));
+}
+
+void ip6t_unregister_table_exit(struct net *net, struct xt_table *table)
+{
+       __ip6t_unregister_table(net, table);
+}
+
 void ip6t_unregister_table(struct net *net, struct xt_table *table,
                           const struct nf_hook_ops *ops)
 {
        if (ops)
-               nf_unregister_net_hooks(net, ops, hweight32(table->valid_hooks));
+               ip6t_unregister_table_pre_exit(net, table, ops);
        __ip6t_unregister_table(net, table);
 }
 
@@ -1969,6 +1980,8 @@ static void __exit ip6_tables_fini(void)
 
 EXPORT_SYMBOL(ip6t_register_table);
 EXPORT_SYMBOL(ip6t_unregister_table);
+EXPORT_SYMBOL(ip6t_unregister_table_pre_exit);
+EXPORT_SYMBOL(ip6t_unregister_table_exit);
 EXPORT_SYMBOL(ip6t_do_table);
 
 module_init(ip6_tables_init);
index fd1f52a..d51d0c3 100644 (file)
@@ -121,3 +121,4 @@ module_exit(synproxy_tg6_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("Intercept IPv6 TCP connections and establish them using syncookies");
index 32667f5..88337b5 100644 (file)
@@ -73,16 +73,24 @@ static int __net_init ip6table_filter_net_init(struct net *net)
        return 0;
 }
 
+static void __net_exit ip6table_filter_net_pre_exit(struct net *net)
+{
+       if (net->ipv6.ip6table_filter)
+               ip6t_unregister_table_pre_exit(net, net->ipv6.ip6table_filter,
+                                              filter_ops);
+}
+
 static void __net_exit ip6table_filter_net_exit(struct net *net)
 {
        if (!net->ipv6.ip6table_filter)
                return;
-       ip6t_unregister_table(net, net->ipv6.ip6table_filter, filter_ops);
+       ip6t_unregister_table_exit(net, net->ipv6.ip6table_filter);
        net->ipv6.ip6table_filter = NULL;
 }
 
 static struct pernet_operations ip6table_filter_net_ops = {
        .init = ip6table_filter_net_init,
+       .pre_exit = ip6table_filter_net_pre_exit,
        .exit = ip6table_filter_net_exit,
 };
 
index 070afb9..1a27486 100644 (file)
@@ -93,16 +93,24 @@ static int __net_init ip6table_mangle_table_init(struct net *net)
        return ret;
 }
 
+static void __net_exit ip6table_mangle_net_pre_exit(struct net *net)
+{
+       if (net->ipv6.ip6table_mangle)
+               ip6t_unregister_table_pre_exit(net, net->ipv6.ip6table_mangle,
+                                              mangle_ops);
+}
+
 static void __net_exit ip6table_mangle_net_exit(struct net *net)
 {
        if (!net->ipv6.ip6table_mangle)
                return;
 
-       ip6t_unregister_table(net, net->ipv6.ip6table_mangle, mangle_ops);
+       ip6t_unregister_table_exit(net, net->ipv6.ip6table_mangle);
        net->ipv6.ip6table_mangle = NULL;
 }
 
 static struct pernet_operations ip6table_mangle_net_ops = {
+       .pre_exit = ip6table_mangle_net_pre_exit,
        .exit = ip6table_mangle_net_exit,
 };
 
index 0f48759..0a23265 100644 (file)
@@ -114,16 +114,22 @@ static int __net_init ip6table_nat_table_init(struct net *net)
        return ret;
 }
 
+static void __net_exit ip6table_nat_net_pre_exit(struct net *net)
+{
+       if (net->ipv6.ip6table_nat)
+               ip6t_nat_unregister_lookups(net);
+}
+
 static void __net_exit ip6table_nat_net_exit(struct net *net)
 {
        if (!net->ipv6.ip6table_nat)
                return;
-       ip6t_nat_unregister_lookups(net);
-       ip6t_unregister_table(net, net->ipv6.ip6table_nat, NULL);
+       ip6t_unregister_table_exit(net, net->ipv6.ip6table_nat);
        net->ipv6.ip6table_nat = NULL;
 }
 
 static struct pernet_operations ip6table_nat_net_ops = {
+       .pre_exit = ip6table_nat_net_pre_exit,
        .exit   = ip6table_nat_net_exit,
 };
 
index a22100b..8f9e742 100644 (file)
@@ -66,15 +66,23 @@ static int __net_init ip6table_raw_table_init(struct net *net)
        return ret;
 }
 
+static void __net_exit ip6table_raw_net_pre_exit(struct net *net)
+{
+       if (net->ipv6.ip6table_raw)
+               ip6t_unregister_table_pre_exit(net, net->ipv6.ip6table_raw,
+                                              rawtable_ops);
+}
+
 static void __net_exit ip6table_raw_net_exit(struct net *net)
 {
        if (!net->ipv6.ip6table_raw)
                return;
-       ip6t_unregister_table(net, net->ipv6.ip6table_raw, rawtable_ops);
+       ip6t_unregister_table_exit(net, net->ipv6.ip6table_raw);
        net->ipv6.ip6table_raw = NULL;
 }
 
 static struct pernet_operations ip6table_raw_net_ops = {
+       .pre_exit = ip6table_raw_net_pre_exit,
        .exit = ip6table_raw_net_exit,
 };
 
index a74335f..5e8c48f 100644 (file)
@@ -61,15 +61,23 @@ static int __net_init ip6table_security_table_init(struct net *net)
        return ret;
 }
 
+static void __net_exit ip6table_security_net_pre_exit(struct net *net)
+{
+       if (net->ipv6.ip6table_security)
+               ip6t_unregister_table_pre_exit(net, net->ipv6.ip6table_security,
+                                              sectbl_ops);
+}
+
 static void __net_exit ip6table_security_net_exit(struct net *net)
 {
        if (!net->ipv6.ip6table_security)
                return;
-       ip6t_unregister_table(net, net->ipv6.ip6table_security, sectbl_ops);
+       ip6t_unregister_table_exit(net, net->ipv6.ip6table_security);
        net->ipv6.ip6table_security = NULL;
 }
 
 static struct pernet_operations ip6table_security_net_ops = {
+       .pre_exit = ip6table_security_net_pre_exit,
        .exit = ip6table_security_net_exit,
 };
 
index a8566ee..667b8af 100644 (file)
@@ -35,3 +35,4 @@ module_exit(nf_flow_ipv6_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
 MODULE_ALIAS_NF_FLOWTABLE(AF_INET6);
+MODULE_DESCRIPTION("Netfilter flow table IPv6 module");
index 2af3220..8b5193e 100644 (file)
@@ -105,3 +105,4 @@ module_exit(nft_dup_ipv6_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
 MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "dup");
+MODULE_DESCRIPTION("IPv6 nftables packet duplication support");
index 7ece86a..e204163 100644 (file)
@@ -255,3 +255,4 @@ module_exit(nft_fib6_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
 MODULE_ALIAS_NFT_AF_EXPR(10, "fib");
+MODULE_DESCRIPTION("nftables fib / ipv6 route lookup support");
index 680a28c..c1098a1 100644 (file)
@@ -72,3 +72,4 @@ module_exit(nft_reject_ipv6_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
 MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "reject");
+MODULE_DESCRIPTION("IPv6 packet rejection for nftables");
index 82cbb46..f327981 100644 (file)
@@ -431,9 +431,12 @@ void fib6_select_path(const struct net *net, struct fib6_result *res,
        struct fib6_info *sibling, *next_sibling;
        struct fib6_info *match = res->f6i;
 
-       if ((!match->fib6_nsiblings && !match->nh) || have_oif_match)
+       if (!match->nh && (!match->fib6_nsiblings || have_oif_match))
                goto out;
 
+       if (match->nh && have_oif_match && res->nh)
+               return;
+
        /* We might have already computed the hash for ICMPv6 errors. In such
         * case it will always be non-zero. Otherwise now is the time to do it.
         */
@@ -3402,7 +3405,7 @@ static bool fib6_is_reject(u32 flags, struct net_device *dev, int addr_type)
        if ((flags & RTF_REJECT) ||
            (dev && (dev->flags & IFF_LOOPBACK) &&
             !(addr_type & IPV6_ADDR_LOOPBACK) &&
-            !(flags & RTF_LOCAL)))
+            !(flags & (RTF_ANYCAST | RTF_LOCAL))))
                return true;
 
        return false;
index 1fbb4df..5e2c34c 100644 (file)
@@ -1421,6 +1421,7 @@ static void ipip6_tunnel_setup(struct net_device *dev)
        int t_hlen = tunnel->hlen + sizeof(struct iphdr);
 
        dev->netdev_ops         = &ipip6_netdev_ops;
+       dev->header_ops         = &ip_tunnel_header_ops;
        dev->needs_free_netdev  = true;
        dev->priv_destructor    = ipip6_dev_free;
 
index 7d41517..a8d74f4 100644 (file)
@@ -148,7 +148,7 @@ static struct sock *udp6_lib_lookup2(struct net *net,
                int dif, int sdif, struct udp_hslot *hslot2,
                struct sk_buff *skb)
 {
-       struct sock *sk, *result;
+       struct sock *sk, *result, *reuseport_result;
        int score, badness;
        u32 hash = 0;
 
@@ -158,17 +158,20 @@ static struct sock *udp6_lib_lookup2(struct net *net,
                score = compute_score(sk, net, saddr, sport,
                                      daddr, hnum, dif, sdif);
                if (score > badness) {
+                       reuseport_result = NULL;
+
                        if (sk->sk_reuseport &&
                            sk->sk_state != TCP_ESTABLISHED) {
                                hash = udp6_ehashfn(net, daddr, hnum,
                                                    saddr, sport);
 
-                               result = reuseport_select_sock(sk, hash, skb,
-                                                       sizeof(struct udphdr));
-                               if (result && !reuseport_has_conns(sk, false))
-                                       return result;
+                               reuseport_result = reuseport_select_sock(sk, hash, skb,
+                                                                        sizeof(struct udphdr));
+                               if (reuseport_result && !reuseport_has_conns(sk, false))
+                                       return reuseport_result;
                        }
-                       result = sk;
+
+                       result = reuseport_result ? : sk;
                        badness = score;
                }
        }
@@ -643,7 +646,7 @@ static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
        /*
         * UDP-Lite specific tests, ignored on UDP sockets (see net/ipv4/udp.c).
         */
-       if ((is_udplite & UDPLITE_RECV_CC)  &&  UDP_SKB_CB(skb)->partial_cov) {
+       if ((up->pcflag & UDPLITE_RECV_CC)  &&  UDP_SKB_CB(skb)->partial_cov) {
 
                if (up->pcrlen == 0) {          /* full coverage was set  */
                        net_dbg_ratelimited("UDPLITE6: partial coverage %d while full coverage %d requested\n",
index 6d7ef78..6434d17 100644 (file)
@@ -1028,6 +1028,7 @@ static void l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb,
 
        /* Queue the packet to IP for output */
        skb->ignore_df = 1;
+       skb_dst_drop(skb);
 #if IS_ENABLED(CONFIG_IPV6)
        if (l2tp_sk_is_v6(tunnel->sock))
                error = inet6_csk_xmit(tunnel->sock, skb, NULL);
@@ -1099,10 +1100,6 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len
                goto out_unlock;
        }
 
-       /* Get routing info from the tunnel socket */
-       skb_dst_drop(skb);
-       skb_dst_set(skb, sk_dst_check(sk, 0));
-
        inet = inet_sk(sk);
        fl = &inet->cork.fl;
        switch (tunnel->encap) {
index 54fb8d4..6e53e43 100644 (file)
@@ -273,6 +273,10 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
 
        if (!sock_flag(sk, SOCK_ZAPPED))
                goto out;
+       if (!addr->sllc_arphrd)
+               addr->sllc_arphrd = ARPHRD_ETHER;
+       if (addr->sllc_arphrd != ARPHRD_ETHER)
+               goto out;
        rc = -ENODEV;
        if (sk->sk_bound_dev_if) {
                llc->dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if);
@@ -328,7 +332,9 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
        if (unlikely(!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr)))
                goto out;
        rc = -EAFNOSUPPORT;
-       if (unlikely(addr->sllc_family != AF_LLC))
+       if (!addr->sllc_arphrd)
+               addr->sllc_arphrd = ARPHRD_ETHER;
+       if (unlikely(addr->sllc_family != AF_LLC || addr->sllc_arphrd != ARPHRD_ETHER))
                goto out;
        dprintk("%s: binding %02X\n", __func__, addr->sllc_sap);
        rc = -ENODEV;
@@ -336,8 +342,6 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
        if (sk->sk_bound_dev_if) {
                llc->dev = dev_get_by_index_rcu(&init_net, sk->sk_bound_dev_if);
                if (llc->dev) {
-                       if (!addr->sllc_arphrd)
-                               addr->sllc_arphrd = llc->dev->type;
                        if (is_zero_ether_addr(addr->sllc_mac))
                                memcpy(addr->sllc_mac, llc->dev->dev_addr,
                                       IFHWADDRLEN);
index aa51509..02cde0f 100644 (file)
@@ -1105,11 +1105,8 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
                               ttl, lifetime, 0, ifmsh->preq_id++, sdata);
 
        spin_lock_bh(&mpath->state_lock);
-       if (mpath->flags & MESH_PATH_DELETED) {
-               spin_unlock_bh(&mpath->state_lock);
-               goto enddiscovery;
-       }
-       mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout);
+       if (!(mpath->flags & MESH_PATH_DELETED))
+               mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout);
        spin_unlock_bh(&mpath->state_lock);
 
 enddiscovery:
index a88ab6f..5c5af4b 100644 (file)
@@ -2396,6 +2396,7 @@ static int ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)
 
 static int ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
 {
+       struct ieee80211_hdr *hdr = (void *)rx->skb->data;
        struct sk_buff *skb = rx->skb;
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 
@@ -2406,6 +2407,31 @@ static int ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
        if (status->flag & RX_FLAG_DECRYPTED)
                return 0;
 
+       /* check mesh EAPOL frames first */
+       if (unlikely(rx->sta && ieee80211_vif_is_mesh(&rx->sdata->vif) &&
+                    ieee80211_is_data(fc))) {
+               struct ieee80211s_hdr *mesh_hdr;
+               u16 hdr_len = ieee80211_hdrlen(fc);
+               u16 ethertype_offset;
+               __be16 ethertype;
+
+               if (!ether_addr_equal(hdr->addr1, rx->sdata->vif.addr))
+                       goto drop_check;
+
+               /* make sure fixed part of mesh header is there, also checks skb len */
+               if (!pskb_may_pull(rx->skb, hdr_len + 6))
+                       goto drop_check;
+
+               mesh_hdr = (struct ieee80211s_hdr *)(skb->data + hdr_len);
+               ethertype_offset = hdr_len + ieee80211_get_mesh_hdrlen(mesh_hdr) +
+                                  sizeof(rfc1042_header);
+
+               if (skb_copy_bits(rx->skb, ethertype_offset, &ethertype, 2) == 0 &&
+                   ethertype == rx->sdata->control_port_protocol)
+                       return 0;
+       }
+
+drop_check:
        /* Drop unencrypted frames if key is set. */
        if (unlikely(!ieee80211_has_protected(fc) &&
                     !ieee80211_is_any_nullfunc(fc) &&
index 7b1baca..cbc40b3 100644 (file)
@@ -639,11 +639,23 @@ static void ieee80211_report_ack_skb(struct ieee80211_local *local,
                u64 cookie = IEEE80211_SKB_CB(skb)->ack.cookie;
                struct ieee80211_sub_if_data *sdata;
                struct ieee80211_hdr *hdr = (void *)skb->data;
+               __be16 ethertype = 0;
+
+               if (skb->len >= ETH_HLEN && skb->protocol == cpu_to_be16(ETH_P_802_3))
+                       skb_copy_bits(skb, 2 * ETH_ALEN, &ethertype, ETH_TLEN);
 
                rcu_read_lock();
                sdata = ieee80211_sdata_from_skb(local, skb);
                if (sdata) {
-                       if (ieee80211_is_any_nullfunc(hdr->frame_control))
+                       if (ethertype == sdata->control_port_protocol ||
+                           ethertype == cpu_to_be16(ETH_P_PREAUTH))
+                               cfg80211_control_port_tx_status(&sdata->wdev,
+                                                               cookie,
+                                                               skb->data,
+                                                               skb->len,
+                                                               acked,
+                                                               GFP_ATOMIC);
+                       else if (ieee80211_is_any_nullfunc(hdr->frame_control))
                                cfg80211_probe_status(sdata->dev, hdr->addr1,
                                                      cookie, acked,
                                                      info->status.ack_signal,
@@ -654,12 +666,8 @@ static void ieee80211_report_ack_skb(struct ieee80211_local *local,
                                                        skb->data, skb->len,
                                                        acked, GFP_ATOMIC);
                        else
-                               cfg80211_control_port_tx_status(&sdata->wdev,
-                                                               cookie,
-                                                               skb->data,
-                                                               skb->len,
-                                                               acked,
-                                                               GFP_ATOMIC);
+                               pr_warn("Unknown status report in ack skb\n");
+
                }
                rcu_read_unlock();
 
index e9ce658..1a2941e 100644 (file)
@@ -3996,6 +3996,9 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
        skb_list_walk_safe(skb, skb, next) {
                skb_mark_not_on_list(skb);
 
+               if (skb->protocol == sdata->control_port_protocol)
+                       ctrl_flags |= IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP;
+
                skb = ieee80211_build_hdr(sdata, skb, info_flags,
                                          sta, ctrl_flags, cookie);
                if (IS_ERR(skb)) {
@@ -4206,7 +4209,7 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
            (!sta || !test_sta_flag(sta, WLAN_STA_TDLS_PEER)))
                ra = sdata->u.mgd.bssid;
 
-       if (!is_valid_ether_addr(ra))
+       if (is_zero_ether_addr(ra))
                goto out_free;
 
        multicast = is_multicast_ether_addr(ra);
@@ -5371,7 +5374,8 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
                return -EINVAL;
 
        if (proto == sdata->control_port_protocol)
-               ctrl_flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO;
+               ctrl_flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO |
+                             IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP;
 
        if (unencrypted)
                flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
index 490b925..8f940be 100644 (file)
@@ -336,9 +336,7 @@ bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb,
         */
        subflow->snd_isn = TCP_SKB_CB(skb)->end_seq;
        if (subflow->request_mptcp) {
-               pr_debug("local_key=%llu", subflow->local_key);
                opts->suboptions = OPTION_MPTCP_MPC_SYN;
-               opts->sndr_key = subflow->local_key;
                *size = TCPOLEN_MPTCP_MPC_SYN;
                return true;
        } else if (subflow->request_join) {
@@ -451,9 +449,9 @@ static bool mptcp_established_options_mp(struct sock *sk, struct sk_buff *skb,
 }
 
 static void mptcp_write_data_fin(struct mptcp_subflow_context *subflow,
-                                struct mptcp_ext *ext)
+                                struct sk_buff *skb, struct mptcp_ext *ext)
 {
-       if (!ext->use_map) {
+       if (!ext->use_map || !skb->len) {
                /* RFC6824 requires a DSS mapping with specific values
                 * if DATA_FIN is set but no data payload is mapped
                 */
@@ -505,7 +503,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
                        opts->ext_copy = *mpext;
 
                if (skb && tcp_fin && subflow->data_fin_tx_enable)
-                       mptcp_write_data_fin(subflow, &opts->ext_copy);
+                       mptcp_write_data_fin(subflow, skb, &opts->ext_copy);
                ret = true;
        }
 
index 809687d..c6eeaf3 100644 (file)
@@ -135,8 +135,6 @@ static inline __be32 mptcp_option(u8 subopt, u8 len, u8 nib, u8 field)
                     ((nib & 0xF) << 8) | field);
 }
 
-#define MPTCP_PM_MAX_ADDR      4
-
 struct mptcp_addr_info {
        sa_family_t             family;
        __be16                  port;
@@ -234,10 +232,7 @@ static inline struct mptcp_data_frag *mptcp_rtx_head(const struct sock *sk)
 {
        struct mptcp_sock *msk = mptcp_sk(sk);
 
-       if (list_empty(&msk->rtx_queue))
-               return NULL;
-
-       return list_first_entry(&msk->rtx_queue, struct mptcp_data_frag, list);
+       return list_first_entry_or_null(&msk->rtx_queue, struct mptcp_data_frag, list);
 }
 
 struct mptcp_subflow_request_sock {
@@ -254,6 +249,7 @@ struct mptcp_subflow_request_sock {
        u64     thmac;
        u32     local_nonce;
        u32     remote_nonce;
+       struct mptcp_sock       *msk;
 };
 
 static inline struct mptcp_subflow_request_sock *
index bf13257..3838a0b 100644 (file)
@@ -69,6 +69,9 @@ static void subflow_req_destructor(struct request_sock *req)
 
        pr_debug("subflow_req=%p", subflow_req);
 
+       if (subflow_req->msk)
+               sock_put((struct sock *)subflow_req->msk);
+
        if (subflow_req->mp_capable)
                mptcp_token_destroy_request(subflow_req->token);
        tcp_request_sock_ops.destructor(req);
@@ -86,8 +89,8 @@ static void subflow_generate_hmac(u64 key1, u64 key2, u32 nonce1, u32 nonce2,
 }
 
 /* validate received token and create truncated hmac and nonce for SYN-ACK */
-static bool subflow_token_join_request(struct request_sock *req,
-                                      const struct sk_buff *skb)
+static struct mptcp_sock *subflow_token_join_request(struct request_sock *req,
+                                                    const struct sk_buff *skb)
 {
        struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
        u8 hmac[SHA256_DIGEST_SIZE];
@@ -97,13 +100,13 @@ static bool subflow_token_join_request(struct request_sock *req,
        msk = mptcp_token_get_sock(subflow_req->token);
        if (!msk) {
                SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINNOTOKEN);
-               return false;
+               return NULL;
        }
 
        local_id = mptcp_pm_get_local_id(msk, (struct sock_common *)req);
        if (local_id < 0) {
                sock_put((struct sock *)msk);
-               return false;
+               return NULL;
        }
        subflow_req->local_id = local_id;
 
@@ -114,9 +117,7 @@ static bool subflow_token_join_request(struct request_sock *req,
                              subflow_req->remote_nonce, hmac);
 
        subflow_req->thmac = get_unaligned_be64(hmac);
-
-       sock_put((struct sock *)msk);
-       return true;
+       return msk;
 }
 
 static void subflow_init_req(struct request_sock *req,
@@ -133,6 +134,7 @@ static void subflow_init_req(struct request_sock *req,
 
        subflow_req->mp_capable = 0;
        subflow_req->mp_join = 0;
+       subflow_req->msk = NULL;
 
 #ifdef CONFIG_TCP_MD5SIG
        /* no MPTCP if MD5SIG is enabled on this socket or we may run out of
@@ -166,12 +168,9 @@ static void subflow_init_req(struct request_sock *req,
                subflow_req->remote_id = mp_opt.join_id;
                subflow_req->token = mp_opt.token;
                subflow_req->remote_nonce = mp_opt.nonce;
-               pr_debug("token=%u, remote_nonce=%u", subflow_req->token,
-                        subflow_req->remote_nonce);
-               if (!subflow_token_join_request(req, skb)) {
-                       subflow_req->mp_join = 0;
-                       // @@ need to trigger RST
-               }
+               subflow_req->msk = subflow_token_join_request(req, skb);
+               pr_debug("token=%u, remote_nonce=%u msk=%p", subflow_req->token,
+                        subflow_req->remote_nonce, subflow_req->msk);
        }
 }
 
@@ -354,10 +353,9 @@ static bool subflow_hmac_valid(const struct request_sock *req,
        const struct mptcp_subflow_request_sock *subflow_req;
        u8 hmac[SHA256_DIGEST_SIZE];
        struct mptcp_sock *msk;
-       bool ret;
 
        subflow_req = mptcp_subflow_rsk(req);
-       msk = mptcp_token_get_sock(subflow_req->token);
+       msk = subflow_req->msk;
        if (!msk)
                return false;
 
@@ -365,12 +363,7 @@ static bool subflow_hmac_valid(const struct request_sock *req,
                              subflow_req->remote_nonce,
                              subflow_req->local_nonce, hmac);
 
-       ret = true;
-       if (crypto_memneq(hmac, mp_opt->hmac, MPTCPOPT_HMAC_LEN))
-               ret = false;
-
-       sock_put((struct sock *)msk);
-       return ret;
+       return !crypto_memneq(hmac, mp_opt->hmac, MPTCPOPT_HMAC_LEN);
 }
 
 static void mptcp_sock_destruct(struct sock *sk)
@@ -438,22 +431,25 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
        struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk);
        struct mptcp_subflow_request_sock *subflow_req;
        struct mptcp_options_received mp_opt;
-       bool fallback_is_fatal = false;
+       bool fallback, fallback_is_fatal;
        struct sock *new_msk = NULL;
-       bool fallback = false;
        struct sock *child;
 
        pr_debug("listener=%p, req=%p, conn=%p", listener, req, listener->conn);
 
-       /* we need later a valid 'mp_capable' value even when options are not
-        * parsed
+       /* After child creation we must look for 'mp_capable' even when options
+        * are not parsed
         */
        mp_opt.mp_capable = 0;
-       if (tcp_rsk(req)->is_mptcp == 0)
+
+       /* hopefully temporary handling for MP_JOIN+syncookie */
+       subflow_req = mptcp_subflow_rsk(req);
+       fallback_is_fatal = subflow_req->mp_join;
+       fallback = !tcp_rsk(req)->is_mptcp;
+       if (fallback)
                goto create_child;
 
        /* if the sk is MP_CAPABLE, we try to fetch the client key */
-       subflow_req = mptcp_subflow_rsk(req);
        if (subflow_req->mp_capable) {
                if (TCP_SKB_CB(skb)->seq != subflow_req->ssn_offset + 1) {
                        /* here we can receive and accept an in-window,
@@ -474,12 +470,11 @@ create_msk:
                if (!new_msk)
                        fallback = true;
        } else if (subflow_req->mp_join) {
-               fallback_is_fatal = true;
                mptcp_get_options(skb, &mp_opt);
                if (!mp_opt.mp_join ||
                    !subflow_hmac_valid(req, &mp_opt)) {
                        SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC);
-                       return NULL;
+                       fallback = true;
                }
        }
 
@@ -522,10 +517,12 @@ create_child:
                } else if (ctx->mp_join) {
                        struct mptcp_sock *owner;
 
-                       owner = mptcp_token_get_sock(ctx->token);
+                       owner = subflow_req->msk;
                        if (!owner)
                                goto dispose_child;
 
+                       /* move the msk reference ownership to the subflow */
+                       subflow_req->msk = NULL;
                        ctx->conn = (struct sock *)owner;
                        if (!mptcp_finish_join(child))
                                goto dispose_child;
@@ -1053,8 +1050,10 @@ int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock)
        err = tcp_set_ulp(sf->sk, "mptcp");
        release_sock(sf->sk);
 
-       if (err)
+       if (err) {
+               sock_release(sf);
                return err;
+       }
 
        /* the newly created socket really belongs to the owning MPTCP master
         * socket, even if for additional subflows the allocation is performed
index 486959f..a8ce04a 100644 (file)
@@ -326,7 +326,7 @@ bitmap_ip_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
        set->variant = &bitmap_ip;
        if (!init_map_ip(set, map, first_ip, last_ip,
                         elements, hosts, netmask)) {
-               kfree(map);
+               ip_set_free(map);
                return -ENOMEM;
        }
        if (tb[IPSET_ATTR_TIMEOUT]) {
index 2310a31..2c625e0 100644 (file)
@@ -363,7 +363,7 @@ bitmap_ipmac_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
        map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long);
        set->variant = &bitmap_ipmac;
        if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) {
-               kfree(map);
+               ip_set_free(map);
                return -ENOMEM;
        }
        if (tb[IPSET_ATTR_TIMEOUT]) {
index e56ced6..7138e08 100644 (file)
@@ -274,7 +274,7 @@ bitmap_port_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
        map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long);
        set->variant = &bitmap_port;
        if (!init_map_port(set, map, first_port, last_port)) {
-               kfree(map);
+               ip_set_free(map);
                return -ENOMEM;
        }
        if (tb[IPSET_ATTR_TIMEOUT]) {
index 340cb95..56621d6 100644 (file)
@@ -460,6 +460,8 @@ ip_set_elem_len(struct ip_set *set, struct nlattr *tb[], size_t len,
        for (id = 0; id < IPSET_EXT_ID_MAX; id++) {
                if (!add_extension(id, cadt_flags, tb))
                        continue;
+               if (align < ip_set_extensions[id].align)
+                       align = ip_set_extensions[id].align;
                len = ALIGN(len, ip_set_extensions[id].align);
                set->offset[id] = len;
                set->extensions |= ip_set_extensions[id].type;
index 1ee4375..521e970 100644 (file)
@@ -682,7 +682,7 @@ retry:
        }
        t->hregion = ip_set_alloc(ahash_sizeof_regions(htable_bits));
        if (!t->hregion) {
-               kfree(t);
+               ip_set_free(t);
                ret = -ENOMEM;
                goto out;
        }
@@ -1533,7 +1533,7 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
        }
        t->hregion = ip_set_alloc(ahash_sizeof_regions(hbits));
        if (!t->hregion) {
-               kfree(t);
+               ip_set_free(t);
                kfree(h);
                return -ENOMEM;
        }
index 605e0f6..2b8abbf 100644 (file)
@@ -1717,6 +1717,8 @@ static int sync_thread_backup(void *data)
 {
        struct ip_vs_sync_thread_data *tinfo = data;
        struct netns_ipvs *ipvs = tinfo->ipvs;
+       struct sock *sk = tinfo->sock->sk;
+       struct udp_sock *up = udp_sk(sk);
        int len;
 
        pr_info("sync thread started: state = BACKUP, mcast_ifn = %s, "
@@ -1724,12 +1726,14 @@ static int sync_thread_backup(void *data)
                ipvs->bcfg.mcast_ifn, ipvs->bcfg.syncid, tinfo->id);
 
        while (!kthread_should_stop()) {
-               wait_event_interruptible(*sk_sleep(tinfo->sock->sk),
-                        !skb_queue_empty(&tinfo->sock->sk->sk_receive_queue)
-                        || kthread_should_stop());
+               wait_event_interruptible(*sk_sleep(sk),
+                                        !skb_queue_empty_lockless(&sk->sk_receive_queue) ||
+                                        !skb_queue_empty_lockless(&up->reader_queue) ||
+                                        kthread_should_stop());
 
                /* do we have data now? */
-               while (!skb_queue_empty(&(tinfo->sock->sk->sk_receive_queue))) {
+               while (!skb_queue_empty_lockless(&sk->sk_receive_queue) ||
+                      !skb_queue_empty_lockless(&up->reader_queue)) {
                        len = ip_vs_receive(tinfo->sock, tinfo->buf,
                                        ipvs->bcfg.sync_maxlen);
                        if (len <= 0) {
index 79cd9dd..f33d72c 100644 (file)
@@ -2158,6 +2158,8 @@ static int nf_conntrack_update(struct net *net, struct sk_buff *skb)
                err = __nf_conntrack_update(net, skb, ct, ctinfo);
                if (err < 0)
                        return err;
+
+               ct = nf_ct_get(skb, &ctinfo);
        }
 
        return nf_confirm_cthelper(skb, ct, ctinfo);
index d7bd8b1..832eabe 100644 (file)
@@ -939,7 +939,8 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family)
                        filter->mark.mask = 0xffffffff;
                }
        } else if (cda[CTA_MARK_MASK]) {
-               return ERR_PTR(-EINVAL);
+               err = -EINVAL;
+               goto err_filter;
        }
 #endif
        if (!cda[CTA_FILTER])
@@ -947,15 +948,17 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family)
 
        err = ctnetlink_parse_zone(cda[CTA_ZONE], &filter->zone);
        if (err < 0)
-               return ERR_PTR(err);
+               goto err_filter;
 
        err = ctnetlink_parse_filter(cda[CTA_FILTER], filter);
        if (err < 0)
-               return ERR_PTR(err);
+               goto err_filter;
 
        if (filter->orig_flags) {
-               if (!cda[CTA_TUPLE_ORIG])
-                       return ERR_PTR(-EINVAL);
+               if (!cda[CTA_TUPLE_ORIG]) {
+                       err = -EINVAL;
+                       goto err_filter;
+               }
 
                err = ctnetlink_parse_tuple_filter(cda, &filter->orig,
                                                   CTA_TUPLE_ORIG,
@@ -963,23 +966,32 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family)
                                                   &filter->zone,
                                                   filter->orig_flags);
                if (err < 0)
-                       return ERR_PTR(err);
+                       goto err_filter;
        }
 
        if (filter->reply_flags) {
-               if (!cda[CTA_TUPLE_REPLY])
-                       return ERR_PTR(-EINVAL);
+               if (!cda[CTA_TUPLE_REPLY]) {
+                       err = -EINVAL;
+                       goto err_filter;
+               }
 
                err = ctnetlink_parse_tuple_filter(cda, &filter->reply,
                                                   CTA_TUPLE_REPLY,
                                                   filter->family,
                                                   &filter->zone,
                                                   filter->orig_flags);
-               if (err < 0)
-                       return ERR_PTR(err);
+               if (err < 0) {
+                       err = -EINVAL;
+                       goto err_filter;
+               }
        }
 
        return filter;
+
+err_filter:
+       kfree(filter);
+
+       return ERR_PTR(err);
 }
 
 static bool ctnetlink_needs_filter(u8 family, const struct nlattr * const *cda)
index f108a76..2b01a15 100644 (file)
@@ -73,3 +73,4 @@ EXPORT_SYMBOL_GPL(nft_fwd_dup_netdev_offload);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
+MODULE_DESCRIPTION("Netfilter packet duplication support");
index 6a3034f..b1eb527 100644 (file)
@@ -387,51 +387,6 @@ static void nf_flow_offload_work_gc(struct work_struct *work)
        queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ);
 }
 
-int nf_flow_table_offload_add_cb(struct nf_flowtable *flow_table,
-                                flow_setup_cb_t *cb, void *cb_priv)
-{
-       struct flow_block *block = &flow_table->flow_block;
-       struct flow_block_cb *block_cb;
-       int err = 0;
-
-       down_write(&flow_table->flow_block_lock);
-       block_cb = flow_block_cb_lookup(block, cb, cb_priv);
-       if (block_cb) {
-               err = -EEXIST;
-               goto unlock;
-       }
-
-       block_cb = flow_block_cb_alloc(cb, cb_priv, cb_priv, NULL);
-       if (IS_ERR(block_cb)) {
-               err = PTR_ERR(block_cb);
-               goto unlock;
-       }
-
-       list_add_tail(&block_cb->list, &block->cb_list);
-
-unlock:
-       up_write(&flow_table->flow_block_lock);
-       return err;
-}
-EXPORT_SYMBOL_GPL(nf_flow_table_offload_add_cb);
-
-void nf_flow_table_offload_del_cb(struct nf_flowtable *flow_table,
-                                 flow_setup_cb_t *cb, void *cb_priv)
-{
-       struct flow_block *block = &flow_table->flow_block;
-       struct flow_block_cb *block_cb;
-
-       down_write(&flow_table->flow_block_lock);
-       block_cb = flow_block_cb_lookup(block, cb, cb_priv);
-       if (block_cb) {
-               list_del(&block_cb->list);
-               flow_block_cb_free(block_cb);
-       } else {
-               WARN_ON(true);
-       }
-       up_write(&flow_table->flow_block_lock);
-}
-EXPORT_SYMBOL_GPL(nf_flow_table_offload_del_cb);
 
 static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff,
                                __be16 port, __be16 new_port)
@@ -639,3 +594,4 @@ module_exit(nf_flow_table_module_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
+MODULE_DESCRIPTION("Netfilter flow table module");
index 88bedf1..bc4126d 100644 (file)
@@ -72,3 +72,4 @@ module_exit(nf_flow_inet_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
 MODULE_ALIAS_NF_FLOWTABLE(1); /* NFPROTO_INET */
+MODULE_DESCRIPTION("Netfilter flow table mixed IPv4/IPv6 module");
index 62651e6..5fff1e0 100644 (file)
@@ -950,6 +950,7 @@ static void nf_flow_table_indr_cleanup(struct flow_block_cb *block_cb)
        nf_flow_table_gc_cleanup(flowtable, dev);
        down_write(&flowtable->flow_block_lock);
        list_del(&block_cb->list);
+       list_del(&block_cb->driver_list);
        flow_block_cb_free(block_cb);
        up_write(&flowtable->flow_block_lock);
 }
index b9cbe1e..ebcdc8e 100644 (file)
@@ -1237,3 +1237,4 @@ EXPORT_SYMBOL_GPL(nf_synproxy_ipv6_fini);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("nftables SYNPROXY expression support");
index 073aa10..88325b2 100644 (file)
@@ -188,24 +188,6 @@ static void nft_netdev_unregister_hooks(struct net *net,
                nf_unregister_net_hook(net, &hook->ops);
 }
 
-static int nft_register_basechain_hooks(struct net *net, int family,
-                                       struct nft_base_chain *basechain)
-{
-       if (family == NFPROTO_NETDEV)
-               return nft_netdev_register_hooks(net, &basechain->hook_list);
-
-       return nf_register_net_hook(net, &basechain->ops);
-}
-
-static void nft_unregister_basechain_hooks(struct net *net, int family,
-                                          struct nft_base_chain *basechain)
-{
-       if (family == NFPROTO_NETDEV)
-               nft_netdev_unregister_hooks(net, &basechain->hook_list);
-       else
-               nf_unregister_net_hook(net, &basechain->ops);
-}
-
 static int nf_tables_register_hook(struct net *net,
                                   const struct nft_table *table,
                                   struct nft_chain *chain)
@@ -223,7 +205,10 @@ static int nf_tables_register_hook(struct net *net,
        if (basechain->type->ops_register)
                return basechain->type->ops_register(net, ops);
 
-       return nft_register_basechain_hooks(net, table->family, basechain);
+       if (table->family == NFPROTO_NETDEV)
+               return nft_netdev_register_hooks(net, &basechain->hook_list);
+
+       return nf_register_net_hook(net, &basechain->ops);
 }
 
 static void nf_tables_unregister_hook(struct net *net,
@@ -242,7 +227,10 @@ static void nf_tables_unregister_hook(struct net *net,
        if (basechain->type->ops_unregister)
                return basechain->type->ops_unregister(net, ops);
 
-       nft_unregister_basechain_hooks(net, table->family, basechain);
+       if (table->family == NFPROTO_NETDEV)
+               nft_netdev_unregister_hooks(net, &basechain->hook_list);
+       else
+               nf_unregister_net_hook(net, &basechain->ops);
 }
 
 static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type)
@@ -832,8 +820,7 @@ static void nft_table_disable(struct net *net, struct nft_table *table, u32 cnt)
                if (cnt && i++ == cnt)
                        break;
 
-               nft_unregister_basechain_hooks(net, table->family,
-                                              nft_base_chain(chain));
+               nf_tables_unregister_hook(net, table, chain);
        }
 }
 
@@ -848,8 +835,7 @@ static int nf_tables_table_enable(struct net *net, struct nft_table *table)
                if (!nft_is_base_chain(chain))
                        continue;
 
-               err = nft_register_basechain_hooks(net, table->family,
-                                                  nft_base_chain(chain));
+               err = nf_tables_register_hook(net, table, chain);
                if (err < 0)
                        goto err_register_hooks;
 
@@ -894,11 +880,12 @@ static int nf_tables_updtable(struct nft_ctx *ctx)
                nft_trans_table_enable(trans) = false;
        } else if (!(flags & NFT_TABLE_F_DORMANT) &&
                   ctx->table->flags & NFT_TABLE_F_DORMANT) {
+               ctx->table->flags &= ~NFT_TABLE_F_DORMANT;
                ret = nf_tables_table_enable(ctx->net, ctx->table);
-               if (ret >= 0) {
-                       ctx->table->flags &= ~NFT_TABLE_F_DORMANT;
+               if (ret >= 0)
                        nft_trans_table_enable(trans) = true;
-               }
+               else
+                       ctx->table->flags |= NFT_TABLE_F_DORMANT;
        }
        if (ret < 0)
                goto err;
@@ -6550,12 +6537,22 @@ err1:
        return err;
 }
 
+static void nft_flowtable_hook_release(struct nft_flowtable_hook *flowtable_hook)
+{
+       struct nft_hook *this, *next;
+
+       list_for_each_entry_safe(this, next, &flowtable_hook->list, list) {
+               list_del(&this->list);
+               kfree(this);
+       }
+}
+
 static int nft_delflowtable_hook(struct nft_ctx *ctx,
                                 struct nft_flowtable *flowtable)
 {
        const struct nlattr * const *nla = ctx->nla;
        struct nft_flowtable_hook flowtable_hook;
-       struct nft_hook *this, *next, *hook;
+       struct nft_hook *this, *hook;
        struct nft_trans *trans;
        int err;
 
@@ -6564,33 +6561,40 @@ static int nft_delflowtable_hook(struct nft_ctx *ctx,
        if (err < 0)
                return err;
 
-       list_for_each_entry_safe(this, next, &flowtable_hook.list, list) {
+       list_for_each_entry(this, &flowtable_hook.list, list) {
                hook = nft_hook_list_find(&flowtable->hook_list, this);
                if (!hook) {
                        err = -ENOENT;
                        goto err_flowtable_del_hook;
                }
                hook->inactive = true;
-               list_del(&this->list);
-               kfree(this);
        }
 
        trans = nft_trans_alloc(ctx, NFT_MSG_DELFLOWTABLE,
                                sizeof(struct nft_trans_flowtable));
-       if (!trans)
-               return -ENOMEM;
+       if (!trans) {
+               err = -ENOMEM;
+               goto err_flowtable_del_hook;
+       }
 
        nft_trans_flowtable(trans) = flowtable;
        nft_trans_flowtable_update(trans) = true;
        INIT_LIST_HEAD(&nft_trans_flowtable_hooks(trans));
+       nft_flowtable_hook_release(&flowtable_hook);
 
        list_add_tail(&trans->list, &ctx->net->nft.commit_list);
 
        return 0;
 
 err_flowtable_del_hook:
-       list_for_each_entry(hook, &flowtable_hook.list, list)
+       list_for_each_entry(this, &flowtable_hook.list, list) {
+               hook = nft_hook_list_find(&flowtable->hook_list, this);
+               if (!hook)
+                       break;
+
                hook->inactive = false;
+       }
+       nft_flowtable_hook_release(&flowtable_hook);
 
        return err;
 }
index 185fc82..c7cf1cd 100644 (file)
@@ -296,6 +296,7 @@ static void nft_indr_block_cleanup(struct flow_block_cb *block_cb)
        nft_flow_block_offload_init(&bo, dev_net(dev), FLOW_BLOCK_UNBIND,
                                    basechain, &extack);
        mutex_lock(&net->nft.commit_mutex);
+       list_del(&block_cb->driver_list);
        list_move(&block_cb->list, &bo.cb_list);
        nft_flow_offload_unbind(&bo, basechain);
        mutex_unlock(&net->nft.commit_mutex);
index 99127e2..5f24edf 100644 (file)
@@ -33,6 +33,7 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
 MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER);
+MODULE_DESCRIPTION("Netfilter messages via netlink socket");
 
 #define nfnl_dereference_protected(id) \
        rcu_dereference_protected(table[(id)].subsys, \
index f9adca6..aa1a066 100644 (file)
@@ -902,3 +902,4 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
 MODULE_ALIAS_NFT_EXPR("match");
 MODULE_ALIAS_NFT_EXPR("target");
+MODULE_DESCRIPTION("x_tables over nftables support");
index 69d6173..7d0761f 100644 (file)
@@ -280,3 +280,4 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pablo Neira Ayuso");
 MODULE_ALIAS_NFT_EXPR("connlimit");
 MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_CONNLIMIT);
+MODULE_DESCRIPTION("nftables connlimit rule support");
index f6d4d0f..85ed461 100644 (file)
@@ -303,3 +303,4 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
 MODULE_ALIAS_NFT_EXPR("counter");
 MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_COUNTER);
+MODULE_DESCRIPTION("nftables counter rule support");
index faea72c..77258af 100644 (file)
@@ -1345,3 +1345,4 @@ MODULE_ALIAS_NFT_EXPR("notrack");
 MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_CT_HELPER);
 MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_CT_TIMEOUT);
 MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_CT_EXPECT);
+MODULE_DESCRIPTION("Netfilter nf_tables conntrack module");
index c2e78c1..40788b3 100644 (file)
@@ -102,3 +102,4 @@ module_exit(nft_dup_netdev_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
 MODULE_ALIAS_NFT_AF_EXPR(5, "dup");
+MODULE_DESCRIPTION("nftables netdev packet duplication support");
index 465432e..a88d44e 100644 (file)
@@ -76,3 +76,4 @@ module_exit(nft_fib_inet_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
 MODULE_ALIAS_NFT_AF_EXPR(1, "fib");
+MODULE_DESCRIPTION("nftables fib inet support");
index a2e726a..3f3478a 100644 (file)
@@ -85,3 +85,4 @@ module_exit(nft_fib_netdev_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pablo M. Bermudo Garay <pablombg@gmail.com>");
 MODULE_ALIAS_NFT_AF_EXPR(5, "fib");
+MODULE_DESCRIPTION("nftables netdev fib lookups support");
index b70b489..3b9b97a 100644 (file)
@@ -286,3 +286,4 @@ module_exit(nft_flow_offload_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
 MODULE_ALIAS_NFT_EXPR("flow_offload");
+MODULE_DESCRIPTION("nftables hardware flow offload module");
index b836d55..96371d8 100644 (file)
@@ -248,3 +248,4 @@ module_exit(nft_hash_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Laura Garcia <nevola@gmail.com>");
 MODULE_ALIAS_NFT_EXPR("hash");
+MODULE_DESCRIPTION("Netfilter nftables hash module");
index 35b67d7..0e2c315 100644 (file)
@@ -372,3 +372,4 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
 MODULE_ALIAS_NFT_EXPR("limit");
 MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_LIMIT);
+MODULE_DESCRIPTION("nftables limit expression support");
index fe4831f..5789945 100644 (file)
@@ -298,3 +298,4 @@ module_exit(nft_log_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
 MODULE_ALIAS_NFT_EXPR("log");
+MODULE_DESCRIPTION("Netfilter nf_tables log module");
index bc9fd98..71390b7 100644 (file)
@@ -305,3 +305,4 @@ module_exit(nft_masq_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
 MODULE_ALIAS_NFT_EXPR("masq");
+MODULE_DESCRIPTION("Netfilter nftables masquerade expression support");
index 23a7bfd..4bcf33b 100644 (file)
@@ -402,3 +402,4 @@ module_exit(nft_nat_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>");
 MODULE_ALIAS_NFT_EXPR("nat");
+MODULE_DESCRIPTION("Network Address Translation support");
index 48edb9d..f1fc824 100644 (file)
@@ -217,3 +217,4 @@ module_exit(nft_ng_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Laura Garcia <nevola@gmail.com>");
 MODULE_ALIAS_NFT_EXPR("numgen");
+MODULE_DESCRIPTION("nftables number generator module");
index bfd18d2..5f9207a 100644 (file)
@@ -252,3 +252,4 @@ module_exit(nft_objref_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
 MODULE_ALIAS_NFT_EXPR("objref");
+MODULE_DESCRIPTION("nftables stateful object reference module");
index b42247a..c261d57 100644 (file)
@@ -149,3 +149,4 @@ module_exit(nft_osf_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Fernando Fernandez <ffmancera@riseup.net>");
 MODULE_ALIAS_NFT_EXPR("osf");
+MODULE_DESCRIPTION("nftables passive OS fingerprint support");
index 5ece0a6..23265d7 100644 (file)
@@ -216,3 +216,4 @@ module_exit(nft_queue_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Eric Leblond <eric@regit.org>");
 MODULE_ALIAS_NFT_EXPR("queue");
+MODULE_DESCRIPTION("Netfilter nftables queue module");
index 4413690..0363f53 100644 (file)
@@ -254,3 +254,4 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
 MODULE_ALIAS_NFT_EXPR("quota");
 MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_QUOTA);
+MODULE_DESCRIPTION("Netfilter nftables quota module");
index 5b77917..2056051 100644 (file)
@@ -292,3 +292,4 @@ module_exit(nft_redir_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
 MODULE_ALIAS_NFT_EXPR("redir");
+MODULE_DESCRIPTION("Netfilter nftables redirect support");
index 00f865f..86eafbb 100644 (file)
@@ -119,3 +119,4 @@ EXPORT_SYMBOL_GPL(nft_reject_icmpv6_code);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("Netfilter x_tables over nftables module");
index f41f414..cf8f264 100644 (file)
@@ -149,3 +149,4 @@ module_exit(nft_reject_inet_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
 MODULE_ALIAS_NFT_AF_EXPR(1, "reject");
+MODULE_DESCRIPTION("Netfilter nftables reject inet support");
index 8b5acc6..8c04388 100644 (file)
@@ -1242,7 +1242,9 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,
                end += NFT_PIPAPO_GROUPS_PADDED_SIZE(f);
        }
 
-       if (!*this_cpu_ptr(m->scratch) || bsize_max > m->bsize_max) {
+       if (!*get_cpu_ptr(m->scratch) || bsize_max > m->bsize_max) {
+               put_cpu_ptr(m->scratch);
+
                err = pipapo_realloc_scratch(m, bsize_max);
                if (err)
                        return err;
@@ -1250,6 +1252,8 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,
                this_cpu_write(nft_pipapo_scratch_index, false);
 
                m->bsize_max = bsize_max;
+       } else {
+               put_cpu_ptr(m->scratch);
        }
 
        *ext2 = &e->ext;
index 62f416b..b6aad3f 100644 (file)
@@ -271,12 +271,14 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
 
                        if (nft_rbtree_interval_start(new)) {
                                if (nft_rbtree_interval_end(rbe) &&
-                                   nft_set_elem_active(&rbe->ext, genmask))
+                                   nft_set_elem_active(&rbe->ext, genmask) &&
+                                   !nft_set_elem_expired(&rbe->ext))
                                        overlap = false;
                        } else {
                                overlap = nft_rbtree_interval_end(rbe) &&
                                          nft_set_elem_active(&rbe->ext,
-                                                             genmask);
+                                                             genmask) &&
+                                         !nft_set_elem_expired(&rbe->ext);
                        }
                } else if (d > 0) {
                        p = &parent->rb_right;
@@ -284,9 +286,11 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
                        if (nft_rbtree_interval_end(new)) {
                                overlap = nft_rbtree_interval_end(rbe) &&
                                          nft_set_elem_active(&rbe->ext,
-                                                             genmask);
+                                                             genmask) &&
+                                         !nft_set_elem_expired(&rbe->ext);
                        } else if (nft_rbtree_interval_end(rbe) &&
-                                  nft_set_elem_active(&rbe->ext, genmask)) {
+                                  nft_set_elem_active(&rbe->ext, genmask) &&
+                                  !nft_set_elem_expired(&rbe->ext)) {
                                overlap = true;
                        }
                } else {
@@ -294,15 +298,18 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
                            nft_rbtree_interval_start(new)) {
                                p = &parent->rb_left;
 
-                               if (nft_set_elem_active(&rbe->ext, genmask))
+                               if (nft_set_elem_active(&rbe->ext, genmask) &&
+                                   !nft_set_elem_expired(&rbe->ext))
                                        overlap = false;
                        } else if (nft_rbtree_interval_start(rbe) &&
                                   nft_rbtree_interval_end(new)) {
                                p = &parent->rb_right;
 
-                               if (nft_set_elem_active(&rbe->ext, genmask))
+                               if (nft_set_elem_active(&rbe->ext, genmask) &&
+                                   !nft_set_elem_expired(&rbe->ext))
                                        overlap = false;
-                       } else if (nft_set_elem_active(&rbe->ext, genmask)) {
+                       } else if (nft_set_elem_active(&rbe->ext, genmask) &&
+                                  !nft_set_elem_expired(&rbe->ext)) {
                                *ext = &rbe->ext;
                                return -EEXIST;
                        } else {
index e2c1fc6..4fda8b3 100644 (file)
@@ -388,3 +388,4 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Fernando Fernandez <ffmancera@riseup.net>");
 MODULE_ALIAS_NFT_EXPR("synproxy");
 MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_SYNPROXY);
+MODULE_DESCRIPTION("nftables SYNPROXY expression support");
index 30be578..d3eb953 100644 (file)
@@ -719,3 +719,4 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
 MODULE_ALIAS_NFT_EXPR("tunnel");
 MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_TUNNEL);
+MODULE_DESCRIPTION("nftables tunnel expression support");
index a8e5f6c..b4f7bbc 100644 (file)
@@ -244,3 +244,4 @@ MODULE_ALIAS("ipt_SNAT");
 MODULE_ALIAS("ipt_DNAT");
 MODULE_ALIAS("ip6t_SNAT");
 MODULE_ALIAS("ip6t_DNAT");
+MODULE_DESCRIPTION("SNAT and DNAT targets support");
index 55ee680..9395ee8 100644 (file)
@@ -351,22 +351,11 @@ int genl_register_family(struct genl_family *family)
                start = end = GENL_ID_VFS_DQUOT;
        }
 
-       if (family->maxattr && !family->parallel_ops) {
-               family->attrbuf = kmalloc_array(family->maxattr + 1,
-                                               sizeof(struct nlattr *),
-                                               GFP_KERNEL);
-               if (family->attrbuf == NULL) {
-                       err = -ENOMEM;
-                       goto errout_locked;
-               }
-       } else
-               family->attrbuf = NULL;
-
        family->id = idr_alloc_cyclic(&genl_fam_idr, family,
                                      start, end + 1, GFP_KERNEL);
        if (family->id < 0) {
                err = family->id;
-               goto errout_free;
+               goto errout_locked;
        }
 
        err = genl_validate_assign_mc_groups(family);
@@ -385,8 +374,6 @@ int genl_register_family(struct genl_family *family)
 
 errout_remove:
        idr_remove(&genl_fam_idr, family->id);
-errout_free:
-       kfree(family->attrbuf);
 errout_locked:
        genl_unlock_all();
        return err;
@@ -419,8 +406,6 @@ int genl_unregister_family(const struct genl_family *family)
                   atomic_read(&genl_sk_destructing_cnt) == 0);
        genl_unlock();
 
-       kfree(family->attrbuf);
-
        genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0);
 
        return 0;
@@ -485,30 +470,23 @@ genl_family_rcv_msg_attrs_parse(const struct genl_family *family,
        if (!family->maxattr)
                return NULL;
 
-       if (family->parallel_ops) {
-               attrbuf = kmalloc_array(family->maxattr + 1,
-                                       sizeof(struct nlattr *), GFP_KERNEL);
-               if (!attrbuf)
-                       return ERR_PTR(-ENOMEM);
-       } else {
-               attrbuf = family->attrbuf;
-       }
+       attrbuf = kmalloc_array(family->maxattr + 1,
+                               sizeof(struct nlattr *), GFP_KERNEL);
+       if (!attrbuf)
+               return ERR_PTR(-ENOMEM);
 
        err = __nlmsg_parse(nlh, hdrlen, attrbuf, family->maxattr,
                            family->policy, validate, extack);
        if (err) {
-               if (family->parallel_ops)
-                       kfree(attrbuf);
+               kfree(attrbuf);
                return ERR_PTR(err);
        }
        return attrbuf;
 }
 
-static void genl_family_rcv_msg_attrs_free(const struct genl_family *family,
-                                          struct nlattr **attrbuf)
+static void genl_family_rcv_msg_attrs_free(struct nlattr **attrbuf)
 {
-       if (family->parallel_ops)
-               kfree(attrbuf);
+       kfree(attrbuf);
 }
 
 struct genl_start_context {
@@ -542,7 +520,7 @@ static int genl_start(struct netlink_callback *cb)
 no_attrs:
        info = genl_dumpit_info_alloc();
        if (!info) {
-               genl_family_rcv_msg_attrs_free(ctx->family, attrs);
+               genl_family_rcv_msg_attrs_free(attrs);
                return -ENOMEM;
        }
        info->family = ctx->family;
@@ -559,7 +537,7 @@ no_attrs:
        }
 
        if (rc) {
-               genl_family_rcv_msg_attrs_free(info->family, info->attrs);
+               genl_family_rcv_msg_attrs_free(info->attrs);
                genl_dumpit_info_free(info);
                cb->data = NULL;
        }
@@ -588,7 +566,7 @@ static int genl_lock_done(struct netlink_callback *cb)
                rc = ops->done(cb);
                genl_unlock();
        }
-       genl_family_rcv_msg_attrs_free(info->family, info->attrs);
+       genl_family_rcv_msg_attrs_free(info->attrs);
        genl_dumpit_info_free(info);
        return rc;
 }
@@ -601,7 +579,7 @@ static int genl_parallel_done(struct netlink_callback *cb)
 
        if (ops->done)
                rc = ops->done(cb);
-       genl_family_rcv_msg_attrs_free(info->family, info->attrs);
+       genl_family_rcv_msg_attrs_free(info->attrs);
        genl_dumpit_info_free(info);
        return rc;
 }
@@ -694,7 +672,7 @@ static int genl_family_rcv_msg_doit(const struct genl_family *family,
                family->post_doit(ops, skb, &info);
 
 out:
-       genl_family_rcv_msg_attrs_free(family, attrbuf);
+       genl_family_rcv_msg_attrs_free(attrbuf);
 
        return err;
 }
@@ -1166,60 +1144,11 @@ static struct genl_family genl_ctrl __ro_after_init = {
        .netnsok = true,
 };
 
-static int genl_bind(struct net *net, int group)
-{
-       struct genl_family *f;
-       int err = -ENOENT;
-       unsigned int id;
-
-       down_read(&cb_lock);
-
-       idr_for_each_entry(&genl_fam_idr, f, id) {
-               if (group >= f->mcgrp_offset &&
-                   group < f->mcgrp_offset + f->n_mcgrps) {
-                       int fam_grp = group - f->mcgrp_offset;
-
-                       if (!f->netnsok && net != &init_net)
-                               err = -ENOENT;
-                       else if (f->mcast_bind)
-                               err = f->mcast_bind(net, fam_grp);
-                       else
-                               err = 0;
-                       break;
-               }
-       }
-       up_read(&cb_lock);
-
-       return err;
-}
-
-static void genl_unbind(struct net *net, int group)
-{
-       struct genl_family *f;
-       unsigned int id;
-
-       down_read(&cb_lock);
-
-       idr_for_each_entry(&genl_fam_idr, f, id) {
-               if (group >= f->mcgrp_offset &&
-                   group < f->mcgrp_offset + f->n_mcgrps) {
-                       int fam_grp = group - f->mcgrp_offset;
-
-                       if (f->mcast_unbind)
-                               f->mcast_unbind(net, fam_grp);
-                       break;
-               }
-       }
-       up_read(&cb_lock);
-}
-
 static int __net_init genl_pernet_init(struct net *net)
 {
        struct netlink_kernel_cfg cfg = {
                .input          = genl_rcv,
                .flags          = NL_CFG_F_NONROOT_RECV,
-               .bind           = genl_bind,
-               .unbind         = genl_unbind,
        };
 
        /* we'll bump the group number right afterwards */
index 7cd5248..78ea8c9 100644 (file)
@@ -1228,10 +1228,13 @@ int nci_register_device(struct nci_dev *ndev)
 
        rc = nfc_register_device(ndev->nfc_dev);
        if (rc)
-               goto destroy_rx_wq_exit;
+               goto destroy_tx_wq_exit;
 
        goto exit;
 
+destroy_tx_wq_exit:
+       destroy_workqueue(ndev->tx_wq);
+
 destroy_rx_wq_exit:
        destroy_workqueue(ndev->rx_wq);
 
index fc0efd8..2611657 100644 (file)
@@ -1169,9 +1169,10 @@ static int execute_check_pkt_len(struct datapath *dp, struct sk_buff *skb,
                                 struct sw_flow_key *key,
                                 const struct nlattr *attr, bool last)
 {
+       struct ovs_skb_cb *ovs_cb = OVS_CB(skb);
        const struct nlattr *actions, *cpl_arg;
+       int len, max_len, rem = nla_len(attr);
        const struct check_pkt_len_arg *arg;
-       int rem = nla_len(attr);
        bool clone_flow_key;
 
        /* The first netlink attribute in 'attr' is always
@@ -1180,7 +1181,11 @@ static int execute_check_pkt_len(struct datapath *dp, struct sk_buff *skb,
        cpl_arg = nla_data(attr);
        arg = nla_data(cpl_arg);
 
-       if (skb->len <= arg->pkt_len) {
+       len = ovs_cb->mru ? ovs_cb->mru + skb->mac_len : skb->len;
+       max_len = arg->pkt_len;
+
+       if ((skb_is_gso(skb) && skb_gso_validate_mac_len(skb, max_len)) ||
+           len <= max_len) {
                /* Second netlink attribute in 'attr' is always
                 * 'OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL'.
                 */
index 2d8d613..300a104 100644 (file)
@@ -166,6 +166,7 @@ static void __qrtr_node_release(struct kref *kref)
 {
        struct qrtr_node *node = container_of(kref, struct qrtr_node, ref);
        struct radix_tree_iter iter;
+       struct qrtr_tx_flow *flow;
        unsigned long flags;
        void __rcu **slot;
 
@@ -181,8 +182,9 @@ static void __qrtr_node_release(struct kref *kref)
 
        /* Free tx flow counters */
        radix_tree_for_each_slot(slot, &node->qrtr_tx_flow, &iter, 0) {
+               flow = *slot;
                radix_tree_iter_delete(&node->qrtr_tx_flow, &iter, slot);
-               kfree(*slot);
+               kfree(flow);
        }
        kfree(node);
 }
@@ -427,7 +429,7 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
        unsigned int ver;
        size_t hdrlen;
 
-       if (len & 3)
+       if (len == 0 || len & 3)
                return -EINVAL;
 
        skb = netdev_alloc_skb(NULL, len);
@@ -441,6 +443,8 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
 
        switch (ver) {
        case QRTR_PROTO_VER_1:
+               if (len < sizeof(*v1))
+                       goto err;
                v1 = data;
                hdrlen = sizeof(*v1);
 
@@ -454,6 +458,8 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
                size = le32_to_cpu(v1->size);
                break;
        case QRTR_PROTO_VER_2:
+               if (len < sizeof(*v2))
+                       goto err;
                v2 = data;
                hdrlen = sizeof(*v2) + v2->optlen;
 
@@ -1174,6 +1180,7 @@ static int qrtr_release(struct socket *sock)
                sk->sk_state_change(sk);
 
        sock_set_flag(sk, SOCK_DEAD);
+       sock_orphan(sk);
        sock->sk = NULL;
 
        if (!sock_flag(sk, SOCK_ZAPPED))
index ed7f213..f2fcab1 100644 (file)
@@ -905,6 +905,17 @@ void rds_conn_path_connect_if_down(struct rds_conn_path *cp)
 }
 EXPORT_SYMBOL_GPL(rds_conn_path_connect_if_down);
 
+/* Check connectivity of all paths
+ */
+void rds_check_all_paths(struct rds_connection *conn)
+{
+       int i = 0;
+
+       do {
+               rds_conn_path_connect_if_down(&conn->c_path[i]);
+       } while (++i < conn->c_npaths);
+}
+
 void rds_conn_connect_if_down(struct rds_connection *conn)
 {
        WARN_ON(conn->c_trans->t_mp_capable);
index 5ae069d..8dfff43 100644 (file)
@@ -264,7 +264,13 @@ struct rds_ib_device {
        int                     *vector_load;
 };
 
-#define ibdev_to_node(ibdev) dev_to_node((ibdev)->dev.parent)
+static inline int ibdev_to_node(struct ib_device *ibdev)
+{
+       struct device *parent;
+
+       parent = ibdev->dev.parent;
+       return parent ? dev_to_node(parent) : NUMA_NO_NODE;
+}
 #define rdsibdev_to_node(rdsibdev) ibdev_to_node(rdsibdev->dev)
 
 /* bits for i_ack_flags */
index 6019b0c..106e862 100644 (file)
@@ -778,6 +778,7 @@ void rds_conn_drop(struct rds_connection *conn);
 void rds_conn_path_drop(struct rds_conn_path *cpath, bool destroy);
 void rds_conn_connect_if_down(struct rds_connection *conn);
 void rds_conn_path_connect_if_down(struct rds_conn_path *cp);
+void rds_check_all_paths(struct rds_connection *conn);
 void rds_for_each_conn_info(struct socket *sock, unsigned int len,
                          struct rds_info_iterator *iter,
                          struct rds_info_lengths *lens,
@@ -822,6 +823,12 @@ rds_conn_path_up(struct rds_conn_path *cp)
        return atomic_read(&cp->cp_state) == RDS_CONN_UP;
 }
 
+static inline int
+rds_conn_path_down(struct rds_conn_path *cp)
+{
+       return atomic_read(&cp->cp_state) == RDS_CONN_DOWN;
+}
+
 static inline int
 rds_conn_up(struct rds_connection *conn)
 {
index 68e2bdb..9a529a0 100644 (file)
@@ -1340,7 +1340,8 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
                goto out;
        }
 
-       rds_conn_path_connect_if_down(cpath);
+       if (rds_conn_path_down(cpath))
+               rds_check_all_paths(conn);
 
        ret = rds_cong_wait(conn->c_fcong, dport, nonblock, rs);
        if (ret) {
index 46f709a..f8001ec 100644 (file)
 #include "rds.h"
 #include "loop.h"
 
+static char * const rds_trans_modules[] = {
+       [RDS_TRANS_IB] = "rds_rdma",
+       [RDS_TRANS_GAP] = NULL,
+       [RDS_TRANS_TCP] = "rds_tcp",
+};
+
 static struct rds_transport *transports[RDS_TRANS_COUNT];
 static DECLARE_RWSEM(rds_trans_sem);
 
@@ -110,18 +116,20 @@ struct rds_transport *rds_trans_get(int t_type)
 {
        struct rds_transport *ret = NULL;
        struct rds_transport *trans;
-       unsigned int i;
 
        down_read(&rds_trans_sem);
-       for (i = 0; i < RDS_TRANS_COUNT; i++) {
-               trans = transports[i];
-
-               if (trans && trans->t_type == t_type &&
-                   (!trans->t_owner || try_module_get(trans->t_owner))) {
-                       ret = trans;
-                       break;
-               }
+       trans = transports[t_type];
+       if (!trans) {
+               up_read(&rds_trans_sem);
+               if (rds_trans_modules[t_type])
+                       request_module(rds_trans_modules[t_type]);
+               down_read(&rds_trans_sem);
+               trans = transports[t_type];
        }
+       if (trans && trans->t_type == t_type &&
+           (!trans->t_owner || try_module_get(trans->t_owner)))
+               ret = trans;
+
        up_read(&rds_trans_sem);
 
        return ret;
index b7611cc..032ed76 100644 (file)
 #include <net/ip.h>
 #include "ar-internal.h"
 
+static void rxrpc_dummy_notify(struct sock *sk, struct rxrpc_call *call,
+                              unsigned long user_call_ID)
+{
+}
+
 /*
  * Preallocate a single service call, connection and peer and, if possible,
  * give them a user ID and attach the user's side of the ID to them.
@@ -228,6 +233,8 @@ void rxrpc_discard_prealloc(struct rxrpc_sock *rx)
                if (rx->discard_new_call) {
                        _debug("discard %lx", call->user_call_ID);
                        rx->discard_new_call(call, call->user_call_ID);
+                       if (call->notify_rx)
+                               call->notify_rx = rxrpc_dummy_notify;
                        rxrpc_put_call(call, rxrpc_call_put_kernel);
                }
                rxrpc_call_completed(call);
index aa1c8ee..6be2672 100644 (file)
@@ -253,7 +253,7 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j)
                 * confuse things
                 */
                annotation &= ~RXRPC_TX_ANNO_MASK;
-               annotation |= RXRPC_TX_ANNO_RESENT;
+               annotation |= RXRPC_TX_ANNO_UNACK | RXRPC_TX_ANNO_RESENT;
                call->rxtx_annotations[ix] = annotation;
 
                skb = call->rxtx_buffer[ix];
index 299ac98..7675793 100644 (file)
@@ -722,13 +722,12 @@ static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb,
               ntohl(ackinfo->rxMTU), ntohl(ackinfo->maxMTU),
               rwind, ntohl(ackinfo->jumbo_max));
 
+       if (rwind > RXRPC_RXTX_BUFF_SIZE - 1)
+               rwind = RXRPC_RXTX_BUFF_SIZE - 1;
        if (call->tx_winsize != rwind) {
-               if (rwind > RXRPC_RXTX_BUFF_SIZE - 1)
-                       rwind = RXRPC_RXTX_BUFF_SIZE - 1;
                if (rwind > call->tx_winsize)
                        wake = true;
-               trace_rxrpc_rx_rwind_change(call, sp->hdr.serial,
-                                           ntohl(ackinfo->rwind), wake);
+               trace_rxrpc_rx_rwind_change(call, sp->hdr.serial, rwind, wake);
                call->tx_winsize = rwind;
        }
 
index 2989742..490b192 100644 (file)
@@ -543,7 +543,7 @@ try_again:
            list_empty(&rx->recvmsg_q) &&
            rx->sk.sk_state != RXRPC_SERVER_LISTENING) {
                release_sock(&rx->sk);
-               return -ENODATA;
+               return -EAGAIN;
        }
 
        if (list_empty(&rx->recvmsg_q)) {
index 1304b86..03a30d0 100644 (file)
@@ -304,7 +304,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
        /* this should be in poll */
        sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk);
 
-       if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
+       if (sk->sk_shutdown & SEND_SHUTDOWN)
                return -EPIPE;
 
        more = msg->msg_flags & MSG_MORE;
index 43a2430..f901421 100644 (file)
@@ -43,17 +43,20 @@ static int tcf_connmark_act(struct sk_buff *skb, const struct tc_action *a,
        tcf_lastuse_update(&ca->tcf_tm);
        bstats_update(&ca->tcf_bstats, skb);
 
-       if (skb->protocol == htons(ETH_P_IP)) {
+       switch (skb_protocol(skb, true)) {
+       case htons(ETH_P_IP):
                if (skb->len < sizeof(struct iphdr))
                        goto out;
 
                proto = NFPROTO_IPV4;
-       } else if (skb->protocol == htons(ETH_P_IPV6)) {
+               break;
+       case htons(ETH_P_IPV6):
                if (skb->len < sizeof(struct ipv6hdr))
                        goto out;
 
                proto = NFPROTO_IPV6;
-       } else {
+               break;
+       default:
                goto out;
        }
 
index cb8608f..c60674c 100644 (file)
@@ -587,7 +587,7 @@ static int tcf_csum_act(struct sk_buff *skb, const struct tc_action *a,
                goto drop;
 
        update_flags = params->update_flags;
-       protocol = tc_skb_protocol(skb);
+       protocol = skb_protocol(skb, false);
 again:
        switch (protocol) {
        case cpu_to_be16(ETH_P_IP):
index e29f0f4..5928efb 100644 (file)
@@ -624,7 +624,7 @@ static u8 tcf_ct_skb_nf_family(struct sk_buff *skb)
 {
        u8 family = NFPROTO_UNSPEC;
 
-       switch (skb->protocol) {
+       switch (skb_protocol(skb, true)) {
        case htons(ETH_P_IP):
                family = NFPROTO_IPV4;
                break;
@@ -673,9 +673,10 @@ static int tcf_ct_ipv6_is_fragment(struct sk_buff *skb, bool *frag)
 }
 
 static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
-                                  u8 family, u16 zone)
+                                  u8 family, u16 zone, bool *defrag)
 {
        enum ip_conntrack_info ctinfo;
+       struct qdisc_skb_cb cb;
        struct nf_conn *ct;
        int err = 0;
        bool frag;
@@ -693,6 +694,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
                return err;
 
        skb_get(skb);
+       cb = *qdisc_skb_cb(skb);
 
        if (family == NFPROTO_IPV4) {
                enum ip_defrag_users user = IP_DEFRAG_CONNTRACK_IN + zone;
@@ -703,6 +705,9 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
                local_bh_enable();
                if (err && err != -EINPROGRESS)
                        goto out_free;
+
+               if (!err)
+                       *defrag = true;
        } else { /* NFPROTO_IPV6 */
 #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
                enum ip6_defrag_users user = IP6_DEFRAG_CONNTRACK_IN + zone;
@@ -711,12 +716,16 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
                err = nf_ct_frag6_gather(net, skb, user);
                if (err && err != -EINPROGRESS)
                        goto out_free;
+
+               if (!err)
+                       *defrag = true;
 #else
                err = -EOPNOTSUPP;
                goto out_free;
 #endif
        }
 
+       *qdisc_skb_cb(skb) = cb;
        skb_clear_hash(skb);
        skb->ignore_df = 1;
        return err;
@@ -748,6 +757,7 @@ static int ct_nat_execute(struct sk_buff *skb, struct nf_conn *ct,
                          const struct nf_nat_range2 *range,
                          enum nf_nat_manip_type maniptype)
 {
+       __be16 proto = skb_protocol(skb, true);
        int hooknum, err = NF_ACCEPT;
 
        /* See HOOK2MANIP(). */
@@ -759,14 +769,13 @@ static int ct_nat_execute(struct sk_buff *skb, struct nf_conn *ct,
        switch (ctinfo) {
        case IP_CT_RELATED:
        case IP_CT_RELATED_REPLY:
-               if (skb->protocol == htons(ETH_P_IP) &&
+               if (proto == htons(ETH_P_IP) &&
                    ip_hdr(skb)->protocol == IPPROTO_ICMP) {
                        if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo,
                                                           hooknum))
                                err = NF_DROP;
                        goto out;
-               } else if (IS_ENABLED(CONFIG_IPV6) &&
-                          skb->protocol == htons(ETH_P_IPV6)) {
+               } else if (IS_ENABLED(CONFIG_IPV6) && proto == htons(ETH_P_IPV6)) {
                        __be16 frag_off;
                        u8 nexthdr = ipv6_hdr(skb)->nexthdr;
                        int hdrlen = ipv6_skip_exthdr(skb,
@@ -914,6 +923,7 @@ static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
        int nh_ofs, err, retval;
        struct tcf_ct_params *p;
        bool skip_add = false;
+       bool defrag = false;
        struct nf_conn *ct;
        u8 family;
 
@@ -925,6 +935,8 @@ static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
        force = p->ct_action & TCA_CT_ACT_FORCE;
        tmpl = p->tmpl;
 
+       tcf_lastuse_update(&c->tcf_tm);
+
        if (clear) {
                ct = nf_ct_get(skb, &ctinfo);
                if (ct) {
@@ -944,7 +956,7 @@ static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
         */
        nh_ofs = skb_network_offset(skb);
        skb_pull_rcsum(skb, nh_ofs);
-       err = tcf_ct_handle_fragments(net, skb, family, p->zone);
+       err = tcf_ct_handle_fragments(net, skb, family, p->zone, &defrag);
        if (err == -EINPROGRESS) {
                retval = TC_ACT_STOLEN;
                goto out;
@@ -1012,6 +1024,8 @@ out_push:
 
 out:
        tcf_action_update_bstats(&c->common, skb);
+       if (defrag)
+               qdisc_skb_cb(skb)->pkt_len = skb->len;
        return retval;
 
 drop:
@@ -1543,17 +1557,6 @@ static void __exit ct_cleanup_module(void)
        destroy_workqueue(act_ct_wq);
 }
 
-void tcf_ct_flow_table_restore_skb(struct sk_buff *skb, unsigned long cookie)
-{
-       enum ip_conntrack_info ctinfo = cookie & NFCT_INFOMASK;
-       struct nf_conn *ct;
-
-       ct = (struct nf_conn *)(cookie & NFCT_PTRMASK);
-       nf_conntrack_get(&ct->ct_general);
-       nf_ct_set(skb, ct, ctinfo);
-}
-EXPORT_SYMBOL_GPL(tcf_ct_flow_table_restore_skb);
-
 module_init(ct_init_module);
 module_exit(ct_cleanup_module);
 MODULE_AUTHOR("Paul Blakey <paulb@mellanox.com>");
@@ -1561,4 +1564,3 @@ MODULE_AUTHOR("Yossi Kuperman <yossiku@mellanox.com>");
 MODULE_AUTHOR("Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>");
 MODULE_DESCRIPTION("Connection tracking action");
 MODULE_LICENSE("GPL v2");
-
index 1964962..b5042f3 100644 (file)
@@ -96,19 +96,22 @@ static int tcf_ctinfo_act(struct sk_buff *skb, const struct tc_action *a,
        action = READ_ONCE(ca->tcf_action);
 
        wlen = skb_network_offset(skb);
-       if (tc_skb_protocol(skb) == htons(ETH_P_IP)) {
+       switch (skb_protocol(skb, true)) {
+       case htons(ETH_P_IP):
                wlen += sizeof(struct iphdr);
                if (!pskb_may_pull(skb, wlen))
                        goto out;
 
                proto = NFPROTO_IPV4;
-       } else if (tc_skb_protocol(skb) == htons(ETH_P_IPV6)) {
+               break;
+       case htons(ETH_P_IPV6):
                wlen += sizeof(struct ipv6hdr);
                if (!pskb_may_pull(skb, wlen))
                        goto out;
 
                proto = NFPROTO_IPV6;
-       } else {
+               break;
+       default:
                goto out;
        }
 
index 9c62859..323ae7f 100644 (file)
@@ -32,7 +32,7 @@ static ktime_t gate_get_time(struct tcf_gate *gact)
        return KTIME_MAX;
 }
 
-static int gate_get_start_time(struct tcf_gate *gact, ktime_t *start)
+static void gate_get_start_time(struct tcf_gate *gact, ktime_t *start)
 {
        struct tcf_gate_params *param = &gact->param;
        ktime_t now, base, cycle;
@@ -43,18 +43,13 @@ static int gate_get_start_time(struct tcf_gate *gact, ktime_t *start)
 
        if (ktime_after(base, now)) {
                *start = base;
-               return 0;
+               return;
        }
 
        cycle = param->tcfg_cycletime;
 
-       /* cycle time should not be zero */
-       if (!cycle)
-               return -EFAULT;
-
        n = div64_u64(ktime_sub_ns(now, base), cycle);
        *start = ktime_add_ns(base, (n + 1) * cycle);
-       return 0;
 }
 
 static void gate_start_timer(struct tcf_gate *gact, ktime_t start)
@@ -277,6 +272,27 @@ release_list:
        return err;
 }
 
+static void gate_setup_timer(struct tcf_gate *gact, u64 basetime,
+                            enum tk_offsets tko, s32 clockid,
+                            bool do_init)
+{
+       if (!do_init) {
+               if (basetime == gact->param.tcfg_basetime &&
+                   tko == gact->tk_offset &&
+                   clockid == gact->param.tcfg_clockid)
+                       return;
+
+               spin_unlock_bh(&gact->tcf_lock);
+               hrtimer_cancel(&gact->hitimer);
+               spin_lock_bh(&gact->tcf_lock);
+       }
+       gact->param.tcfg_basetime = basetime;
+       gact->param.tcfg_clockid = clockid;
+       gact->tk_offset = tko;
+       hrtimer_init(&gact->hitimer, clockid, HRTIMER_MODE_ABS_SOFT);
+       gact->hitimer.function = gate_timer_func;
+}
+
 static int tcf_gate_init(struct net *net, struct nlattr *nla,
                         struct nlattr *est, struct tc_action **a,
                         int ovr, int bind, bool rtnl_held,
@@ -287,12 +303,12 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
        enum tk_offsets tk_offset = TK_OFFS_TAI;
        struct nlattr *tb[TCA_GATE_MAX + 1];
        struct tcf_chain *goto_ch = NULL;
+       u64 cycletime = 0, basetime = 0;
        struct tcf_gate_params *p;
        s32 clockid = CLOCK_TAI;
        struct tcf_gate *gact;
        struct tc_gate *parm;
        int ret = 0, err;
-       u64 basetime = 0;
        u32 gflags = 0;
        s32 prio = -1;
        ktime_t start;
@@ -308,6 +324,27 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
        if (!tb[TCA_GATE_PARMS])
                return -EINVAL;
 
+       if (tb[TCA_GATE_CLOCKID]) {
+               clockid = nla_get_s32(tb[TCA_GATE_CLOCKID]);
+               switch (clockid) {
+               case CLOCK_REALTIME:
+                       tk_offset = TK_OFFS_REAL;
+                       break;
+               case CLOCK_MONOTONIC:
+                       tk_offset = TK_OFFS_MAX;
+                       break;
+               case CLOCK_BOOTTIME:
+                       tk_offset = TK_OFFS_BOOT;
+                       break;
+               case CLOCK_TAI:
+                       tk_offset = TK_OFFS_TAI;
+                       break;
+               default:
+                       NL_SET_ERR_MSG(extack, "Invalid 'clockid'");
+                       return -EINVAL;
+               }
+       }
+
        parm = nla_data(tb[TCA_GATE_PARMS]);
        index = parm->index;
 
@@ -331,10 +368,6 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
                tcf_idr_release(*a, bind);
                return -EEXIST;
        }
-       if (ret == ACT_P_CREATED) {
-               to_gate(*a)->param.tcfg_clockid = -1;
-               INIT_LIST_HEAD(&(to_gate(*a)->param.entries));
-       }
 
        if (tb[TCA_GATE_PRIORITY])
                prio = nla_get_s32(tb[TCA_GATE_PRIORITY]);
@@ -345,41 +378,19 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
        if (tb[TCA_GATE_FLAGS])
                gflags = nla_get_u32(tb[TCA_GATE_FLAGS]);
 
-       if (tb[TCA_GATE_CLOCKID]) {
-               clockid = nla_get_s32(tb[TCA_GATE_CLOCKID]);
-               switch (clockid) {
-               case CLOCK_REALTIME:
-                       tk_offset = TK_OFFS_REAL;
-                       break;
-               case CLOCK_MONOTONIC:
-                       tk_offset = TK_OFFS_MAX;
-                       break;
-               case CLOCK_BOOTTIME:
-                       tk_offset = TK_OFFS_BOOT;
-                       break;
-               case CLOCK_TAI:
-                       tk_offset = TK_OFFS_TAI;
-                       break;
-               default:
-                       NL_SET_ERR_MSG(extack, "Invalid 'clockid'");
-                       goto release_idr;
-               }
-       }
+       gact = to_gate(*a);
+       if (ret == ACT_P_CREATED)
+               INIT_LIST_HEAD(&gact->param.entries);
 
        err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
        if (err < 0)
                goto release_idr;
 
-       gact = to_gate(*a);
-
        spin_lock_bh(&gact->tcf_lock);
        p = &gact->param;
 
-       if (tb[TCA_GATE_CYCLE_TIME]) {
-               p->tcfg_cycletime = nla_get_u64(tb[TCA_GATE_CYCLE_TIME]);
-               if (!p->tcfg_cycletime_ext)
-                       goto chain_put;
-       }
+       if (tb[TCA_GATE_CYCLE_TIME])
+               cycletime = nla_get_u64(tb[TCA_GATE_CYCLE_TIME]);
 
        if (tb[TCA_GATE_ENTRY_LIST]) {
                err = parse_gate_list(tb[TCA_GATE_ENTRY_LIST], p, extack);
@@ -387,35 +398,29 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
                        goto chain_put;
        }
 
-       if (!p->tcfg_cycletime) {
+       if (!cycletime) {
                struct tcfg_gate_entry *entry;
                ktime_t cycle = 0;
 
                list_for_each_entry(entry, &p->entries, list)
                        cycle = ktime_add_ns(cycle, entry->interval);
-               p->tcfg_cycletime = cycle;
+               cycletime = cycle;
+               if (!cycletime) {
+                       err = -EINVAL;
+                       goto chain_put;
+               }
        }
+       p->tcfg_cycletime = cycletime;
 
        if (tb[TCA_GATE_CYCLE_TIME_EXT])
                p->tcfg_cycletime_ext =
                        nla_get_u64(tb[TCA_GATE_CYCLE_TIME_EXT]);
 
+       gate_setup_timer(gact, basetime, tk_offset, clockid,
+                        ret == ACT_P_CREATED);
        p->tcfg_priority = prio;
-       p->tcfg_basetime = basetime;
-       p->tcfg_clockid = clockid;
        p->tcfg_flags = gflags;
-
-       gact->tk_offset = tk_offset;
-       hrtimer_init(&gact->hitimer, clockid, HRTIMER_MODE_ABS_SOFT);
-       gact->hitimer.function = gate_timer_func;
-
-       err = gate_get_start_time(gact, &start);
-       if (err < 0) {
-               NL_SET_ERR_MSG(extack,
-                              "Internal error: failed get start time");
-               release_entry_list(&p->entries);
-               goto chain_put;
-       }
+       gate_get_start_time(gact, &start);
 
        gact->current_close_time = start;
        gact->current_gate_status = GATE_ACT_GATE_OPEN | GATE_ACT_PENDING;
@@ -443,6 +448,13 @@ chain_put:
        if (goto_ch)
                tcf_chain_put_by_act(goto_ch);
 release_idr:
+       /* action is not inserted in any list: it's safe to init hitimer
+        * without taking tcf_lock.
+        */
+       if (ret == ACT_P_CREATED)
+               gate_setup_timer(gact, gact->param.tcfg_basetime,
+                                gact->tk_offset, gact->param.tcfg_clockid,
+                                true);
        tcf_idr_release(*a, bind);
        return err;
 }
@@ -453,9 +465,7 @@ static void tcf_gate_cleanup(struct tc_action *a)
        struct tcf_gate_params *p;
 
        p = &gact->param;
-       if (p->tcfg_clockid != -1)
-               hrtimer_cancel(&gact->hitimer);
-
+       hrtimer_cancel(&gact->hitimer);
        release_entry_list(&p->entries);
 }
 
index be3f215..8118e26 100644 (file)
@@ -82,7 +82,7 @@ static int tcf_mpls_act(struct sk_buff *skb, const struct tc_action *a,
                        goto drop;
                break;
        case TCA_MPLS_ACT_PUSH:
-               new_lse = tcf_mpls_get_lse(NULL, p, !eth_p_mpls(skb->protocol));
+               new_lse = tcf_mpls_get_lse(NULL, p, !eth_p_mpls(skb_protocol(skb, true)));
                if (skb_mpls_push(skb, new_lse, p->tcfm_proto, mac_len,
                                  skb->dev && skb->dev->type == ARPHRD_ETHER))
                        goto drop;
index b125b2b..b2b3faa 100644 (file)
@@ -41,7 +41,7 @@ static int tcf_skbedit_act(struct sk_buff *skb, const struct tc_action *a,
        if (params->flags & SKBEDIT_F_INHERITDSFIELD) {
                int wlen = skb_network_offset(skb);
 
-               switch (tc_skb_protocol(skb)) {
+               switch (skb_protocol(skb, true)) {
                case htons(ETH_P_IP):
                        wlen += sizeof(struct iphdr);
                        if (!pskb_may_pull(skb, wlen))
index a00a203..4619cb3 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/kmod.h>
 #include <linux/slab.h>
 #include <linux/idr.h>
-#include <linux/rhashtable.h>
 #include <linux/jhash.h>
 #include <linux/rculist.h>
 #include <net/net_namespace.h>
@@ -652,6 +651,7 @@ static void tc_block_indr_cleanup(struct flow_block_cb *block_cb)
                               &block->flow_block, tcf_block_shared(block),
                               &extack);
        down_write(&block->cb_lock);
+       list_del(&block_cb->driver_list);
        list_move(&block_cb->list, &bo.cb_list);
        up_write(&block->cb_lock);
        rtnl_lock();
@@ -671,25 +671,29 @@ static int tcf_block_offload_cmd(struct tcf_block *block,
                                 struct netlink_ext_ack *extack)
 {
        struct flow_block_offload bo = {};
-       int err;
 
        tcf_block_offload_init(&bo, dev, command, ei->binder_type,
                               &block->flow_block, tcf_block_shared(block),
                               extack);
 
-       if (dev->netdev_ops->ndo_setup_tc)
+       if (dev->netdev_ops->ndo_setup_tc) {
+               int err;
+
                err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_BLOCK, &bo);
-       else
-               err = flow_indr_dev_setup_offload(dev, TC_SETUP_BLOCK, block,
-                                                 &bo, tc_block_indr_cleanup);
+               if (err < 0) {
+                       if (err != -EOPNOTSUPP)
+                               NL_SET_ERR_MSG(extack, "Driver ndo_setup_tc failed");
+                       return err;
+               }
 
-       if (err < 0) {
-               if (err != -EOPNOTSUPP)
-                       NL_SET_ERR_MSG(extack, "Driver ndo_setup_tc failed");
-               return err;
+               return tcf_block_setup(block, &bo);
        }
 
-       return tcf_block_setup(block, &bo);
+       flow_indr_dev_setup_offload(dev, TC_SETUP_BLOCK, block, &bo,
+                                   tc_block_indr_cleanup);
+       tcf_block_setup(block, &bo);
+
+       return -EOPNOTSUPP;
 }
 
 static int tcf_block_offload_bind(struct tcf_block *block, struct Qdisc *q,
@@ -1533,7 +1537,7 @@ static inline int __tcf_classify(struct sk_buff *skb,
 reclassify:
 #endif
        for (; tp; tp = rcu_dereference_bh(tp->next)) {
-               __be16 protocol = tc_skb_protocol(skb);
+               __be16 protocol = skb_protocol(skb, false);
                int err;
 
                if (tp->protocol != protocol &&
index 80ae7b9..ab53a93 100644 (file)
@@ -80,7 +80,7 @@ static u32 flow_get_dst(const struct sk_buff *skb, const struct flow_keys *flow)
        if (dst)
                return ntohl(dst);
 
-       return addr_fold(skb_dst(skb)) ^ (__force u16) tc_skb_protocol(skb);
+       return addr_fold(skb_dst(skb)) ^ (__force u16)skb_protocol(skb, true);
 }
 
 static u32 flow_get_proto(const struct sk_buff *skb,
@@ -104,7 +104,7 @@ static u32 flow_get_proto_dst(const struct sk_buff *skb,
        if (flow->ports.ports)
                return ntohs(flow->ports.dst);
 
-       return addr_fold(skb_dst(skb)) ^ (__force u16) tc_skb_protocol(skb);
+       return addr_fold(skb_dst(skb)) ^ (__force u16)skb_protocol(skb, true);
 }
 
 static u32 flow_get_iif(const struct sk_buff *skb)
@@ -151,7 +151,7 @@ static u32 flow_get_nfct(const struct sk_buff *skb)
 static u32 flow_get_nfct_src(const struct sk_buff *skb,
                             const struct flow_keys *flow)
 {
-       switch (tc_skb_protocol(skb)) {
+       switch (skb_protocol(skb, true)) {
        case htons(ETH_P_IP):
                return ntohl(CTTUPLE(skb, src.u3.ip));
        case htons(ETH_P_IPV6):
@@ -164,7 +164,7 @@ fallback:
 static u32 flow_get_nfct_dst(const struct sk_buff *skb,
                             const struct flow_keys *flow)
 {
-       switch (tc_skb_protocol(skb)) {
+       switch (skb_protocol(skb, true)) {
        case htons(ETH_P_IP):
                return ntohl(CTTUPLE(skb, dst.u3.ip));
        case htons(ETH_P_IPV6):
index b2da372..e30bd96 100644 (file)
@@ -313,7 +313,7 @@ static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp,
                /* skb_flow_dissect() does not set n_proto in case an unknown
                 * protocol, so do it rather here.
                 */
-               skb_key.basic.n_proto = skb->protocol;
+               skb_key.basic.n_proto = skb_protocol(skb, false);
                skb_flow_dissect_tunnel_info(skb, &mask->dissector, &skb_key);
                skb_flow_dissect_ct(skb, &mask->dissector, &skb_key,
                                    fl_ct_info_to_flower_map,
index df00566..c95cf86 100644 (file)
@@ -59,7 +59,7 @@ static int em_ipset_match(struct sk_buff *skb, struct tcf_ematch *em,
        };
        int ret, network_offset;
 
-       switch (tc_skb_protocol(skb)) {
+       switch (skb_protocol(skb, true)) {
        case htons(ETH_P_IP):
                state.pf = NFPROTO_IPV4;
                if (!pskb_network_may_pull(skb, sizeof(struct iphdr)))
index 18755d2..3650117 100644 (file)
@@ -212,7 +212,7 @@ static int em_ipt_match(struct sk_buff *skb, struct tcf_ematch *em,
        struct nf_hook_state state;
        int ret;
 
-       switch (tc_skb_protocol(skb)) {
+       switch (skb_protocol(skb, true)) {
        case htons(ETH_P_IP):
                if (!pskb_network_may_pull(skb, sizeof(struct iphdr)))
                        return 0;
index d99966a..4625496 100644 (file)
@@ -195,7 +195,7 @@ META_COLLECTOR(int_priority)
 META_COLLECTOR(int_protocol)
 {
        /* Let userspace take care of the byte ordering */
-       dst->value = tc_skb_protocol(skb);
+       dst->value = skb_protocol(skb, false);
 }
 
 META_COLLECTOR(int_pkttype)
index ee12ca9..1c281cc 100644 (file)
@@ -553,16 +553,16 @@ static int atm_tc_init(struct Qdisc *sch, struct nlattr *opt,
        if (!p->link.q)
                p->link.q = &noop_qdisc;
        pr_debug("atm_tc_init: link (%p) qdisc %p\n", &p->link, p->link.q);
+       p->link.vcc = NULL;
+       p->link.sock = NULL;
+       p->link.common.classid = sch->handle;
+       p->link.ref = 1;
 
        err = tcf_block_get(&p->link.block, &p->link.filter_list, sch,
                            extack);
        if (err)
                return err;
 
-       p->link.vcc = NULL;
-       p->link.sock = NULL;
-       p->link.common.classid = sch->handle;
-       p->link.ref = 1;
        tasklet_init(&p->task, sch_atm_dequeue, (unsigned long)sch);
        return 0;
 }
index 60f8ae5..ebaeec1 100644 (file)
@@ -592,7 +592,7 @@ static bool cake_update_flowkeys(struct flow_keys *keys,
        bool rev = !skb->_nfct, upd = false;
        __be32 ip;
 
-       if (tc_skb_protocol(skb) != htons(ETH_P_IP))
+       if (skb_protocol(skb, true) != htons(ETH_P_IP))
                return false;
 
        if (!nf_ct_get_tuple_skb(&tuple, skb))
@@ -1551,32 +1551,51 @@ static unsigned int cake_drop(struct Qdisc *sch, struct sk_buff **to_free)
        return idx + (tin << 16);
 }
 
-static u8 cake_handle_diffserv(struct sk_buff *skb, u16 wash)
+static u8 cake_handle_diffserv(struct sk_buff *skb, bool wash)
 {
-       int wlen = skb_network_offset(skb);
+       const int offset = skb_network_offset(skb);
+       u16 *buf, buf_;
        u8 dscp;
 
-       switch (tc_skb_protocol(skb)) {
+       switch (skb_protocol(skb, true)) {
        case htons(ETH_P_IP):
-               wlen += sizeof(struct iphdr);
-               if (!pskb_may_pull(skb, wlen) ||
-                   skb_try_make_writable(skb, wlen))
+               buf = skb_header_pointer(skb, offset, sizeof(buf_), &buf_);
+               if (unlikely(!buf))
                        return 0;
 
-               dscp = ipv4_get_dsfield(ip_hdr(skb)) >> 2;
-               if (wash && dscp)
+               /* ToS is in the second byte of iphdr */
+               dscp = ipv4_get_dsfield((struct iphdr *)buf) >> 2;
+
+               if (wash && dscp) {
+                       const int wlen = offset + sizeof(struct iphdr);
+
+                       if (!pskb_may_pull(skb, wlen) ||
+                           skb_try_make_writable(skb, wlen))
+                               return 0;
+
                        ipv4_change_dsfield(ip_hdr(skb), INET_ECN_MASK, 0);
+               }
+
                return dscp;
 
        case htons(ETH_P_IPV6):
-               wlen += sizeof(struct ipv6hdr);
-               if (!pskb_may_pull(skb, wlen) ||
-                   skb_try_make_writable(skb, wlen))
+               buf = skb_header_pointer(skb, offset, sizeof(buf_), &buf_);
+               if (unlikely(!buf))
                        return 0;
 
-               dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2;
-               if (wash && dscp)
+               /* Traffic class is in the first and second bytes of ipv6hdr */
+               dscp = ipv6_get_dsfield((struct ipv6hdr *)buf) >> 2;
+
+               if (wash && dscp) {
+                       const int wlen = offset + sizeof(struct ipv6hdr);
+
+                       if (!pskb_may_pull(skb, wlen) ||
+                           skb_try_make_writable(skb, wlen))
+                               return 0;
+
                        ipv6_change_dsfield(ipv6_hdr(skb), INET_ECN_MASK, 0);
+               }
+
                return dscp;
 
        case htons(ETH_P_ARP):
@@ -1593,14 +1612,17 @@ static struct cake_tin_data *cake_select_tin(struct Qdisc *sch,
 {
        struct cake_sched_data *q = qdisc_priv(sch);
        u32 tin, mark;
+       bool wash;
        u8 dscp;
 
        /* Tin selection: Default to diffserv-based selection, allow overriding
-        * using firewall marks or skb->priority.
+        * using firewall marks or skb->priority. Call DSCP parsing early if
+        * wash is enabled, otherwise defer to below to skip unneeded parsing.
         */
-       dscp = cake_handle_diffserv(skb,
-                                   q->rate_flags & CAKE_FLAG_WASH);
        mark = (skb->mark & q->fwmark_mask) >> q->fwmark_shft;
+       wash = !!(q->rate_flags & CAKE_FLAG_WASH);
+       if (wash)
+               dscp = cake_handle_diffserv(skb, wash);
 
        if (q->tin_mode == CAKE_DIFFSERV_BESTEFFORT)
                tin = 0;
@@ -1614,6 +1636,8 @@ static struct cake_tin_data *cake_select_tin(struct Qdisc *sch,
                tin = q->tin_order[TC_H_MIN(skb->priority) - 1];
 
        else {
+               if (!wash)
+                       dscp = cake_handle_diffserv(skb, wash);
                tin = q->tin_index[dscp];
 
                if (unlikely(tin >= q->tin_cnt))
@@ -2691,7 +2715,7 @@ static int cake_init(struct Qdisc *sch, struct nlattr *opt,
        qdisc_watchdog_init(&q->watchdog, sch);
 
        if (opt) {
-               int err = cake_change(sch, opt, extack);
+               err = cake_change(sch, opt, extack);
 
                if (err)
                        return err;
@@ -3008,7 +3032,7 @@ static int cake_dump_class_stats(struct Qdisc *sch, unsigned long cl,
                        PUT_STAT_S32(BLUE_TIMER_US,
                                     ktime_to_us(
                                             ktime_sub(now,
-                                                    flow->cvars.blue_timer)));
+                                                      flow->cvars.blue_timer)));
                }
                if (flow->cvars.dropping) {
                        PUT_STAT_S32(DROP_NEXT_US,
index 05605b3..2b88710 100644 (file)
@@ -210,7 +210,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        if (p->set_tc_index) {
                int wlen = skb_network_offset(skb);
 
-               switch (tc_skb_protocol(skb)) {
+               switch (skb_protocol(skb, true)) {
                case htons(ETH_P_IP):
                        wlen += sizeof(struct iphdr);
                        if (!pskb_may_pull(skb, wlen) ||
@@ -303,7 +303,7 @@ static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
        index = skb->tc_index & (p->indices - 1);
        pr_debug("index %d->%d\n", skb->tc_index, index);
 
-       switch (tc_skb_protocol(skb)) {
+       switch (skb_protocol(skb, true)) {
        case htons(ETH_P_IP):
                ipv4_change_dsfield(ip_hdr(skb), p->mv[index].mask,
                                    p->mv[index].value);
@@ -320,7 +320,7 @@ static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
                 */
                if (p->mv[index].mask != 0xff || p->mv[index].value)
                        pr_warn("%s: unsupported protocol %d\n",
-                               __func__, ntohs(tc_skb_protocol(skb)));
+                               __func__, ntohs(skb_protocol(skb, true)));
                break;
        }
 
index 8f06a80..2fb76fc 100644 (file)
@@ -1075,3 +1075,4 @@ module_init(fq_module_init)
 module_exit(fq_module_exit)
 MODULE_AUTHOR("Eric Dumazet");
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Fair Queue Packet Scheduler");
index 436160b..459a784 100644 (file)
@@ -721,3 +721,4 @@ module_init(fq_codel_module_init)
 module_exit(fq_codel_module_exit)
 MODULE_AUTHOR("Eric Dumazet");
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Fair Queue CoDel discipline");
index be35f03..420ede8 100644 (file)
@@ -721,3 +721,4 @@ module_exit(hhf_module_exit)
 MODULE_AUTHOR("Terry Lam");
 MODULE_AUTHOR("Nandita Dukkipati");
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Heavy-Hitter Filter (HHF)");
index 689ef6f..2f1f0a3 100644 (file)
@@ -239,7 +239,7 @@ __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res,
                char haddr[MAX_ADDR_LEN];
 
                neigh_ha_snapshot(haddr, n, dev);
-               err = dev_hard_header(skb, dev, ntohs(tc_skb_protocol(skb)),
+               err = dev_hard_header(skb, dev, ntohs(skb_protocol(skb, false)),
                                      haddr, NULL, skb->len);
 
                if (err < 0)
index 7231513..8d73546 100644 (file)
@@ -1565,12 +1565,15 @@ void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len)
 int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc,
                                     enum sctp_scope scope, gfp_t gfp)
 {
+       struct sock *sk = asoc->base.sk;
        int flags;
 
        /* Use scoping rules to determine the subset of addresses from
         * the endpoint.
         */
-       flags = (PF_INET6 == asoc->base.sk->sk_family) ? SCTP_ADDR6_ALLOWED : 0;
+       flags = (PF_INET6 == sk->sk_family) ? SCTP_ADDR6_ALLOWED : 0;
+       if (!inet_v6_ipv6only(sk))
+               flags |= SCTP_ADDR4_ALLOWED;
        if (asoc->peer.ipv4_address)
                flags |= SCTP_ADDR4_PEERSUPP;
        if (asoc->peer.ipv6_address)
index 53bc615..701c5a4 100644 (file)
@@ -461,6 +461,7 @@ static int sctp_copy_one_addr(struct net *net, struct sctp_bind_addr *dest,
                 * well as the remote peer.
                 */
                if ((((AF_INET == addr->sa.sa_family) &&
+                     (flags & SCTP_ADDR4_ALLOWED) &&
                      (flags & SCTP_ADDR4_PEERSUPP))) ||
                    (((AF_INET6 == addr->sa.sa_family) &&
                      (flags & SCTP_ADDR6_ALLOWED) &&
index 092d1af..cde29f3 100644 (file)
@@ -148,7 +148,8 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
                 * sock as well as the remote peer.
                 */
                if (addr->a.sa.sa_family == AF_INET &&
-                   !(copy_flags & SCTP_ADDR4_PEERSUPP))
+                   (!(copy_flags & SCTP_ADDR4_ALLOWED) ||
+                    !(copy_flags & SCTP_ADDR4_PEERSUPP)))
                        continue;
                if (addr->a.sa.sa_family == AF_INET6 &&
                    (!(copy_flags & SCTP_ADDR6_ALLOWED) ||
index 67f7e71..bda2536 100644 (file)
 #include <net/sctp/sm.h>
 #include <net/sctp/stream_sched.h>
 
-/* 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.
- */
-static void sctp_stream_outq_migrate(struct sctp_stream *stream,
-                                    struct sctp_stream *new, __u16 outcnt)
+static void sctp_stream_shrink_out(struct sctp_stream *stream, __u16 outcnt)
 {
        struct sctp_association *asoc;
        struct sctp_chunk *ch, *temp;
        struct sctp_outq *outq;
-       int i;
 
        asoc = container_of(stream, struct sctp_association, stream);
        outq = &asoc->outqueue;
@@ -56,6 +50,19 @@ static void sctp_stream_outq_migrate(struct sctp_stream *stream,
 
                sctp_chunk_free(ch);
        }
+}
+
+/* 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.
+ */
+static void sctp_stream_outq_migrate(struct sctp_stream *stream,
+                                    struct sctp_stream *new, __u16 outcnt)
+{
+       int i;
+
+       if (stream->outcnt > outcnt)
+               sctp_stream_shrink_out(stream, outcnt);
 
        if (new) {
                /* Here we actually move the old ext stuff into the new
@@ -1037,11 +1044,13 @@ struct sctp_chunk *sctp_process_strreset_resp(
                nums = ntohs(addstrm->number_of_streams);
                number = stream->outcnt - nums;
 
-               if (result == SCTP_STRRESET_PERFORMED)
+               if (result == SCTP_STRRESET_PERFORMED) {
                        for (i = number; i < stream->outcnt; i++)
                                SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
-               else
+               } else {
+                       sctp_stream_shrink_out(stream, number);
                        stream->outcnt = number;
+               }
 
                *evp = sctp_ulpevent_make_stream_change_event(asoc, flags,
                        0, nums, GFP_ATOMIC);
index 9033215..1163d51 100644 (file)
@@ -126,8 +126,10 @@ EXPORT_SYMBOL_GPL(smc_proto6);
 
 static void smc_restore_fallback_changes(struct smc_sock *smc)
 {
-       smc->clcsock->file->private_data = smc->sk.sk_socket;
-       smc->clcsock->file = NULL;
+       if (smc->clcsock->file) { /* non-accepted sockets have no file yet */
+               smc->clcsock->file->private_data = smc->sk.sk_socket;
+               smc->clcsock->file = NULL;
+       }
 }
 
 static int __smc_release(struct smc_sock *smc)
@@ -352,7 +354,7 @@ static int smcr_lgr_reg_rmbs(struct smc_link *link,
         */
        mutex_lock(&lgr->llc_conf_mutex);
        for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
-               if (lgr->lnk[i].state != SMC_LNK_ACTIVE)
+               if (!smc_link_active(&lgr->lnk[i]))
                        continue;
                rc = smcr_link_reg_rmb(&lgr->lnk[i], rmb_desc);
                if (rc)
@@ -632,7 +634,9 @@ static int smc_connect_rdma(struct smc_sock *smc,
                for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
                        struct smc_link *l = &smc->conn.lgr->lnk[i];
 
-                       if (l->peer_qpn == ntoh24(aclc->qpn)) {
+                       if (l->peer_qpn == ntoh24(aclc->qpn) &&
+                           !memcmp(l->peer_gid, &aclc->lcl.gid, SMC_GID_SIZE) &&
+                           !memcmp(l->peer_mac, &aclc->lcl.mac, sizeof(l->peer_mac))) {
                                link = l;
                                break;
                        }
index a47e885..ce468ff 100644 (file)
@@ -66,9 +66,13 @@ int smc_cdc_get_free_slot(struct smc_connection *conn,
        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->killed)
+       if (conn->killed) {
                /* abnormal termination */
+               if (!rc)
+                       smc_wr_tx_put_slot(link,
+                                          (struct smc_wr_tx_pend_priv *)pend);
                rc = -EPIPE;
+       }
        return rc;
 }
 
index d5627df..779f414 100644 (file)
@@ -27,6 +27,7 @@
 
 #define SMCR_CLC_ACCEPT_CONFIRM_LEN 68
 #define SMCD_CLC_ACCEPT_CONFIRM_LEN 48
+#define SMC_CLC_RECV_BUF_LEN   100
 
 /* eye catcher "SMCR" EBCDIC for CLC messages */
 static const char SMC_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xd9'};
@@ -36,7 +37,7 @@ static const char SMCD_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xc4'};
 /* check if received message has a correct header length and contains valid
  * heading and trailing eyecatchers
  */
-static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
+static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm, bool check_trl)
 {
        struct smc_clc_msg_proposal_prefix *pclc_prfx;
        struct smc_clc_msg_accept_confirm *clc;
@@ -49,12 +50,9 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
                return false;
        switch (clcm->type) {
        case SMC_CLC_PROPOSAL:
-               if (clcm->path != SMC_TYPE_R && clcm->path != SMC_TYPE_D &&
-                   clcm->path != SMC_TYPE_B)
-                       return false;
                pclc = (struct smc_clc_msg_proposal *)clcm;
                pclc_prfx = smc_clc_proposal_get_prefix(pclc);
-               if (ntohs(pclc->hdr.length) !=
+               if (ntohs(pclc->hdr.length) <
                        sizeof(*pclc) + ntohs(pclc->iparea_offset) +
                        sizeof(*pclc_prfx) +
                        pclc_prfx->ipv6_prefixes_cnt *
@@ -86,7 +84,8 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
        default:
                return false;
        }
-       if (memcmp(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) &&
+       if (check_trl &&
+           memcmp(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) &&
            memcmp(trl->eyecatcher, SMCD_EYECATCHER, sizeof(SMCD_EYECATCHER)))
                return false;
        return true;
@@ -276,7 +275,8 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
        struct msghdr msg = {NULL, 0};
        int reason_code = 0;
        struct kvec vec = {buf, buflen};
-       int len, datlen;
+       int len, datlen, recvlen;
+       bool check_trl = true;
        int krflags;
 
        /* peek the first few bytes to determine length of data to receive
@@ -320,10 +320,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
        }
        datlen = ntohs(clcm->length);
        if ((len < sizeof(struct smc_clc_msg_hdr)) ||
-           (datlen > buflen) ||
-           (clcm->version != SMC_CLC_V1) ||
-           (clcm->path != SMC_TYPE_R && clcm->path != SMC_TYPE_D &&
-            clcm->path != SMC_TYPE_B) ||
+           (clcm->version < SMC_CLC_V1) ||
            ((clcm->type != SMC_CLC_DECLINE) &&
             (clcm->type != expected_type))) {
                smc->sk.sk_err = EPROTO;
@@ -331,16 +328,38 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
                goto out;
        }
 
+       if (clcm->type == SMC_CLC_PROPOSAL && clcm->path == SMC_TYPE_N)
+               reason_code = SMC_CLC_DECL_VERSMISMAT; /* just V2 offered */
+
        /* receive the complete CLC message */
        memset(&msg, 0, sizeof(struct msghdr));
-       iov_iter_kvec(&msg.msg_iter, READ, &vec, 1, datlen);
+       if (datlen > buflen) {
+               check_trl = false;
+               recvlen = buflen;
+       } else {
+               recvlen = datlen;
+       }
+       iov_iter_kvec(&msg.msg_iter, READ, &vec, 1, recvlen);
        krflags = MSG_WAITALL;
        len = sock_recvmsg(smc->clcsock, &msg, krflags);
-       if (len < datlen || !smc_clc_msg_hdr_valid(clcm)) {
+       if (len < recvlen || !smc_clc_msg_hdr_valid(clcm, check_trl)) {
                smc->sk.sk_err = EPROTO;
                reason_code = -EPROTO;
                goto out;
        }
+       datlen -= len;
+       while (datlen) {
+               u8 tmp[SMC_CLC_RECV_BUF_LEN];
+
+               vec.iov_base = &tmp;
+               vec.iov_len = SMC_CLC_RECV_BUF_LEN;
+               /* receive remaining proposal message */
+               recvlen = datlen > SMC_CLC_RECV_BUF_LEN ?
+                                               SMC_CLC_RECV_BUF_LEN : datlen;
+               iov_iter_kvec(&msg.msg_iter, READ, &vec, 1, recvlen);
+               len = sock_recvmsg(smc->clcsock, &msg, krflags);
+               datlen -= len;
+       }
        if (clcm->type == SMC_CLC_DECLINE) {
                struct smc_clc_msg_decline *dclc;
 
index 4658767..76c2b15 100644 (file)
@@ -25,6 +25,7 @@
 #define SMC_CLC_V1             0x1             /* SMC version                */
 #define SMC_TYPE_R             0               /* SMC-R only                 */
 #define SMC_TYPE_D             1               /* SMC-D only                 */
+#define SMC_TYPE_N             2               /* neither SMC-R nor SMC-D    */
 #define SMC_TYPE_B             3               /* SMC-R and SMC-D            */
 #define CLC_WAIT_TIME          (6 * HZ)        /* max. wait time on clcsock  */
 #define CLC_WAIT_TIME_SHORT    HZ              /* short wait time on clcsock */
@@ -46,6 +47,7 @@
 #define SMC_CLC_DECL_ISMVLANERR        0x03090000  /* err to reg vlan id on ism dev  */
 #define SMC_CLC_DECL_NOACTLINK 0x030a0000  /* no active smc-r link in lgr    */
 #define SMC_CLC_DECL_NOSRVLINK 0x030b0000  /* SMC-R link from srv not found  */
+#define SMC_CLC_DECL_VERSMISMAT        0x030c0000  /* SMC version mismatch           */
 #define SMC_CLC_DECL_SYNCERR   0x04000000  /* synchronization error          */
 #define SMC_CLC_DECL_PEERDECL  0x05000000  /* peer declined during handshake */
 #define SMC_CLC_DECL_INTERR    0x09990000  /* internal error                 */
index 7964a21..f82a2e5 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/workqueue.h>
 #include <linux/wait.h>
 #include <linux/reboot.h>
+#include <linux/mutex.h>
 #include <net/tcp.h>
 #include <net/sock.h>
 #include <rdma/ib_verbs.h>
@@ -44,18 +45,10 @@ static struct smc_lgr_list smc_lgr_list = { /* established link groups */
 static atomic_t lgr_cnt = ATOMIC_INIT(0); /* number of existing link groups */
 static DECLARE_WAIT_QUEUE_HEAD(lgrs_deleted);
 
-struct smc_ib_up_work {
-       struct work_struct      work;
-       struct smc_link_group   *lgr;
-       struct smc_ib_device    *smcibdev;
-       u8                      ibport;
-};
-
 static void smc_buf_free(struct smc_link_group *lgr, bool is_rmb,
                         struct smc_buf_desc *buf_desc);
 static void __smc_lgr_terminate(struct smc_link_group *lgr, bool soft);
 
-static void smc_link_up_work(struct work_struct *work);
 static void smc_link_down_work(struct work_struct *work);
 
 /* return head of link group list and its lock for a given link group */
@@ -247,7 +240,8 @@ static void smcr_lgr_link_deactivate_all(struct smc_link_group *lgr)
                if (smc_link_usable(lnk))
                        lnk->state = SMC_LNK_INACTIVE;
        }
-       wake_up_interruptible_all(&lgr->llc_waiter);
+       wake_up_all(&lgr->llc_msg_waiter);
+       wake_up_all(&lgr->llc_flow_waiter);
 }
 
 static void smc_lgr_free(struct smc_link_group *lgr);
@@ -324,7 +318,6 @@ int smcr_link_init(struct smc_link_group *lgr, struct smc_link *lnk,
 
        get_device(&ini->ib_dev->ibdev->dev);
        atomic_inc(&ini->ib_dev->lnk_cnt);
-       lnk->state = SMC_LNK_ACTIVATING;
        lnk->link_id = smcr_next_link_id(lgr);
        lnk->lgr = lgr;
        lnk->link_idx = link_idx;
@@ -360,6 +353,7 @@ int smcr_link_init(struct smc_link_group *lgr, struct smc_link *lnk,
        rc = smc_wr_create_link(lnk);
        if (rc)
                goto destroy_qp;
+       lnk->state = SMC_LNK_ACTIVATING;
        return 0;
 
 destroy_qp:
@@ -450,7 +444,7 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
        }
        smc->conn.lgr = lgr;
        spin_lock_bh(lgr_lock);
-       list_add(&lgr->list, lgr_list);
+       list_add_tail(&lgr->list, lgr_list);
        spin_unlock_bh(lgr_lock);
        return 0;
 
@@ -548,8 +542,7 @@ struct smc_link *smc_switch_conns(struct smc_link_group *lgr,
        smc_wr_wakeup_tx_wait(from_lnk);
 
        for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
-               if (lgr->lnk[i].state != SMC_LNK_ACTIVE ||
-                   i == from_lnk->link_idx)
+               if (!smc_link_active(&lgr->lnk[i]) || i == from_lnk->link_idx)
                        continue;
                if (is_dev_err && from_lnk->smcibdev == lgr->lnk[i].smcibdev &&
                    from_lnk->ibport == lgr->lnk[i].ibport) {
@@ -1104,66 +1097,23 @@ static void smc_conn_abort_work(struct work_struct *work)
        sock_put(&smc->sk); /* sock_hold done by schedulers of abort_work */
 }
 
-/* link is up - establish alternate link if applicable */
-static void smcr_link_up(struct smc_link_group *lgr,
-                        struct smc_ib_device *smcibdev, u8 ibport)
-{
-       struct smc_link *link = NULL;
-
-       if (list_empty(&lgr->list) ||
-           lgr->type == SMC_LGR_SYMMETRIC ||
-           lgr->type == SMC_LGR_ASYMMETRIC_PEER)
-               return;
-
-       if (lgr->role == SMC_SERV) {
-               /* trigger local add link processing */
-               link = smc_llc_usable_link(lgr);
-               if (!link)
-                       return;
-               smc_llc_srv_add_link_local(link);
-       } else {
-               /* invite server to start add link processing */
-               u8 gid[SMC_GID_SIZE];
-
-               if (smc_ib_determine_gid(smcibdev, ibport, lgr->vlan_id, gid,
-                                        NULL))
-                       return;
-               if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE) {
-                       /* some other llc task is ongoing */
-                       wait_event_interruptible_timeout(lgr->llc_waiter,
-                               (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_NONE),
-                               SMC_LLC_WAIT_TIME);
-               }
-               if (list_empty(&lgr->list) ||
-                   !smc_ib_port_active(smcibdev, ibport))
-                       return; /* lgr or device no longer active */
-               link = smc_llc_usable_link(lgr);
-               if (!link)
-                       return;
-               smc_llc_send_add_link(link, smcibdev->mac[ibport - 1], gid,
-                                     NULL, SMC_LLC_REQ);
-       }
-}
-
 void smcr_port_add(struct smc_ib_device *smcibdev, u8 ibport)
 {
-       struct smc_ib_up_work *ib_work;
        struct smc_link_group *lgr, *n;
 
        list_for_each_entry_safe(lgr, n, &smc_lgr_list.list, list) {
+               struct smc_link *link;
+
                if (strncmp(smcibdev->pnetid[ibport - 1], lgr->pnet_id,
                            SMC_MAX_PNETID_LEN) ||
                    lgr->type == SMC_LGR_SYMMETRIC ||
                    lgr->type == SMC_LGR_ASYMMETRIC_PEER)
                        continue;
-               ib_work = kmalloc(sizeof(*ib_work), GFP_KERNEL);
-               if (!ib_work)
-                       continue;
-               INIT_WORK(&ib_work->work, smc_link_up_work);
-               ib_work->lgr = lgr;
-               ib_work->smcibdev = smcibdev;
-               ib_work->ibport = ibport;
-               schedule_work(&ib_work->work);
+
+               /* trigger local add link processing */
+               link = smc_llc_usable_link(lgr);
+               if (link)
+                       smc_llc_add_link_local(link);
        }
 }
 
@@ -1195,13 +1145,19 @@ static void smcr_link_down(struct smc_link *lnk)
                if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE) {
                        /* another llc task is ongoing */
                        mutex_unlock(&lgr->llc_conf_mutex);
-                       wait_event_interruptible_timeout(lgr->llc_waiter,
-                               (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_NONE),
+                       wait_event_timeout(lgr->llc_flow_waiter,
+                               (list_empty(&lgr->list) ||
+                                lgr->llc_flow_lcl.type == SMC_LLC_FLOW_NONE),
                                SMC_LLC_WAIT_TIME);
                        mutex_lock(&lgr->llc_conf_mutex);
                }
-               smc_llc_send_delete_link(to_lnk, del_link_id, SMC_LLC_REQ, true,
-                                        SMC_LLC_DEL_LOST_PATH);
+               if (!list_empty(&lgr->list)) {
+                       smc_llc_send_delete_link(to_lnk, del_link_id,
+                                                SMC_LLC_REQ, true,
+                                                SMC_LLC_DEL_LOST_PATH);
+                       smcr_link_clear(lnk, true);
+               }
+               wake_up(&lgr->llc_flow_waiter); /* wake up next waiter */
        }
 }
 
@@ -1240,20 +1196,6 @@ void smcr_port_err(struct smc_ib_device *smcibdev, u8 ibport)
        }
 }
 
-static void smc_link_up_work(struct work_struct *work)
-{
-       struct smc_ib_up_work *ib_work = container_of(work,
-                                                     struct smc_ib_up_work,
-                                                     work);
-       struct smc_link_group *lgr = ib_work->lgr;
-
-       if (list_empty(&lgr->list))
-               goto out;
-       smcr_link_up(lgr, ib_work->smcibdev, ib_work->ibport);
-out:
-       kfree(ib_work);
-}
-
 static void smc_link_down_work(struct work_struct *work)
 {
        struct smc_link *link = container_of(work, struct smc_link,
@@ -1262,7 +1204,7 @@ static void smc_link_down_work(struct work_struct *work)
 
        if (list_empty(&lgr->list))
                return;
-       wake_up_interruptible_all(&lgr->llc_waiter);
+       wake_up_all(&lgr->llc_msg_waiter);
        mutex_lock(&lgr->llc_conf_mutex);
        smcr_link_down(link);
        mutex_unlock(&lgr->llc_conf_mutex);
@@ -1326,7 +1268,7 @@ static bool smcr_lgr_match(struct smc_link_group *lgr,
                return false;
 
        for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
-               if (lgr->lnk[i].state != SMC_LNK_ACTIVE)
+               if (!smc_link_active(&lgr->lnk[i]))
                        continue;
                if ((lgr->role == SMC_SERV || lgr->lnk[i].peer_qpn == clcqpn) &&
                    !memcmp(lgr->lnk[i].peer_gid, &lcl->gid, SMC_GID_SIZE) &&
@@ -1369,7 +1311,7 @@ int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini)
                     smcr_lgr_match(lgr, ini->ib_lcl, role, ini->ib_clcqpn)) &&
                    !lgr->sync_err &&
                    lgr->vlan_id == ini->vlan_id &&
-                   (role == SMC_CLNT ||
+                   (role == SMC_CLNT || ini->is_smcd ||
                     lgr->conns_num < SMC_RMBS_PER_LGR_MAX)) {
                        /* link group found */
                        ini->cln_first_contact = SMC_REUSE_CONTACT;
@@ -1774,14 +1716,14 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb)
 
 void smc_sndbuf_sync_sg_for_cpu(struct smc_connection *conn)
 {
-       if (!conn->lgr || conn->lgr->is_smcd || !smc_link_usable(conn->lnk))
+       if (!conn->lgr || conn->lgr->is_smcd || !smc_link_active(conn->lnk))
                return;
        smc_ib_sync_sg_for_cpu(conn->lnk, conn->sndbuf_desc, DMA_TO_DEVICE);
 }
 
 void smc_sndbuf_sync_sg_for_device(struct smc_connection *conn)
 {
-       if (!conn->lgr || conn->lgr->is_smcd || !smc_link_usable(conn->lnk))
+       if (!conn->lgr || conn->lgr->is_smcd || !smc_link_active(conn->lnk))
                return;
        smc_ib_sync_sg_for_device(conn->lnk, conn->sndbuf_desc, DMA_TO_DEVICE);
 }
@@ -1793,7 +1735,7 @@ void smc_rmb_sync_sg_for_cpu(struct smc_connection *conn)
        if (!conn->lgr || conn->lgr->is_smcd)
                return;
        for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
-               if (!smc_link_usable(&conn->lgr->lnk[i]))
+               if (!smc_link_active(&conn->lgr->lnk[i]))
                        continue;
                smc_ib_sync_sg_for_cpu(&conn->lgr->lnk[i], conn->rmb_desc,
                                       DMA_FROM_DEVICE);
@@ -1807,7 +1749,7 @@ void smc_rmb_sync_sg_for_device(struct smc_connection *conn)
        if (!conn->lgr || conn->lgr->is_smcd)
                return;
        for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
-               if (!smc_link_usable(&conn->lgr->lnk[i]))
+               if (!smc_link_active(&conn->lgr->lnk[i]))
                        continue;
                smc_ib_sync_sg_for_device(&conn->lgr->lnk[i], conn->rmb_desc,
                                          DMA_FROM_DEVICE);
@@ -1830,8 +1772,12 @@ int smc_buf_create(struct smc_sock *smc, bool is_smcd)
                return rc;
        /* create rmb */
        rc = __smc_buf_create(smc, is_smcd, true);
-       if (rc)
+       if (rc) {
+               mutex_lock(&smc->conn.lgr->sndbufs_lock);
+               list_del(&smc->conn.sndbuf_desc->list);
+               mutex_unlock(&smc->conn.lgr->sndbufs_lock);
                smc_buf_free(smc->conn.lgr, false, smc->conn.sndbuf_desc);
+       }
        return rc;
 }
 
@@ -1955,20 +1901,20 @@ static void smc_core_going_away(void)
        struct smc_ib_device *smcibdev;
        struct smcd_dev *smcd;
 
-       spin_lock(&smc_ib_devices.lock);
+       mutex_lock(&smc_ib_devices.mutex);
        list_for_each_entry(smcibdev, &smc_ib_devices.list, list) {
                int i;
 
                for (i = 0; i < SMC_MAX_PORTS; i++)
                        set_bit(i, smcibdev->ports_going_away);
        }
-       spin_unlock(&smc_ib_devices.lock);
+       mutex_unlock(&smc_ib_devices.mutex);
 
-       spin_lock(&smcd_dev_list.lock);
+       mutex_lock(&smcd_dev_list.mutex);
        list_for_each_entry(smcd, &smcd_dev_list.list, list) {
                smcd->going_away = 1;
        }
-       spin_unlock(&smcd_dev_list.lock);
+       mutex_unlock(&smcd_dev_list.mutex);
 }
 
 /* Clean up all SMC link groups */
@@ -1980,10 +1926,10 @@ static void smc_lgrs_shutdown(void)
 
        smc_smcr_terminate_all(NULL);
 
-       spin_lock(&smcd_dev_list.lock);
+       mutex_lock(&smcd_dev_list.mutex);
        list_for_each_entry(smcd, &smcd_dev_list.list, list)
                smc_smcd_terminate_all(smcd);
-       spin_unlock(&smcd_dev_list.lock);
+       mutex_unlock(&smcd_dev_list.mutex);
 }
 
 static int smc_core_reboot_event(struct notifier_block *this,
index 86d160f..1c4d543 100644 (file)
@@ -262,8 +262,10 @@ struct smc_link_group {
                        struct work_struct      llc_del_link_work;
                        struct work_struct      llc_event_work;
                                                /* llc event worker */
-                       wait_queue_head_t       llc_waiter;
+                       wait_queue_head_t       llc_flow_waiter;
                                                /* w4 next llc event */
+                       wait_queue_head_t       llc_msg_waiter;
+                                               /* w4 next llc msg */
                        struct smc_llc_flow     llc_flow_lcl;
                                                /* llc local control field */
                        struct smc_llc_flow     llc_flow_rmt;
@@ -347,6 +349,11 @@ static inline bool smc_link_usable(struct smc_link *lnk)
        return true;
 }
 
+static inline bool smc_link_active(struct smc_link *lnk)
+{
+       return lnk->state == SMC_LNK_ACTIVE;
+}
+
 struct smc_sock;
 struct smc_clc_msg_accept_confirm;
 struct smc_clc_msg_local;
index 562a52d..1c314db 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/workqueue.h>
 #include <linux/scatterlist.h>
 #include <linux/wait.h>
+#include <linux/mutex.h>
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_cache.h>
 
@@ -33,7 +34,7 @@
 #define SMC_QP_RNR_RETRY                       7 /* 7: infinite */
 
 struct smc_ib_devices smc_ib_devices = {       /* smc-registered ib devices */
-       .lock = __SPIN_LOCK_UNLOCKED(smc_ib_devices.lock),
+       .mutex = __MUTEX_INITIALIZER(smc_ib_devices.mutex),
        .list = LIST_HEAD_INIT(smc_ib_devices.list),
 };
 
@@ -505,6 +506,10 @@ long smc_ib_setup_per_ibdev(struct smc_ib_device *smcibdev)
        int cqe_size_order, smc_order;
        long rc;
 
+       mutex_lock(&smcibdev->mutex);
+       rc = 0;
+       if (smcibdev->initialized)
+               goto out;
        /* the calculated number of cq entries fits to mlx5 cq allocation */
        cqe_size_order = cache_line_size() == 128 ? 7 : 6;
        smc_order = MAX_ORDER - cqe_size_order - 1;
@@ -516,7 +521,7 @@ long smc_ib_setup_per_ibdev(struct smc_ib_device *smcibdev)
        rc = PTR_ERR_OR_ZERO(smcibdev->roce_cq_send);
        if (IS_ERR(smcibdev->roce_cq_send)) {
                smcibdev->roce_cq_send = NULL;
-               return rc;
+               goto out;
        }
        smcibdev->roce_cq_recv = ib_create_cq(smcibdev->ibdev,
                                              smc_wr_rx_cq_handler, NULL,
@@ -528,21 +533,26 @@ long smc_ib_setup_per_ibdev(struct smc_ib_device *smcibdev)
        }
        smc_wr_add_dev(smcibdev);
        smcibdev->initialized = 1;
-       return rc;
+       goto out;
 
 err:
        ib_destroy_cq(smcibdev->roce_cq_send);
+out:
+       mutex_unlock(&smcibdev->mutex);
        return rc;
 }
 
 static void smc_ib_cleanup_per_ibdev(struct smc_ib_device *smcibdev)
 {
+       mutex_lock(&smcibdev->mutex);
        if (!smcibdev->initialized)
-               return;
+               goto out;
        smcibdev->initialized = 0;
        ib_destroy_cq(smcibdev->roce_cq_recv);
        ib_destroy_cq(smcibdev->roce_cq_send);
        smc_wr_remove_dev(smcibdev);
+out:
+       mutex_unlock(&smcibdev->mutex);
 }
 
 static struct ib_client smc_ib_client;
@@ -565,9 +575,10 @@ static int smc_ib_add_dev(struct ib_device *ibdev)
        INIT_WORK(&smcibdev->port_event_work, smc_ib_port_event_work);
        atomic_set(&smcibdev->lnk_cnt, 0);
        init_waitqueue_head(&smcibdev->lnks_deleted);
-       spin_lock(&smc_ib_devices.lock);
+       mutex_init(&smcibdev->mutex);
+       mutex_lock(&smc_ib_devices.mutex);
        list_add_tail(&smcibdev->list, &smc_ib_devices.list);
-       spin_unlock(&smc_ib_devices.lock);
+       mutex_unlock(&smc_ib_devices.mutex);
        ib_set_client_data(ibdev, &smc_ib_client, smcibdev);
        INIT_IB_EVENT_HANDLER(&smcibdev->event_handler, smcibdev->ibdev,
                              smc_ib_global_event_handler);
@@ -602,9 +613,9 @@ static void smc_ib_remove_dev(struct ib_device *ibdev, void *client_data)
 {
        struct smc_ib_device *smcibdev = client_data;
 
-       spin_lock(&smc_ib_devices.lock);
+       mutex_lock(&smc_ib_devices.mutex);
        list_del_init(&smcibdev->list); /* remove from smc_ib_devices */
-       spin_unlock(&smc_ib_devices.lock);
+       mutex_unlock(&smc_ib_devices.mutex);
        pr_warn_ratelimited("smc: removing ib device %s\n",
                            smcibdev->ibdev->name);
        smc_smcr_terminate_all(smcibdev);
index e6a696a..2ce4811 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/if_ether.h>
+#include <linux/mutex.h>
 #include <linux/wait.h>
 #include <rdma/ib_verbs.h>
 #include <net/smc.h>
@@ -25,7 +26,7 @@
 
 struct smc_ib_devices {                        /* list of smc ib devices definition */
        struct list_head        list;
-       spinlock_t              lock;   /* protects list of smc ib devices */
+       struct mutex            mutex;  /* protects list of smc ib devices */
 };
 
 extern struct smc_ib_devices   smc_ib_devices; /* list of smc ib devices */
@@ -51,6 +52,7 @@ struct smc_ib_device {                                /* ib-device infos for smc */
        DECLARE_BITMAP(ports_going_away, SMC_MAX_PORTS);
        atomic_t                lnk_cnt;        /* number of links on ibdev */
        wait_queue_head_t       lnks_deleted;   /* wait 4 removal of all links*/
+       struct mutex            mutex;          /* protect dev setup+cleanup */
 };
 
 struct smc_buf_desc;
index 91f85fc..998c525 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 #include <asm/page.h>
 
@@ -17,7 +18,7 @@
 
 struct smcd_dev_list smcd_dev_list = {
        .list = LIST_HEAD_INIT(smcd_dev_list.list),
-       .lock = __SPIN_LOCK_UNLOCKED(smcd_dev_list.lock)
+       .mutex = __MUTEX_INITIALIZER(smcd_dev_list.mutex)
 };
 
 /* Test if an ISM communication is possible. */
@@ -317,9 +318,9 @@ EXPORT_SYMBOL_GPL(smcd_alloc_dev);
 
 int smcd_register_dev(struct smcd_dev *smcd)
 {
-       spin_lock(&smcd_dev_list.lock);
+       mutex_lock(&smcd_dev_list.mutex);
        list_add_tail(&smcd->list, &smcd_dev_list.list);
-       spin_unlock(&smcd_dev_list.lock);
+       mutex_unlock(&smcd_dev_list.mutex);
 
        pr_warn_ratelimited("smc: adding smcd device %s with pnetid %.16s%s\n",
                            dev_name(&smcd->dev), smcd->pnetid,
@@ -333,9 +334,9 @@ void smcd_unregister_dev(struct smcd_dev *smcd)
 {
        pr_warn_ratelimited("smc: removing smcd device %s\n",
                            dev_name(&smcd->dev));
-       spin_lock(&smcd_dev_list.lock);
+       mutex_lock(&smcd_dev_list.mutex);
        list_del_init(&smcd->list);
-       spin_unlock(&smcd_dev_list.lock);
+       mutex_unlock(&smcd_dev_list.mutex);
        smcd->going_away = 1;
        smc_smcd_terminate_all(smcd);
        flush_workqueue(smcd->event_wq);
index 4da946c..81cc453 100644 (file)
 #define SMCD_ISM_H
 
 #include <linux/uio.h>
+#include <linux/mutex.h>
 
 #include "smc.h"
 
 struct smcd_dev_list { /* List of SMCD devices */
        struct list_head list;
-       spinlock_t lock;        /* Protects list of devices */
+       struct mutex mutex;     /* Protects list of devices */
 };
 
 extern struct smcd_dev_list    smcd_dev_list; /* list of smcd devices */
index 391237b..df5b0a6 100644 (file)
@@ -186,6 +186,26 @@ static inline void smc_llc_flow_qentry_set(struct smc_llc_flow *flow,
        flow->qentry = qentry;
 }
 
+static void smc_llc_flow_parallel(struct smc_link_group *lgr, u8 flow_type,
+                                 struct smc_llc_qentry *qentry)
+{
+       u8 msg_type = qentry->msg.raw.hdr.common.type;
+
+       if ((msg_type == SMC_LLC_ADD_LINK || msg_type == SMC_LLC_DELETE_LINK) &&
+           flow_type != msg_type && !lgr->delayed_event) {
+               lgr->delayed_event = qentry;
+               return;
+       }
+       /* drop parallel or already-in-progress llc requests */
+       if (flow_type != msg_type)
+               pr_warn_once("smc: SMC-R lg %*phN dropped parallel "
+                            "LLC msg: msg %d flow %d role %d\n",
+                            SMC_LGR_ID_SIZE, &lgr->id,
+                            qentry->msg.raw.hdr.common.type,
+                            flow_type, lgr->role);
+       kfree(qentry);
+}
+
 /* try to start a new llc flow, initiated by an incoming llc msg */
 static bool smc_llc_flow_start(struct smc_llc_flow *flow,
                               struct smc_llc_qentry *qentry)
@@ -195,14 +215,7 @@ static bool smc_llc_flow_start(struct smc_llc_flow *flow,
        spin_lock_bh(&lgr->llc_flow_lock);
        if (flow->type) {
                /* a flow is already active */
-               if ((qentry->msg.raw.hdr.common.type == SMC_LLC_ADD_LINK ||
-                    qentry->msg.raw.hdr.common.type == SMC_LLC_DELETE_LINK) &&
-                   !lgr->delayed_event) {
-                       lgr->delayed_event = qentry;
-               } else {
-                       /* forget this llc request */
-                       kfree(qentry);
-               }
+               smc_llc_flow_parallel(lgr, flow->type, qentry);
                spin_unlock_bh(&lgr->llc_flow_lock);
                return false;
        }
@@ -222,8 +235,8 @@ static bool smc_llc_flow_start(struct smc_llc_flow *flow,
        }
        if (qentry == lgr->delayed_event)
                lgr->delayed_event = NULL;
-       spin_unlock_bh(&lgr->llc_flow_lock);
        smc_llc_flow_qentry_set(flow, qentry);
+       spin_unlock_bh(&lgr->llc_flow_lock);
        return true;
 }
 
@@ -251,11 +264,11 @@ again:
                return 0;
        }
        spin_unlock_bh(&lgr->llc_flow_lock);
-       rc = wait_event_interruptible_timeout(lgr->llc_waiter,
-                       (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_NONE &&
-                        (lgr->llc_flow_rmt.type == SMC_LLC_FLOW_NONE ||
-                         lgr->llc_flow_rmt.type == allowed_remote)),
-                       SMC_LLC_WAIT_TIME);
+       rc = wait_event_timeout(lgr->llc_flow_waiter, (list_empty(&lgr->list) ||
+                               (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_NONE &&
+                                (lgr->llc_flow_rmt.type == SMC_LLC_FLOW_NONE ||
+                                 lgr->llc_flow_rmt.type == allowed_remote))),
+                               SMC_LLC_WAIT_TIME * 10);
        if (!rc)
                return -ETIMEDOUT;
        goto again;
@@ -272,7 +285,7 @@ void smc_llc_flow_stop(struct smc_link_group *lgr, struct smc_llc_flow *flow)
            flow == &lgr->llc_flow_lcl)
                schedule_work(&lgr->llc_event_work);
        else
-               wake_up_interruptible(&lgr->llc_waiter);
+               wake_up(&lgr->llc_flow_waiter);
 }
 
 /* lnk is optional and used for early wakeup when link goes down, useful in
@@ -283,26 +296,32 @@ struct smc_llc_qentry *smc_llc_wait(struct smc_link_group *lgr,
                                    int time_out, u8 exp_msg)
 {
        struct smc_llc_flow *flow = &lgr->llc_flow_lcl;
+       u8 rcv_msg;
 
-       wait_event_interruptible_timeout(lgr->llc_waiter,
-                                        (flow->qentry ||
-                                         (lnk && !smc_link_usable(lnk)) ||
-                                         list_empty(&lgr->list)),
-                                        time_out);
+       wait_event_timeout(lgr->llc_msg_waiter,
+                          (flow->qentry ||
+                           (lnk && !smc_link_usable(lnk)) ||
+                           list_empty(&lgr->list)),
+                          time_out);
        if (!flow->qentry ||
            (lnk && !smc_link_usable(lnk)) || list_empty(&lgr->list)) {
                smc_llc_flow_qentry_del(flow);
                goto out;
        }
-       if (exp_msg && flow->qentry->msg.raw.hdr.common.type != exp_msg) {
+       rcv_msg = flow->qentry->msg.raw.hdr.common.type;
+       if (exp_msg && rcv_msg != exp_msg) {
                if (exp_msg == SMC_LLC_ADD_LINK &&
-                   flow->qentry->msg.raw.hdr.common.type ==
-                   SMC_LLC_DELETE_LINK) {
+                   rcv_msg == SMC_LLC_DELETE_LINK) {
                        /* flow_start will delay the unexpected msg */
                        smc_llc_flow_start(&lgr->llc_flow_lcl,
                                           smc_llc_flow_qentry_clr(flow));
                        return NULL;
                }
+               pr_warn_once("smc: SMC-R lg %*phN dropped unexpected LLC msg: "
+                            "msg %d exp %d flow %d role %d flags %x\n",
+                            SMC_LGR_ID_SIZE, &lgr->id, rcv_msg, exp_msg,
+                            flow->type, lgr->role,
+                            flow->qentry->msg.raw.hdr.flags);
                smc_llc_flow_qentry_del(flow);
        }
 out:
@@ -409,7 +428,7 @@ static int smc_llc_send_confirm_rkey(struct smc_link *send_link,
        rtok_ix = 1;
        for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
                link = &send_link->lgr->lnk[i];
-               if (link->state == SMC_LNK_ACTIVE && link != send_link) {
+               if (smc_link_active(link) && link != send_link) {
                        rkeyllc->rtoken[rtok_ix].link_id = link->link_id;
                        rkeyllc->rtoken[rtok_ix].rmb_key =
                                htonl(rmb_desc->mr_rx[link->link_idx]->rkey);
@@ -876,6 +895,36 @@ out:
        return rc;
 }
 
+/* as an SMC client, invite server to start the add_link processing */
+static void smc_llc_cli_add_link_invite(struct smc_link *link,
+                                       struct smc_llc_qentry *qentry)
+{
+       struct smc_link_group *lgr = smc_get_lgr(link);
+       struct smc_init_info ini;
+
+       if (lgr->type == SMC_LGR_SYMMETRIC ||
+           lgr->type == SMC_LGR_ASYMMETRIC_PEER)
+               goto out;
+
+       ini.vlan_id = lgr->vlan_id;
+       smc_pnet_find_alt_roce(lgr, &ini, link->smcibdev);
+       if (!ini.ib_dev)
+               goto out;
+
+       smc_llc_send_add_link(link, ini.ib_dev->mac[ini.ib_port - 1],
+                             ini.ib_gid, NULL, SMC_LLC_REQ);
+out:
+       kfree(qentry);
+}
+
+static bool smc_llc_is_local_add_link(union smc_llc_msg *llc)
+{
+       if (llc->raw.hdr.common.type == SMC_LLC_ADD_LINK &&
+           !llc->add_link.qp_mtu && !llc->add_link.link_num)
+               return true;
+       return false;
+}
+
 static void smc_llc_process_cli_add_link(struct smc_link_group *lgr)
 {
        struct smc_llc_qentry *qentry;
@@ -883,7 +932,10 @@ static void smc_llc_process_cli_add_link(struct smc_link_group *lgr)
        qentry = smc_llc_flow_qentry_clr(&lgr->llc_flow_lcl);
 
        mutex_lock(&lgr->llc_conf_mutex);
-       smc_llc_cli_add_link(qentry->link, qentry);
+       if (smc_llc_is_local_add_link(&qentry->msg))
+               smc_llc_cli_add_link_invite(qentry->link, qentry);
+       else
+               smc_llc_cli_add_link(qentry->link, qentry);
        mutex_unlock(&lgr->llc_conf_mutex);
 }
 
@@ -892,7 +944,7 @@ static int smc_llc_active_link_count(struct smc_link_group *lgr)
        int i, link_count = 0;
 
        for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
-               if (!smc_link_usable(&lgr->lnk[i]))
+               if (!smc_link_active(&lgr->lnk[i]))
                        continue;
                link_count++;
        }
@@ -1032,12 +1084,14 @@ static int smc_llc_srv_conf_link(struct smc_link *link,
        if (rc)
                return -ENOLINK;
        /* receive CONFIRM LINK response over the RoCE fabric */
-       qentry = smc_llc_wait(lgr, link, SMC_LLC_WAIT_FIRST_TIME,
-                             SMC_LLC_CONFIRM_LINK);
-       if (!qentry) {
+       qentry = smc_llc_wait(lgr, link, SMC_LLC_WAIT_FIRST_TIME, 0);
+       if (!qentry ||
+           qentry->msg.raw.hdr.common.type != SMC_LLC_CONFIRM_LINK) {
                /* send DELETE LINK */
                smc_llc_send_delete_link(link, link_new->link_id, SMC_LLC_REQ,
                                         false, SMC_LLC_DEL_LOST_PATH);
+               if (qentry)
+                       smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
                return -ENOLINK;
        }
        smc_llc_save_peer_uid(qentry);
@@ -1139,14 +1193,14 @@ static void smc_llc_process_srv_add_link(struct smc_link_group *lgr)
        mutex_unlock(&lgr->llc_conf_mutex);
 }
 
-/* enqueue a local add_link req to trigger a new add_link flow, only as SERV */
-void smc_llc_srv_add_link_local(struct smc_link *link)
+/* enqueue a local add_link req to trigger a new add_link flow */
+void smc_llc_add_link_local(struct smc_link *link)
 {
        struct smc_llc_msg_add_link add_llc = {0};
 
        add_llc.hd.length = sizeof(add_llc);
        add_llc.hd.common.type = SMC_LLC_ADD_LINK;
-       /* no dev and port needed, we as server ignore client data anyway */
+       /* no dev and port needed */
        smc_llc_enqueue(link, (union smc_llc_msg *)&add_llc);
 }
 
@@ -1222,8 +1276,8 @@ static void smc_llc_process_cli_delete_link(struct smc_link_group *lgr)
        smc_llc_send_message(lnk, &qentry->msg); /* response */
 
        if (smc_link_downing(&lnk_del->state)) {
-               smc_switch_conns(lgr, lnk_del, false);
-               smc_wr_tx_wait_no_pending_sends(lnk_del);
+               if (smc_switch_conns(lgr, lnk_del, false))
+                       smc_wr_tx_wait_no_pending_sends(lnk_del);
        }
        smcr_link_clear(lnk_del, true);
 
@@ -1297,8 +1351,8 @@ static void smc_llc_process_srv_delete_link(struct smc_link_group *lgr)
                goto out; /* asymmetric link already deleted */
 
        if (smc_link_downing(&lnk_del->state)) {
-               smc_switch_conns(lgr, lnk_del, false);
-               smc_wr_tx_wait_no_pending_sends(lnk_del);
+               if (smc_switch_conns(lgr, lnk_del, false))
+                       smc_wr_tx_wait_no_pending_sends(lnk_del);
        }
        if (!list_empty(&lgr->list)) {
                /* qentry is either a request from peer (send it back to
@@ -1326,7 +1380,7 @@ static void smc_llc_process_srv_delete_link(struct smc_link_group *lgr)
 
        if (lgr->type == SMC_LGR_SINGLE && !list_empty(&lgr->list)) {
                /* trigger setup of asymm alt link */
-               smc_llc_srv_add_link_local(lnk);
+               smc_llc_add_link_local(lnk);
        }
 out:
        mutex_unlock(&lgr->llc_conf_mutex);
@@ -1455,11 +1509,22 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
                if (list_empty(&lgr->list))
                        goto out;       /* lgr is terminating */
                if (lgr->role == SMC_CLNT) {
-                       if (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_ADD_LINK) {
+                       if (smc_llc_is_local_add_link(llc)) {
+                               if (lgr->llc_flow_lcl.type ==
+                                   SMC_LLC_FLOW_ADD_LINK)
+                                       break;  /* add_link in progress */
+                               if (smc_llc_flow_start(&lgr->llc_flow_lcl,
+                                                      qentry)) {
+                                       schedule_work(&lgr->llc_add_link_work);
+                               }
+                               return;
+                       }
+                       if (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_ADD_LINK &&
+                           !lgr->llc_flow_lcl.qentry) {
                                /* a flow is waiting for this message */
                                smc_llc_flow_qentry_set(&lgr->llc_flow_lcl,
                                                        qentry);
-                               wake_up_interruptible(&lgr->llc_waiter);
+                               wake_up(&lgr->llc_msg_waiter);
                        } else if (smc_llc_flow_start(&lgr->llc_flow_lcl,
                                                      qentry)) {
                                schedule_work(&lgr->llc_add_link_work);
@@ -1474,33 +1539,18 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
                if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE) {
                        /* a flow is waiting for this message */
                        smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, qentry);
-                       wake_up_interruptible(&lgr->llc_waiter);
+                       wake_up(&lgr->llc_msg_waiter);
                        return;
                }
                break;
        case SMC_LLC_DELETE_LINK:
-               if (lgr->role == SMC_CLNT) {
-                       /* server requests to delete this link, send response */
-                       if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE) {
-                               /* DEL LINK REQ during ADD LINK SEQ */
-                               smc_llc_flow_qentry_set(&lgr->llc_flow_lcl,
-                                                       qentry);
-                               wake_up_interruptible(&lgr->llc_waiter);
-                       } else if (smc_llc_flow_start(&lgr->llc_flow_lcl,
-                                                     qentry)) {
-                               schedule_work(&lgr->llc_del_link_work);
-                       }
-               } else {
-                       if (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_ADD_LINK &&
-                           !lgr->llc_flow_lcl.qentry) {
-                               /* DEL LINK REQ during ADD LINK SEQ */
-                               smc_llc_flow_qentry_set(&lgr->llc_flow_lcl,
-                                                       qentry);
-                               wake_up_interruptible(&lgr->llc_waiter);
-                       } else if (smc_llc_flow_start(&lgr->llc_flow_lcl,
-                                                     qentry)) {
-                               schedule_work(&lgr->llc_del_link_work);
-                       }
+               if (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_ADD_LINK &&
+                   !lgr->llc_flow_lcl.qentry) {
+                       /* DEL LINK REQ during ADD LINK SEQ */
+                       smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, qentry);
+                       wake_up(&lgr->llc_msg_waiter);
+               } else if (smc_llc_flow_start(&lgr->llc_flow_lcl, qentry)) {
+                       schedule_work(&lgr->llc_del_link_work);
                }
                return;
        case SMC_LLC_CONFIRM_RKEY:
@@ -1566,23 +1616,30 @@ again:
 static void smc_llc_rx_response(struct smc_link *link,
                                struct smc_llc_qentry *qentry)
 {
+       enum smc_llc_flowtype flowtype = link->lgr->llc_flow_lcl.type;
+       struct smc_llc_flow *flow = &link->lgr->llc_flow_lcl;
        u8 llc_type = qentry->msg.raw.hdr.common.type;
 
        switch (llc_type) {
        case SMC_LLC_TEST_LINK:
-               if (link->state == SMC_LNK_ACTIVE)
+               if (smc_link_active(link))
                        complete(&link->llc_testlink_resp);
                break;
        case SMC_LLC_ADD_LINK:
-       case SMC_LLC_DELETE_LINK:
-       case SMC_LLC_CONFIRM_LINK:
        case SMC_LLC_ADD_LINK_CONT:
+       case SMC_LLC_CONFIRM_LINK:
+               if (flowtype != SMC_LLC_FLOW_ADD_LINK || flow->qentry)
+                       break;  /* drop out-of-flow response */
+               goto assign;
+       case SMC_LLC_DELETE_LINK:
+               if (flowtype != SMC_LLC_FLOW_DEL_LINK || flow->qentry)
+                       break;  /* drop out-of-flow response */
+               goto assign;
        case SMC_LLC_CONFIRM_RKEY:
        case SMC_LLC_DELETE_RKEY:
-               /* assign responses to the local flow, we requested them */
-               smc_llc_flow_qentry_set(&link->lgr->llc_flow_lcl, qentry);
-               wake_up_interruptible(&link->lgr->llc_waiter);
-               return;
+               if (flowtype != SMC_LLC_FLOW_RKEY || flow->qentry)
+                       break;  /* drop out-of-flow response */
+               goto assign;
        case SMC_LLC_CONFIRM_RKEY_CONT:
                /* not used because max links is 3 */
                break;
@@ -1591,6 +1648,11 @@ static void smc_llc_rx_response(struct smc_link *link,
                break;
        }
        kfree(qentry);
+       return;
+assign:
+       /* assign responses to the local flow, we requested them */
+       smc_llc_flow_qentry_set(&link->lgr->llc_flow_lcl, qentry);
+       wake_up(&link->lgr->llc_msg_waiter);
 }
 
 static void smc_llc_enqueue(struct smc_link *link, union smc_llc_msg *llc)
@@ -1616,7 +1678,7 @@ static void smc_llc_enqueue(struct smc_link *link, union smc_llc_msg *llc)
        spin_lock_irqsave(&lgr->llc_event_q_lock, flags);
        list_add_tail(&qentry->list, &lgr->llc_event_q);
        spin_unlock_irqrestore(&lgr->llc_event_q_lock, flags);
-       schedule_work(&link->lgr->llc_event_work);
+       schedule_work(&lgr->llc_event_work);
 }
 
 /* copy received msg and add it to the event queue */
@@ -1644,7 +1706,7 @@ static void smc_llc_testlink_work(struct work_struct *work)
        u8 user_data[16] = { 0 };
        int rc;
 
-       if (link->state != SMC_LNK_ACTIVE)
+       if (!smc_link_active(link))
                return;         /* don't reschedule worker */
        expire_time = link->wr_rx_tstamp + link->llc_testlink_time;
        if (time_is_after_jiffies(expire_time)) {
@@ -1656,7 +1718,7 @@ static void smc_llc_testlink_work(struct work_struct *work)
        /* receive TEST LINK response over RoCE fabric */
        rc = wait_for_completion_interruptible_timeout(&link->llc_testlink_resp,
                                                       SMC_LLC_WAIT_TIME);
-       if (link->state != SMC_LNK_ACTIVE)
+       if (!smc_link_active(link))
                return;         /* link state changed */
        if (rc <= 0) {
                smcr_link_down_cond_sched(link);
@@ -1677,7 +1739,8 @@ void smc_llc_lgr_init(struct smc_link_group *lgr, struct smc_sock *smc)
        INIT_LIST_HEAD(&lgr->llc_event_q);
        spin_lock_init(&lgr->llc_event_q_lock);
        spin_lock_init(&lgr->llc_flow_lock);
-       init_waitqueue_head(&lgr->llc_waiter);
+       init_waitqueue_head(&lgr->llc_flow_waiter);
+       init_waitqueue_head(&lgr->llc_msg_waiter);
        mutex_init(&lgr->llc_conf_mutex);
        lgr->llc_testlink_time = net->ipv4.sysctl_tcp_keepalive_time;
 }
@@ -1686,7 +1749,8 @@ void smc_llc_lgr_init(struct smc_link_group *lgr, struct smc_sock *smc)
 void smc_llc_lgr_clear(struct smc_link_group *lgr)
 {
        smc_llc_event_flush(lgr);
-       wake_up_interruptible_all(&lgr->llc_waiter);
+       wake_up_all(&lgr->llc_flow_waiter);
+       wake_up_all(&lgr->llc_msg_waiter);
        cancel_work_sync(&lgr->llc_event_work);
        cancel_work_sync(&lgr->llc_add_link_work);
        cancel_work_sync(&lgr->llc_del_link_work);
index a5d2fe3..cc00a2e 100644 (file)
@@ -103,7 +103,7 @@ void smc_llc_send_link_delete_all(struct smc_link_group *lgr, bool ord,
                                  u32 rsn);
 int smc_llc_cli_add_link(struct smc_link *link, struct smc_llc_qentry *qentry);
 int smc_llc_srv_add_link(struct smc_link *link);
-void smc_llc_srv_add_link_local(struct smc_link *link);
+void smc_llc_add_link_local(struct smc_link *link);
 int smc_llc_init(void) __init;
 
 #endif /* SMC_LLC_H */
index 014d91b..30e5fac 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/list.h>
 #include <linux/ctype.h>
+#include <linux/mutex.h>
 #include <net/netlink.h>
 #include <net/genetlink.h>
 
@@ -129,7 +130,7 @@ static int smc_pnet_remove_by_pnetid(struct net *net, char *pnet_name)
                return rc;
 
        /* remove ib devices */
-       spin_lock(&smc_ib_devices.lock);
+       mutex_lock(&smc_ib_devices.mutex);
        list_for_each_entry(ibdev, &smc_ib_devices.list, list) {
                for (ibport = 0; ibport < SMC_MAX_PORTS; ibport++) {
                        if (ibdev->pnetid_by_user[ibport] &&
@@ -149,9 +150,9 @@ static int smc_pnet_remove_by_pnetid(struct net *net, char *pnet_name)
                        }
                }
        }
-       spin_unlock(&smc_ib_devices.lock);
+       mutex_unlock(&smc_ib_devices.mutex);
        /* remove smcd devices */
-       spin_lock(&smcd_dev_list.lock);
+       mutex_lock(&smcd_dev_list.mutex);
        list_for_each_entry(smcd_dev, &smcd_dev_list.list, list) {
                if (smcd_dev->pnetid_by_user &&
                    (!pnet_name ||
@@ -165,7 +166,7 @@ static int smc_pnet_remove_by_pnetid(struct net *net, char *pnet_name)
                        rc = 0;
                }
        }
-       spin_unlock(&smcd_dev_list.lock);
+       mutex_unlock(&smcd_dev_list.mutex);
        return rc;
 }
 
@@ -240,14 +241,14 @@ static bool smc_pnet_apply_ib(struct smc_ib_device *ib_dev, u8 ib_port,
        u8 pnet_null[SMC_MAX_PNETID_LEN] = {0};
        bool applied = false;
 
-       spin_lock(&smc_ib_devices.lock);
+       mutex_lock(&smc_ib_devices.mutex);
        if (smc_pnet_match(ib_dev->pnetid[ib_port - 1], pnet_null)) {
                memcpy(ib_dev->pnetid[ib_port - 1], pnet_name,
                       SMC_MAX_PNETID_LEN);
                ib_dev->pnetid_by_user[ib_port - 1] = true;
                applied = true;
        }
-       spin_unlock(&smc_ib_devices.lock);
+       mutex_unlock(&smc_ib_devices.mutex);
        return applied;
 }
 
@@ -258,13 +259,13 @@ static bool smc_pnet_apply_smcd(struct smcd_dev *smcd_dev, char *pnet_name)
        u8 pnet_null[SMC_MAX_PNETID_LEN] = {0};
        bool applied = false;
 
-       spin_lock(&smcd_dev_list.lock);
+       mutex_lock(&smcd_dev_list.mutex);
        if (smc_pnet_match(smcd_dev->pnetid, pnet_null)) {
                memcpy(smcd_dev->pnetid, pnet_name, SMC_MAX_PNETID_LEN);
                smcd_dev->pnetid_by_user = true;
                applied = true;
        }
-       spin_unlock(&smcd_dev_list.lock);
+       mutex_unlock(&smcd_dev_list.mutex);
        return applied;
 }
 
@@ -300,7 +301,7 @@ static struct smc_ib_device *smc_pnet_find_ib(char *ib_name)
 {
        struct smc_ib_device *ibdev;
 
-       spin_lock(&smc_ib_devices.lock);
+       mutex_lock(&smc_ib_devices.mutex);
        list_for_each_entry(ibdev, &smc_ib_devices.list, list) {
                if (!strncmp(ibdev->ibdev->name, ib_name,
                             sizeof(ibdev->ibdev->name)) ||
@@ -311,7 +312,7 @@ static struct smc_ib_device *smc_pnet_find_ib(char *ib_name)
        }
        ibdev = NULL;
 out:
-       spin_unlock(&smc_ib_devices.lock);
+       mutex_unlock(&smc_ib_devices.mutex);
        return ibdev;
 }
 
@@ -320,7 +321,7 @@ static struct smcd_dev *smc_pnet_find_smcd(char *smcd_name)
 {
        struct smcd_dev *smcd_dev;
 
-       spin_lock(&smcd_dev_list.lock);
+       mutex_lock(&smcd_dev_list.mutex);
        list_for_each_entry(smcd_dev, &smcd_dev_list.list, list) {
                if (!strncmp(dev_name(&smcd_dev->dev), smcd_name,
                             IB_DEVICE_NAME_MAX - 1))
@@ -328,7 +329,7 @@ static struct smcd_dev *smc_pnet_find_smcd(char *smcd_name)
        }
        smcd_dev = NULL;
 out:
-       spin_unlock(&smcd_dev_list.lock);
+       mutex_unlock(&smcd_dev_list.mutex);
        return smcd_dev;
 }
 
@@ -825,7 +826,7 @@ static void _smc_pnet_find_roce_by_pnetid(u8 *pnet_id,
        int i;
 
        ini->ib_dev = NULL;
-       spin_lock(&smc_ib_devices.lock);
+       mutex_lock(&smc_ib_devices.mutex);
        list_for_each_entry(ibdev, &smc_ib_devices.list, list) {
                if (ibdev == known_dev)
                        continue;
@@ -844,7 +845,7 @@ static void _smc_pnet_find_roce_by_pnetid(u8 *pnet_id,
                }
        }
 out:
-       spin_unlock(&smc_ib_devices.lock);
+       mutex_unlock(&smc_ib_devices.mutex);
 }
 
 /* find alternate roce device with same pnet_id and vlan_id */
@@ -863,7 +864,7 @@ static void smc_pnet_find_rdma_dev(struct net_device *netdev,
 {
        struct smc_ib_device *ibdev;
 
-       spin_lock(&smc_ib_devices.lock);
+       mutex_lock(&smc_ib_devices.mutex);
        list_for_each_entry(ibdev, &smc_ib_devices.list, list) {
                struct net_device *ndev;
                int i;
@@ -888,7 +889,7 @@ static void smc_pnet_find_rdma_dev(struct net_device *netdev,
                        }
                }
        }
-       spin_unlock(&smc_ib_devices.lock);
+       mutex_unlock(&smc_ib_devices.mutex);
 }
 
 /* Determine the corresponding IB device port based on the hardware PNETID.
@@ -924,7 +925,7 @@ static void smc_pnet_find_ism_by_pnetid(struct net_device *ndev,
            smc_pnet_find_ndev_pnetid_by_table(ndev, ndev_pnetid))
                return; /* pnetid could not be determined */
 
-       spin_lock(&smcd_dev_list.lock);
+       mutex_lock(&smcd_dev_list.mutex);
        list_for_each_entry(ismdev, &smcd_dev_list.list, list) {
                if (smc_pnet_match(ismdev->pnetid, ndev_pnetid) &&
                    !ismdev->going_away) {
@@ -932,7 +933,7 @@ static void smc_pnet_find_ism_by_pnetid(struct net_device *ndev,
                        break;
                }
        }
-       spin_unlock(&smcd_dev_list.lock);
+       mutex_unlock(&smcd_dev_list.mutex);
 }
 
 /* PNET table analysis for a given sock:
index 7239ba9..1e23cdd 100644 (file)
@@ -169,6 +169,8 @@ void smc_wr_tx_cq_handler(struct ib_cq *ib_cq, void *cq_context)
 static inline int smc_wr_tx_get_free_slot_index(struct smc_link *link, u32 *idx)
 {
        *idx = link->wr_tx_cnt;
+       if (!smc_link_usable(link))
+               return -ENOLINK;
        for_each_clear_bit(*idx, link->wr_tx_mask, link->wr_tx_cnt) {
                if (!test_and_set_bit(*idx, link->wr_tx_mask))
                        return 0;
@@ -560,15 +562,15 @@ void smc_wr_free_link(struct smc_link *lnk)
 {
        struct ib_device *ibdev;
 
+       if (!lnk->smcibdev)
+               return;
+       ibdev = lnk->smcibdev->ibdev;
+
        if (smc_wr_tx_wait_no_pending_sends(lnk))
                memset(lnk->wr_tx_mask, 0,
                       BITS_TO_LONGS(SMC_WR_BUF_CNT) *
                                                sizeof(*lnk->wr_tx_mask));
 
-       if (!lnk->smcibdev)
-               return;
-       ibdev = lnk->smcibdev->ibdev;
-
        if (lnk->wr_rx_dma_addr) {
                ib_dma_unmap_single(ibdev, lnk->wr_rx_dma_addr,
                                    SMC_WR_BUF_SIZE * lnk->wr_rx_cnt,
index 39e14d5..e9d0953 100644 (file)
@@ -1317,6 +1317,7 @@ rpc_gssd_dummy_populate(struct dentry *root, struct rpc_pipe *pipe_data)
        q.len = strlen(gssd_dummy_clnt_dir[0].name);
        clnt_dentry = d_hash_and_lookup(gssd_dentry, &q);
        if (!clnt_dentry) {
+               __rpc_depopulate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1);
                pipe_dentry = ERR_PTR(-ENOENT);
                goto out;
        }
index 5c4ec93..c537272 100644 (file)
@@ -44,6 +44,7 @@
 #include <net/tcp.h>
 #include <net/tcp_states.h>
 #include <linux/uaccess.h>
+#include <linux/highmem.h>
 #include <asm/ioctls.h>
 
 #include <linux/sunrpc/types.h>
index 6f7d82f..be11d67 100644 (file)
@@ -1118,6 +1118,7 @@ xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf,
                base = 0;
        } else {
                base -= buf->head[0].iov_len;
+               subbuf->head[0].iov_base = buf->head[0].iov_base;
                subbuf->head[0].iov_len = 0;
        }
 
@@ -1130,6 +1131,8 @@ xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf,
                base = 0;
        } else {
                base -= buf->page_len;
+               subbuf->pages = buf->pages;
+               subbuf->page_base = 0;
                subbuf->page_len = 0;
        }
 
@@ -1141,6 +1144,7 @@ xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf,
                base = 0;
        } else {
                base -= buf->tail[0].iov_len;
+               subbuf->tail[0].iov_base = buf->tail[0].iov_base;
                subbuf->tail[0].iov_len = 0;
        }
 
index ef99788..b647562 100644 (file)
@@ -367,7 +367,7 @@ static void frwr_wc_fastreg(struct ib_cq *cq, struct ib_wc *wc)
        trace_xprtrdma_wc_fastreg(wc, frwr);
        /* The MR will get recycled when the associated req is retransmitted */
 
-       rpcrdma_flush_disconnect(cq, wc);
+       rpcrdma_flush_disconnect(cq->cq_context, wc);
 }
 
 /**
@@ -452,7 +452,7 @@ static void frwr_wc_localinv(struct ib_cq *cq, struct ib_wc *wc)
        trace_xprtrdma_wc_li(wc, frwr);
        __frwr_release_mr(wc, mr);
 
-       rpcrdma_flush_disconnect(cq, wc);
+       rpcrdma_flush_disconnect(cq->cq_context, wc);
 }
 
 /**
@@ -474,7 +474,7 @@ static void frwr_wc_localinv_wake(struct ib_cq *cq, struct ib_wc *wc)
        __frwr_release_mr(wc, mr);
        complete(&frwr->fr_linv_done);
 
-       rpcrdma_flush_disconnect(cq, wc);
+       rpcrdma_flush_disconnect(cq->cq_context, wc);
 }
 
 /**
@@ -582,7 +582,7 @@ static void frwr_wc_localinv_done(struct ib_cq *cq, struct ib_wc *wc)
        smp_rmb();
        rpcrdma_complete_rqst(rep);
 
-       rpcrdma_flush_disconnect(cq, wc);
+       rpcrdma_flush_disconnect(cq->cq_context, wc);
 }
 
 /**
index 2081c8f..453bacc 100644 (file)
@@ -71,7 +71,7 @@ static unsigned int rpcrdma_max_call_header_size(unsigned int maxsegs)
        size = RPCRDMA_HDRLEN_MIN;
 
        /* Maximum Read list size */
-       size = maxsegs * rpcrdma_readchunk_maxsz * sizeof(__be32);
+       size += maxsegs * rpcrdma_readchunk_maxsz * sizeof(__be32);
 
        /* Minimal Read chunk size */
        size += sizeof(__be32); /* segment count */
@@ -94,7 +94,7 @@ static unsigned int rpcrdma_max_reply_header_size(unsigned int maxsegs)
        size = RPCRDMA_HDRLEN_MIN;
 
        /* Maximum Write list size */
-       size = sizeof(__be32);          /* segment count */
+       size += sizeof(__be32);         /* segment count */
        size += maxsegs * rpcrdma_segment_maxsz * sizeof(__be32);
        size += sizeof(__be32); /* list discriminator */
 
@@ -1349,8 +1349,7 @@ rpcrdma_decode_error(struct rpcrdma_xprt *r_xprt, struct rpcrdma_rep *rep,
                        be32_to_cpup(p), be32_to_cpu(rep->rr_xid));
        }
 
-       r_xprt->rx_stats.bad_reply_count++;
-       return -EREMOTEIO;
+       return -EIO;
 }
 
 /* Perform XID lookup, reconstruction of the RPC reply, and
@@ -1387,13 +1386,11 @@ out:
        spin_unlock(&xprt->queue_lock);
        return;
 
-/* If the incoming reply terminated a pending RPC, the next
- * RPC call will post a replacement receive buffer as it is
- * being marshaled.
- */
 out_badheader:
        trace_xprtrdma_reply_hdr(rep);
        r_xprt->rx_stats.bad_reply_count++;
+       rqst->rq_task->tk_status = status;
+       status = 0;
        goto out;
 }
 
index 0c4af7f..053c8ab 100644 (file)
@@ -242,13 +242,18 @@ xprt_rdma_connect_worker(struct work_struct *work)
 
        rc = rpcrdma_xprt_connect(r_xprt);
        xprt_clear_connecting(xprt);
-       if (r_xprt->rx_ep && r_xprt->rx_ep->re_connect_status > 0) {
+       if (!rc) {
                xprt->connect_cookie++;
                xprt->stat.connect_count++;
                xprt->stat.connect_time += (long)jiffies -
                                           xprt->stat.connect_start;
                xprt_set_connected(xprt);
                rc = -EAGAIN;
+       } else {
+               /* Force a call to xprt_rdma_close to clean up */
+               spin_lock(&xprt->transport_lock);
+               set_bit(XPRT_CLOSE_WAIT, &xprt->state);
+               spin_unlock(&xprt->transport_lock);
        }
        xprt_wake_pending_tasks(xprt, rc);
 }
index 2ae3483..75c6467 100644 (file)
@@ -84,7 +84,8 @@ static void rpcrdma_rep_destroy(struct rpcrdma_rep *rep);
 static void rpcrdma_reps_unmap(struct rpcrdma_xprt *r_xprt);
 static void rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt);
 static void rpcrdma_mrs_destroy(struct rpcrdma_xprt *r_xprt);
-static int rpcrdma_ep_destroy(struct rpcrdma_ep *ep);
+static void rpcrdma_ep_get(struct rpcrdma_ep *ep);
+static int rpcrdma_ep_put(struct rpcrdma_ep *ep);
 static struct rpcrdma_regbuf *
 rpcrdma_regbuf_alloc(size_t size, enum dma_data_direction direction,
                     gfp_t flags);
@@ -97,7 +98,8 @@ static void rpcrdma_regbuf_free(struct rpcrdma_regbuf *rb);
  */
 static void rpcrdma_xprt_drain(struct rpcrdma_xprt *r_xprt)
 {
-       struct rdma_cm_id *id = r_xprt->rx_ep->re_id;
+       struct rpcrdma_ep *ep = r_xprt->rx_ep;
+       struct rdma_cm_id *id = ep->re_id;
 
        /* Flush Receives, then wait for deferred Reply work
         * to complete.
@@ -108,6 +110,8 @@ static void rpcrdma_xprt_drain(struct rpcrdma_xprt *r_xprt)
         * local invalidations.
         */
        ib_drain_sq(id->qp);
+
+       rpcrdma_ep_put(ep);
 }
 
 /**
@@ -126,23 +130,27 @@ static void rpcrdma_qp_event_handler(struct ib_event *event, void *context)
        trace_xprtrdma_qp_event(ep, event);
 }
 
+/* Ensure xprt_force_disconnect() is invoked exactly once when a
+ * connection is closed or lost. (The important thing is it needs
+ * to be invoked "at least" once).
+ */
+static void rpcrdma_force_disconnect(struct rpcrdma_ep *ep)
+{
+       if (atomic_add_unless(&ep->re_force_disconnect, 1, 1))
+               xprt_force_disconnect(ep->re_xprt);
+}
+
 /**
  * rpcrdma_flush_disconnect - Disconnect on flushed completion
- * @cq: completion queue
+ * @r_xprt: transport to disconnect
  * @wc: work completion entry
  *
  * Must be called in process context.
  */
-void rpcrdma_flush_disconnect(struct ib_cq *cq, struct ib_wc *wc)
+void rpcrdma_flush_disconnect(struct rpcrdma_xprt *r_xprt, struct ib_wc *wc)
 {
-       struct rpcrdma_xprt *r_xprt = cq->cq_context;
-       struct rpc_xprt *xprt = &r_xprt->rx_xprt;
-
-       if (wc->status != IB_WC_SUCCESS &&
-           r_xprt->rx_ep->re_connect_status == 1) {
-               r_xprt->rx_ep->re_connect_status = -ECONNABORTED;
-               xprt_force_disconnect(xprt);
-       }
+       if (wc->status != IB_WC_SUCCESS)
+               rpcrdma_force_disconnect(r_xprt->rx_ep);
 }
 
 /**
@@ -156,11 +164,12 @@ static void rpcrdma_wc_send(struct ib_cq *cq, struct ib_wc *wc)
        struct ib_cqe *cqe = wc->wr_cqe;
        struct rpcrdma_sendctx *sc =
                container_of(cqe, struct rpcrdma_sendctx, sc_cqe);
+       struct rpcrdma_xprt *r_xprt = cq->cq_context;
 
        /* WARNING: Only wr_cqe and status are reliable at this point */
        trace_xprtrdma_wc_send(sc, wc);
-       rpcrdma_sendctx_put_locked((struct rpcrdma_xprt *)cq->cq_context, sc);
-       rpcrdma_flush_disconnect(cq, wc);
+       rpcrdma_sendctx_put_locked(r_xprt, sc);
+       rpcrdma_flush_disconnect(r_xprt, wc);
 }
 
 /**
@@ -195,7 +204,7 @@ static void rpcrdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
        return;
 
 out_flushed:
-       rpcrdma_flush_disconnect(cq, wc);
+       rpcrdma_flush_disconnect(r_xprt, wc);
        rpcrdma_rep_destroy(rep);
 }
 
@@ -239,7 +248,6 @@ rpcrdma_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
 {
        struct sockaddr *sap = (struct sockaddr *)&id->route.addr.dst_addr;
        struct rpcrdma_ep *ep = id->context;
-       struct rpc_xprt *xprt = ep->re_xprt;
 
        might_sleep();
 
@@ -263,10 +271,9 @@ rpcrdma_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
                /* fall through */
        case RDMA_CM_EVENT_ADDR_CHANGE:
                ep->re_connect_status = -ENODEV;
-               xprt_force_disconnect(xprt);
                goto disconnected;
        case RDMA_CM_EVENT_ESTABLISHED:
-               kref_get(&ep->re_kref);
+               rpcrdma_ep_get(ep);
                ep->re_connect_status = 1;
                rpcrdma_update_cm_private(ep, &event->param.conn);
                trace_xprtrdma_inline_thresh(ep);
@@ -274,22 +281,24 @@ rpcrdma_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
                break;
        case RDMA_CM_EVENT_CONNECT_ERROR:
                ep->re_connect_status = -ENOTCONN;
-               goto disconnected;
+               goto wake_connect_worker;
        case RDMA_CM_EVENT_UNREACHABLE:
                ep->re_connect_status = -ENETUNREACH;
-               goto disconnected;
+               goto wake_connect_worker;
        case RDMA_CM_EVENT_REJECTED:
                dprintk("rpcrdma: connection to %pISpc rejected: %s\n",
                        sap, rdma_reject_msg(id, event->status));
                ep->re_connect_status = -ECONNREFUSED;
                if (event->status == IB_CM_REJ_STALE_CONN)
-                       ep->re_connect_status = -EAGAIN;
-               goto disconnected;
+                       ep->re_connect_status = -ENOTCONN;
+wake_connect_worker:
+               wake_up_all(&ep->re_connect_wait);
+               return 0;
        case RDMA_CM_EVENT_DISCONNECTED:
                ep->re_connect_status = -ECONNABORTED;
 disconnected:
-               xprt_force_disconnect(xprt);
-               return rpcrdma_ep_destroy(ep);
+               rpcrdma_force_disconnect(ep);
+               return rpcrdma_ep_put(ep);
        default:
                break;
        }
@@ -345,7 +354,7 @@ out:
        return ERR_PTR(rc);
 }
 
-static void rpcrdma_ep_put(struct kref *kref)
+static void rpcrdma_ep_destroy(struct kref *kref)
 {
        struct rpcrdma_ep *ep = container_of(kref, struct rpcrdma_ep, re_kref);
 
@@ -369,13 +378,18 @@ static void rpcrdma_ep_put(struct kref *kref)
        module_put(THIS_MODULE);
 }
 
+static noinline void rpcrdma_ep_get(struct rpcrdma_ep *ep)
+{
+       kref_get(&ep->re_kref);
+}
+
 /* Returns:
  *     %0 if @ep still has a positive kref count, or
  *     %1 if @ep was destroyed successfully.
  */
-static int rpcrdma_ep_destroy(struct rpcrdma_ep *ep)
+static noinline int rpcrdma_ep_put(struct rpcrdma_ep *ep)
 {
-       return kref_put(&ep->re_kref, rpcrdma_ep_put);
+       return kref_put(&ep->re_kref, rpcrdma_ep_destroy);
 }
 
 static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
@@ -388,14 +402,14 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
 
        ep = kzalloc(sizeof(*ep), GFP_NOFS);
        if (!ep)
-               return -EAGAIN;
+               return -ENOTCONN;
        ep->re_xprt = &r_xprt->rx_xprt;
        kref_init(&ep->re_kref);
 
        id = rpcrdma_create_id(r_xprt, ep);
        if (IS_ERR(id)) {
-               rc = PTR_ERR(id);
-               goto out_free;
+               kfree(ep);
+               return PTR_ERR(id);
        }
        __module_get(THIS_MODULE);
        device = id->device;
@@ -492,11 +506,8 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
        return 0;
 
 out_destroy:
-       rpcrdma_ep_destroy(ep);
+       rpcrdma_ep_put(ep);
        rdma_destroy_id(id);
-out_free:
-       kfree(ep);
-       r_xprt->rx_ep = NULL;
        return rc;
 }
 
@@ -512,22 +523,19 @@ int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt)
        struct rpcrdma_ep *ep;
        int rc;
 
-retry:
-       rpcrdma_xprt_disconnect(r_xprt);
        rc = rpcrdma_ep_create(r_xprt);
        if (rc)
                return rc;
        ep = r_xprt->rx_ep;
 
-       ep->re_connect_status = 0;
        xprt_clear_connected(xprt);
-
        rpcrdma_reset_cwnd(r_xprt);
-       rpcrdma_post_recvs(r_xprt, true);
 
-       rc = rpcrdma_sendctxs_create(r_xprt);
-       if (rc)
-               goto out;
+       /* Bump the ep's reference count while there are
+        * outstanding Receives.
+        */
+       rpcrdma_ep_get(ep);
+       rpcrdma_post_recvs(r_xprt, true);
 
        rc = rdma_connect(ep->re_id, &ep->re_remote_cma);
        if (rc)
@@ -538,22 +546,24 @@ retry:
        wait_event_interruptible(ep->re_connect_wait,
                                 ep->re_connect_status != 0);
        if (ep->re_connect_status <= 0) {
-               if (ep->re_connect_status == -EAGAIN)
-                       goto retry;
                rc = ep->re_connect_status;
                goto out;
        }
 
+       rc = rpcrdma_sendctxs_create(r_xprt);
+       if (rc) {
+               rc = -ENOTCONN;
+               goto out;
+       }
+
        rc = rpcrdma_reqs_setup(r_xprt);
        if (rc) {
-               rpcrdma_xprt_disconnect(r_xprt);
+               rc = -ENOTCONN;
                goto out;
        }
        rpcrdma_mrs_create(r_xprt);
 
 out:
-       if (rc)
-               ep->re_connect_status = rc;
        trace_xprtrdma_connect(r_xprt, rc);
        return rc;
 }
@@ -587,7 +597,7 @@ void rpcrdma_xprt_disconnect(struct rpcrdma_xprt *r_xprt)
        rpcrdma_mrs_destroy(r_xprt);
        rpcrdma_sendctxs_destroy(r_xprt);
 
-       if (rpcrdma_ep_destroy(ep))
+       if (rpcrdma_ep_put(ep))
                rdma_destroy_id(id);
 
        r_xprt->rx_ep = NULL;
index 0a16fdb..43974ef 100644 (file)
@@ -82,6 +82,7 @@ struct rpcrdma_ep {
        unsigned int            re_max_inline_recv;
        int                     re_async_rc;
        int                     re_connect_status;
+       atomic_t                re_force_disconnect;
        struct ib_qp_init_attr  re_attr;
        wait_queue_head_t       re_connect_wait;
        struct rpc_xprt         *re_xprt;
@@ -446,7 +447,7 @@ extern unsigned int xprt_rdma_memreg_strategy;
 /*
  * Endpoint calls - xprtrdma/verbs.c
  */
-void rpcrdma_flush_disconnect(struct ib_cq *cq, struct ib_wc *wc);
+void rpcrdma_flush_disconnect(struct rpcrdma_xprt *r_xprt, struct ib_wc *wc);
 int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt);
 void rpcrdma_xprt_disconnect(struct rpcrdma_xprt *r_xprt);
 
index ee3b8d0..d40f8e5 100644 (file)
@@ -827,11 +827,11 @@ int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq)
                state |= l->bc_rcvlink->rcv_unacked;
                state |= l->rcv_unacked;
                state |= !skb_queue_empty(&l->transmq);
-               state |= !skb_queue_empty(&l->deferdq);
                probe = mstate->probing;
                probe |= l->silent_intv_cnt;
                if (probe || mstate->monitoring)
                        l->silent_intv_cnt++;
+               probe |= !skb_queue_empty(&l->deferdq);
                if (l->snd_nxt == l->checkpoint) {
                        tipc_link_update_cwin(l, 0, 0);
                        probe = true;
@@ -921,6 +921,21 @@ static void link_prepare_wakeup(struct tipc_link *l)
 
 }
 
+/**
+ * tipc_link_set_skb_retransmit_time - set the time at which retransmission of
+ *                                     the given skb should be next attempted
+ * @skb: skb to set a future retransmission time for
+ * @l: link the skb will be transmitted on
+ */
+static void tipc_link_set_skb_retransmit_time(struct sk_buff *skb,
+                                             struct tipc_link *l)
+{
+       if (link_is_bc_sndlink(l))
+               TIPC_SKB_CB(skb)->nxt_retr = TIPC_BC_RETR_LIM;
+       else
+               TIPC_SKB_CB(skb)->nxt_retr = TIPC_UC_RETR_TIME;
+}
+
 void tipc_link_reset(struct tipc_link *l)
 {
        struct sk_buff_head list;
@@ -1036,9 +1051,7 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
                                return -ENOBUFS;
                        }
                        __skb_queue_tail(transmq, skb);
-                       /* next retransmit attempt */
-                       if (link_is_bc_sndlink(l))
-                               TIPC_SKB_CB(skb)->nxt_retr = TIPC_BC_RETR_LIM;
+                       tipc_link_set_skb_retransmit_time(skb, l);
                        __skb_queue_tail(xmitq, _skb);
                        TIPC_SKB_CB(skb)->ackers = l->ackers;
                        l->rcv_unacked = 0;
@@ -1139,9 +1152,7 @@ static void tipc_link_advance_backlog(struct tipc_link *l,
                if (unlikely(skb == l->backlog[imp].target_bskb))
                        l->backlog[imp].target_bskb = NULL;
                __skb_queue_tail(&l->transmq, skb);
-               /* next retransmit attempt */
-               if (link_is_bc_sndlink(l))
-                       TIPC_SKB_CB(skb)->nxt_retr = TIPC_BC_RETR_LIM;
+               tipc_link_set_skb_retransmit_time(skb, l);
 
                __skb_queue_tail(xmitq, _skb);
                TIPC_SKB_CB(skb)->ackers = l->ackers;
@@ -1584,8 +1595,7 @@ release:
                        /* retransmit skb if unrestricted*/
                        if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr))
                                continue;
-                       TIPC_SKB_CB(skb)->nxt_retr = (is_uc) ?
-                                       TIPC_UC_RETR_TIME : TIPC_BC_RETR_LIM;
+                       tipc_link_set_skb_retransmit_time(skb, l);
                        _skb = pskb_copy(skb, GFP_ATOMIC);
                        if (!_skb)
                                continue;
index dfbaf6b..2700a63 100644 (file)
@@ -22,7 +22,7 @@
 #include <net/af_vsock.h>
 
 static struct workqueue_struct *virtio_vsock_workqueue;
-static struct virtio_vsock *the_virtio_vsock;
+static struct virtio_vsock __rcu *the_virtio_vsock;
 static DEFINE_MUTEX(the_virtio_vsock_mutex); /* protects the_virtio_vsock */
 
 struct virtio_vsock {
index 263ae39..0e07fb8 100644 (file)
@@ -5016,7 +5016,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
                err = nl80211_parse_he_obss_pd(
                                        info->attrs[NL80211_ATTR_HE_OBSS_PD],
                                        &params.he_obss_pd);
-               goto out;
+               if (err)
+                       goto out;
        }
 
        if (info->attrs[NL80211_ATTR_HE_BSS_COLOR]) {
@@ -5024,7 +5025,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
                                        info->attrs[NL80211_ATTR_HE_BSS_COLOR],
                                        &params.he_bss_color);
                if (err)
-                       return err;
+                       goto out;
        }
 
        nl80211_calculate_ap_params(&params);
index 540ed75..08b8066 100644 (file)
@@ -2,9 +2,6 @@
 
 #include <net/xsk_buff_pool.h>
 #include <net/xdp_sock.h>
-#include <linux/dma-direct.h>
-#include <linux/dma-noncoherent.h>
-#include <linux/swiotlb.h>
 
 #include "xsk_queue.h"
 
@@ -55,7 +52,6 @@ struct xsk_buff_pool *xp_create(struct page **pages, u32 nr_pages, u32 chunks,
        pool->free_heads_cnt = chunks;
        pool->headroom = headroom;
        pool->chunk_size = chunk_size;
-       pool->cheap_dma = true;
        pool->unaligned = unaligned;
        pool->frame_len = chunk_size - headroom - XDP_PACKET_HEADROOM;
        INIT_LIST_HEAD(&pool->free_list);
@@ -125,48 +121,6 @@ static void xp_check_dma_contiguity(struct xsk_buff_pool *pool)
        }
 }
 
-static bool __maybe_unused xp_check_swiotlb_dma(struct xsk_buff_pool *pool)
-{
-#if defined(CONFIG_SWIOTLB)
-       phys_addr_t paddr;
-       u32 i;
-
-       for (i = 0; i < pool->dma_pages_cnt; i++) {
-               paddr = dma_to_phys(pool->dev, pool->dma_pages[i]);
-               if (is_swiotlb_buffer(paddr))
-                       return false;
-       }
-#endif
-       return true;
-}
-
-static bool xp_check_cheap_dma(struct xsk_buff_pool *pool)
-{
-#if defined(CONFIG_HAS_DMA)
-       const struct dma_map_ops *ops = get_dma_ops(pool->dev);
-
-       if (ops) {
-               return !ops->sync_single_for_cpu &&
-                       !ops->sync_single_for_device;
-       }
-
-       if (!dma_is_direct(ops))
-               return false;
-
-       if (!xp_check_swiotlb_dma(pool))
-               return false;
-
-       if (!dev_is_dma_coherent(pool->dev)) {
-#if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU) ||               \
-       defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL) ||        \
-       defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE)
-               return false;
-#endif
-       }
-#endif
-       return true;
-}
-
 int xp_dma_map(struct xsk_buff_pool *pool, struct device *dev,
               unsigned long attrs, struct page **pages, u32 nr_pages)
 {
@@ -180,6 +134,7 @@ int xp_dma_map(struct xsk_buff_pool *pool, struct device *dev,
 
        pool->dev = dev;
        pool->dma_pages_cnt = nr_pages;
+       pool->dma_need_sync = false;
 
        for (i = 0; i < pool->dma_pages_cnt; i++) {
                dma = dma_map_page_attrs(dev, pages[i], 0, PAGE_SIZE,
@@ -188,14 +143,13 @@ int xp_dma_map(struct xsk_buff_pool *pool, struct device *dev,
                        xp_dma_unmap(pool, attrs);
                        return -ENOMEM;
                }
+               if (dma_need_sync(dev, dma))
+                       pool->dma_need_sync = true;
                pool->dma_pages[i] = dma;
        }
 
        if (pool->unaligned)
                xp_check_dma_contiguity(pool);
-
-       pool->dev = dev;
-       pool->cheap_dma = xp_check_cheap_dma(pool);
        return 0;
 }
 EXPORT_SYMBOL(xp_dma_map);
@@ -280,7 +234,7 @@ struct xdp_buff *xp_alloc(struct xsk_buff_pool *pool)
        xskb->xdp.data = xskb->xdp.data_hard_start + XDP_PACKET_HEADROOM;
        xskb->xdp.data_meta = xskb->xdp.data;
 
-       if (!pool->cheap_dma) {
+       if (pool->dma_need_sync) {
                dma_sync_single_range_for_device(pool->dev, xskb->dma, 0,
                                                 pool->frame_len,
                                                 DMA_BIDIRECTIONAL);
index b5d4a1e..5b9a5ab 100644 (file)
@@ -67,6 +67,30 @@ config XFRM_STATISTICS
 
          If unsure, say N.
 
+# This option selects XFRM_ALGO along with the AH authentication algorithms that
+# RFC 8221 lists as MUST be implemented.
+config XFRM_AH
+       tristate
+       select XFRM_ALGO
+       select CRYPTO
+       select CRYPTO_HMAC
+       select CRYPTO_SHA256
+
+# This option selects XFRM_ALGO along with the ESP encryption and authentication
+# algorithms that RFC 8221 lists as MUST be implemented.
+config XFRM_ESP
+       tristate
+       select XFRM_ALGO
+       select CRYPTO
+       select CRYPTO_AES
+       select CRYPTO_AUTHENC
+       select CRYPTO_CBC
+       select CRYPTO_ECHAINIV
+       select CRYPTO_GCM
+       select CRYPTO_HMAC
+       select CRYPTO_SEQIV
+       select CRYPTO_SHA256
+
 config XFRM_IPCOMP
        tristate
        select XFRM_ALGO
index f50d1f9..626096b 100644 (file)
@@ -108,7 +108,7 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
        struct xfrm_offload *xo = xfrm_offload(skb);
        struct sec_path *sp;
 
-       if (!xo)
+       if (!xo || (xo->flags & XFRM_XMIT))
                return skb;
 
        if (!(features & NETIF_F_HW_ESP))
@@ -129,6 +129,8 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
                return skb;
        }
 
+       xo->flags |= XFRM_XMIT;
+
        if (skb_is_gso(skb)) {
                struct net_device *dev = skb->dev;
 
index c407ecb..b615729 100644 (file)
@@ -37,6 +37,7 @@
 #include <net/ip.h>
 #include <net/ipv6.h>
 #include <net/ip6_route.h>
+#include <net/ip_tunnels.h>
 #include <net/addrconf.h>
 #include <net/xfrm.h>
 #include <net/net_namespace.h>
@@ -581,6 +582,7 @@ static const struct net_device_ops xfrmi_netdev_ops = {
 static void xfrmi_dev_setup(struct net_device *dev)
 {
        dev->netdev_ops         = &xfrmi_netdev_ops;
+       dev->header_ops         = &ip_tunnel_header_ops;
        dev->type               = ARPHRD_NONE;
        dev->mtu                = ETH_DATA_LEN;
        dev->min_mtu            = ETH_MIN_MTU;
index e4c23f6..a7ab193 100644 (file)
@@ -574,16 +574,12 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb)
        switch (x->outer_mode.family) {
        case AF_INET:
                memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
-#ifdef CONFIG_NETFILTER
                IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
-#endif
                break;
        case AF_INET6:
                memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
 
-#ifdef CONFIG_NETFILTER
                IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
-#endif
                break;
        }
 
index f3ac549..0ed6e4d 100644 (file)
@@ -211,7 +211,7 @@ config SAMPLE_WATCHDOG
 
 config SAMPLE_WATCH_QUEUE
        bool "Build example /dev/watch_queue notification consumer"
-       depends on HEADERS_INSTALL
+       depends on CC_CAN_LINK && HEADERS_INSTALL
        help
          Build example userspace program to use the new mount_notify(),
          sb_notify() syscalls and the KEYCTL_WATCH_KEY keyctl() function.
index dd558cb..ef53b93 100644 (file)
@@ -509,11 +509,8 @@ static void *alloc_rec_per_cpu(int record_size)
 {
        unsigned int nr_cpus = bpf_num_possible_cpus();
        void *array;
-       size_t size;
 
-       size = record_size * nr_cpus;
-       array = malloc(size);
-       memset(array, 0, size);
+       array = calloc(nr_cpus, record_size);
        if (!array) {
                fprintf(stderr, "Mem alloc error (nr_cpus:%u)\n", nr_cpus);
                exit(EXIT_FAIL_MEM);
@@ -528,8 +525,7 @@ static struct stats_record *alloc_stats_record(void)
        int i;
 
        /* Alloc main stats_record structure */
-       rec = malloc(sizeof(*rec));
-       memset(rec, 0, sizeof(*rec));
+       rec = calloc(1, sizeof(*rec));
        if (!rec) {
                fprintf(stderr, "Mem alloc error\n");
                exit(EXIT_FAIL_MEM);
index f346816..f4e755e 100644 (file)
@@ -207,11 +207,8 @@ static struct datarec *alloc_record_per_cpu(void)
 {
        unsigned int nr_cpus = bpf_num_possible_cpus();
        struct datarec *array;
-       size_t size;
 
-       size = sizeof(struct datarec) * nr_cpus;
-       array = malloc(size);
-       memset(array, 0, size);
+       array = calloc(nr_cpus, sizeof(struct datarec));
        if (!array) {
                fprintf(stderr, "Mem alloc error (nr_cpus:%u)\n", nr_cpus);
                exit(EXIT_FAIL_MEM);
@@ -226,11 +223,11 @@ static struct stats_record *alloc_stats_record(void)
 
        size = sizeof(*rec) + n_cpus * sizeof(struct record);
        rec = malloc(size);
-       memset(rec, 0, size);
        if (!rec) {
                fprintf(stderr, "Mem alloc error\n");
                exit(EXIT_FAIL_MEM);
        }
+       memset(rec, 0, size);
        rec->rx_cnt.cpu    = alloc_record_per_cpu();
        rec->redir_err.cpu = alloc_record_per_cpu();
        rec->kthread.cpu   = alloc_record_per_cpu();
index 4fe4750..caa4e7f 100644 (file)
@@ -198,11 +198,8 @@ static struct datarec *alloc_record_per_cpu(void)
 {
        unsigned int nr_cpus = bpf_num_possible_cpus();
        struct datarec *array;
-       size_t size;
 
-       size = sizeof(struct datarec) * nr_cpus;
-       array = malloc(size);
-       memset(array, 0, size);
+       array = calloc(nr_cpus, sizeof(struct datarec));
        if (!array) {
                fprintf(stderr, "Mem alloc error (nr_cpus:%u)\n", nr_cpus);
                exit(EXIT_FAIL_MEM);
@@ -214,11 +211,8 @@ static struct record *alloc_record_per_rxq(void)
 {
        unsigned int nr_rxqs = bpf_map__def(rx_queue_index_map)->max_entries;
        struct record *array;
-       size_t size;
 
-       size = sizeof(struct record) * nr_rxqs;
-       array = malloc(size);
-       memset(array, 0, size);
+       array = calloc(nr_rxqs, sizeof(struct record));
        if (!array) {
                fprintf(stderr, "Mem alloc error (nr_rxqs:%u)\n", nr_rxqs);
                exit(EXIT_FAIL_MEM);
@@ -232,8 +226,7 @@ static struct stats_record *alloc_stats_record(void)
        struct stats_record *rec;
        int i;
 
-       rec = malloc(sizeof(*rec));
-       memset(rec, 0, sizeof(*rec));
+       rec = calloc(1, sizeof(struct stats_record));
        if (!rec) {
                fprintf(stderr, "Mem alloc error\n");
                exit(EXIT_FAIL_MEM);
index d523450..6aba02a 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/timer.h>
 #include <linux/err.h>
 #include <linux/jiffies.h>
+#include <linux/workqueue.h>
 
 /*
  * Any file that uses trace points, must include the header.
@@ -20,6 +21,16 @@ struct trace_array *tr;
 static void mytimer_handler(struct timer_list *unused);
 static struct task_struct *simple_tsk;
 
+static void trace_work_fn(struct work_struct *work)
+{
+       /*
+        * Disable tracing for event "sample_event".
+        */
+       trace_array_set_clr_event(tr, "sample-subsystem", "sample_event",
+                       false);
+}
+static DECLARE_WORK(trace_work, trace_work_fn);
+
 /*
  * mytimer: Timer setup to disable tracing for event "sample_event". This
  * timer is only for the purposes of the sample module to demonstrate access of
@@ -29,11 +40,7 @@ static DEFINE_TIMER(mytimer, mytimer_handler);
 
 static void mytimer_handler(struct timer_list *unused)
 {
-       /*
-        * Disable tracing for event "sample_event".
-        */
-       trace_array_set_clr_event(tr, "sample-subsystem", "sample_event",
-                       false);
+       schedule_work(&trace_work);
 }
 
 static void simple_thread_func(int count)
@@ -76,6 +83,7 @@ static int simple_thread(void *arg)
                simple_thread_func(count++);
 
        del_timer(&mytimer);
+       cancel_work_sync(&trace_work);
 
        /*
         * trace_array_put() decrements the reference counter associated with
@@ -107,8 +115,12 @@ static int __init sample_trace_array_init(void)
        trace_printk_init_buffers();
 
        simple_tsk = kthread_run(simple_thread, NULL, "sample-instance");
-       if (IS_ERR(simple_tsk))
+       if (IS_ERR(simple_tsk)) {
+               trace_array_put(tr);
+               trace_array_destroy(tr);
                return -1;
+       }
+
        return 0;
 }
 
index 3223448..ad3e560 100644 (file)
@@ -267,7 +267,7 @@ struct amt_host_if_msg_header {
 struct amt_host_if_resp_header {
        struct amt_host_if_msg_header header;
        uint32_t status;
-       unsigned char data[0];
+       unsigned char data[];
 } __attribute__((packed));
 
 const uuid_le MEI_IAMTHIF = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d,  \
index 76c577e..49c7a46 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/fcntl.h>
 #define statx foo
 #define statx_timestamp foo_timestamp
+struct statx;
+struct statx_timestamp;
 #include <sys/stat.h>
 #undef statx
 #undef statx_timestamp
index 8511fb6..792b22f 100644 (file)
@@ -1,7 +1,5 @@
-# List of programs to build
-hostprogs := watch_test
+# SPDX-License-Identifier: GPL-2.0-only
+userprogs := watch_test
+always-y := $(userprogs)
 
-# Tell kbuild to always build the programs
-always-y := $(hostprogs)
-
-HOSTCFLAGS_watch_test.o += -I$(objtree)/usr/include
+userccflags += -I usr/include
index 0c3dc98..9a15fbf 100644 (file)
@@ -86,20 +86,21 @@ cc-cross-prefix = $(firstword $(foreach c, $(1), \
                        $(if $(shell command -v -- $(c)gcc 2>/dev/null), $(c))))
 
 # output directory for tests below
-TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/)
+TMPOUT = $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_$$$$
 
 # try-run
 # Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)
 # Exit code chooses option. "$$TMP" serves as a temporary file and is
 # automatically cleaned up.
 try-run = $(shell set -e;              \
-       TMP="$(TMPOUT).$$$$.tmp";       \
-       TMPO="$(TMPOUT).$$$$.o";        \
+       TMP=$(TMPOUT)/tmp;              \
+       TMPO=$(TMPOUT)/tmp.o;           \
+       mkdir -p $(TMPOUT);             \
+       trap "rm -rf $(TMPOUT)" EXIT;   \
        if ($(1)) >/dev/null 2>&1;      \
        then echo "$(2)";               \
        else echo "$(3)";               \
-       fi;                             \
-       rm -f "$$TMP" "$$TMPO")
+       fi)
 
 # as-option
 # Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,)
index c264da2..a5fe72c 100644 (file)
@@ -25,18 +25,12 @@ failure = $(if-success,$(1),n,y)
 
 # $(cc-option,<flag>)
 # Return y if the compiler supports <flag>, n otherwise
-cc-option = $(success,$(CC) -Werror $(CLANG_FLAGS) $(1) -S -x c /dev/null -o /dev/null)
+cc-option = $(success,mkdir .tmp_$$$$; trap "rm -rf .tmp_$$$$" EXIT; $(CC) -Werror $(CLANG_FLAGS) $(1) -c -x c /dev/null -o .tmp_$$$$/tmp.o)
 
 # $(ld-option,<flag>)
 # Return y if the linker supports <flag>, n otherwise
 ld-option = $(success,$(LD) -v $(1))
 
-# $(as-option,<flag>)
-# /dev/zero is used as output instead of /dev/null as some assembler cribs when
-# both input and output are same. Also both of them have same write behaviour so
-# can be easily substituted.
-as-option = $(success, $(CC) $(CLANG_FLAGS) $(1) -c -x assembler /dev/null -o /dev/zero)
-
 # $(as-instr,<instr>)
 # Return y if the assembler supports <instr>, n otherwise
 as-instr = $(success,printf "%b\n" "$(1)" | $(CC) $(CLANG_FLAGS) -c -x assembler -o /dev/null -)
index 4aea7cf..62c2756 100644 (file)
@@ -35,6 +35,7 @@ KBUILD_CFLAGS += $(call cc-option, -Wstringop-truncation)
 # The following turn off the warnings enabled by -Wextra
 KBUILD_CFLAGS += -Wno-missing-field-initializers
 KBUILD_CFLAGS += -Wno-sign-compare
+KBUILD_CFLAGS += -Wno-type-limits
 
 KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN1
 
@@ -66,6 +67,7 @@ KBUILD_CFLAGS += -Wshadow
 KBUILD_CFLAGS += $(call cc-option, -Wlogical-op)
 KBUILD_CFLAGS += -Wmissing-field-initializers
 KBUILD_CFLAGS += -Wsign-compare
+KBUILD_CFLAGS += -Wtype-limits
 KBUILD_CFLAGS += $(call cc-option, -Wmaybe-uninitialized)
 KBUILD_CFLAGS += $(call cc-option, -Wunused-macros)
 
index 99ac59c..916b2f7 100644 (file)
@@ -212,6 +212,9 @@ $(foreach m, $(notdir $1), \
        $(addprefix $(obj)/, $(foreach s, $3, $($(m:%$(strip $2)=%$(s)))))))
 endef
 
+quiet_cmd_copy = COPY    $@
+      cmd_copy = cp $< $@
+
 # Shipped files
 # ===========================================================================
 
@@ -259,6 +262,7 @@ quiet_cmd_gzip = GZIP    $@
 # DTC
 # ---------------------------------------------------------------------------
 DTC ?= $(objtree)/scripts/dtc/dtc
+DTC_FLAGS += -Wno-interrupt_provider
 
 # Disable noisy checks by default
 ifeq ($(findstring 1,$(KBUILD_EXTRA_WARN)),)
@@ -274,7 +278,8 @@ endif
 
 ifneq ($(findstring 2,$(KBUILD_EXTRA_WARN)),)
 DTC_FLAGS += -Wnode_name_chars_strict \
-       -Wproperty_name_chars_strict
+       -Wproperty_name_chars_strict \
+       -Winterrupt_provider
 endif
 
 DTC_FLAGS += $(DTC_FLAGS_$(basetarget))
index 0fd1cf0..693dfa1 100755 (executable)
@@ -58,6 +58,21 @@ cat << EOF
 EOF
 }
 
+gen_proto_order_variant()
+{
+       local meta="$1"; shift
+       local pfx="$1"; shift
+       local name="$1"; shift
+       local sfx="$1"; shift
+       local order="$1"; shift
+       local arch="$1"
+       local atomic="$2"
+
+       local basename="${arch}${atomic}_${pfx}${name}${sfx}"
+
+       printf "#define arch_${basename}${order} ${basename}${order}\n"
+}
+
 #gen_proto_order_variants(meta, pfx, name, sfx, arch, atomic, int, args...)
 gen_proto_order_variants()
 {
@@ -72,6 +87,22 @@ gen_proto_order_variants()
 
        local template="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")"
 
+       if [ -z "$arch" ]; then
+               gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@"
+
+               if meta_has_acquire "${meta}"; then
+                       gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@"
+               fi
+               if meta_has_release "${meta}"; then
+                       gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@"
+               fi
+               if meta_has_relaxed "${meta}"; then
+                       gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_relaxed" "$@"
+               fi
+
+               echo ""
+       fi
+
        # If we don't have relaxed atomics, then we don't bother with ordering fallbacks
        # read_acquire and set_release need to be templated, though
        if ! meta_has_relaxed "${meta}"; then
index 13e5fba..0869def 100755 (executable)
@@ -27,7 +27,10 @@ parse_symbol() {
        elif [[ "${modcache[$module]+isset}" == "isset" ]]; then
                local objfile=${modcache[$module]}
        else
-               [[ $modpath == "" ]] && return
+               if [[ $modpath == "" ]]; then
+                       echo "WARNING! Modules path isn't set, but is needed to parse this symbol" >&2
+                       return
+               fi
                local objfile=$(find "$modpath" -name "${module//_/[-_]}.ko*" -print -quit)
                [[ $objfile == "" ]] && return
                modcache[$module]=$objfile
@@ -84,8 +87,8 @@ parse_symbol() {
                return
        fi
 
-       # Strip out the base of the path
-       code=${code#$basepath/}
+       # Strip out the base of the path on each line
+       code=$(while read -r line; do echo "${line#$basepath/}"; done <<< "$code")
 
        # In the case of inlines, move everything to same line
        code=${code//$'\n'/' '}
index 4b3c486..b7955db 100644 (file)
@@ -1022,6 +1022,9 @@ static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct no
 }
 WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells);
 
+#define I2C_OWN_SLAVE_ADDRESS  (1U << 30)
+#define I2C_TEN_BIT_ADDRESS    (1U << 31)
+
 static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
 {
        struct property *prop;
@@ -1044,6 +1047,8 @@ static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node
        }
 
        reg = fdt32_to_cpu(*cells);
+       /* Ignore I2C_OWN_SLAVE_ADDRESS */
+       reg &= ~I2C_OWN_SLAVE_ADDRESS;
        snprintf(unit_addr, sizeof(unit_addr), "%x", reg);
        if (!streq(unitname, unit_addr))
                FAIL(c, dti, node, "I2C bus unit address format error, expected \"%s\"",
@@ -1051,10 +1056,15 @@ static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node
 
        for (len = prop->val.len; len > 0; len -= 4) {
                reg = fdt32_to_cpu(*(cells++));
-               if (reg > 0x3ff)
+               /* Ignore I2C_OWN_SLAVE_ADDRESS */
+               reg &= ~I2C_OWN_SLAVE_ADDRESS;
+
+               if ((reg & I2C_TEN_BIT_ADDRESS) && ((reg & ~I2C_TEN_BIT_ADDRESS) > 0x3ff))
                        FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"",
                                  reg);
-
+               else if (reg > 0x7f)
+                       FAIL_PROP(c, dti, node, prop, "I2C address must be less than 7-bits, got \"0x%x\". Set I2C_TEN_BIT_ADDRESS for 10 bit addresses or fix the property",
+                                 reg);
        }
 }
 WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, &reg_format, &i2c_bus_bridge);
@@ -1547,6 +1557,28 @@ static bool node_is_interrupt_provider(struct node *node)
 
        return false;
 }
+
+static void check_interrupt_provider(struct check *c,
+                                    struct dt_info *dti,
+                                    struct node *node)
+{
+       struct property *prop;
+
+       if (!node_is_interrupt_provider(node))
+               return;
+
+       prop = get_property(node, "#interrupt-cells");
+       if (!prop)
+               FAIL(c, dti, node,
+                    "Missing #interrupt-cells in interrupt provider");
+
+       prop = get_property(node, "#address-cells");
+       if (!prop)
+               FAIL(c, dti, node,
+                    "Missing #address-cells in interrupt provider");
+}
+WARNING(interrupt_provider, check_interrupt_provider, NULL);
+
 static void check_interrupts_property(struct check *c,
                                      struct dt_info *dti,
                                      struct node *node)
@@ -1604,7 +1636,7 @@ static void check_interrupts_property(struct check *c,
 
        prop = get_property(irq_node, "#interrupt-cells");
        if (!prop) {
-               FAIL(c, dti, irq_node, "Missing #interrupt-cells in interrupt-parent");
+               /* We warn about that already in another test. */
                return;
        }
 
@@ -1828,6 +1860,7 @@ static struct check *check_table[] = {
        &deprecated_gpio_property,
        &gpios_property,
        &interrupts_property,
+       &interrupt_provider,
 
        &alias_paths,
 
index 6e74ece..a08f415 100644 (file)
@@ -51,6 +51,37 @@ extern int annotate;         /* annotate .dts with input source location */
 
 typedef uint32_t cell_t;
 
+static inline uint16_t dtb_ld16(const void *p)
+{
+       const uint8_t *bp = (const uint8_t *)p;
+
+       return ((uint16_t)bp[0] << 8)
+               | bp[1];
+}
+
+static inline uint32_t dtb_ld32(const void *p)
+{
+       const uint8_t *bp = (const uint8_t *)p;
+
+       return ((uint32_t)bp[0] << 24)
+               | ((uint32_t)bp[1] << 16)
+               | ((uint32_t)bp[2] << 8)
+               | bp[3];
+}
+
+static inline uint64_t dtb_ld64(const void *p)
+{
+       const uint8_t *bp = (const uint8_t *)p;
+
+       return ((uint64_t)bp[0] << 56)
+               | ((uint64_t)bp[1] << 48)
+               | ((uint64_t)bp[2] << 40)
+               | ((uint64_t)bp[3] << 32)
+               | ((uint64_t)bp[4] << 24)
+               | ((uint64_t)bp[5] << 16)
+               | ((uint64_t)bp[6] << 8)
+               | bp[7];
+}
 
 #define streq(a, b)    (strcmp((a), (b)) == 0)
 #define strstarts(s, prefix)   (strncmp((s), (prefix), strlen(prefix)) == 0)
index bd6977e..07f10d2 100644 (file)
@@ -156,7 +156,7 @@ static void asm_emit_data(void *e, struct data d)
                emit_offset_label(f, m->ref, m->offset);
 
        while ((d.len - off) >= sizeof(uint32_t)) {
-               asm_emit_cell(e, fdt32_to_cpu(*((fdt32_t *)(d.val+off))));
+               asm_emit_cell(e, dtb_ld32(d.val + off));
                off += sizeof(uint32_t);
        }
 
index 524b520..93e4a2b 100644 (file)
@@ -436,7 +436,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
                        return struct_size;
        }
 
-       if (can_assume(LIBFDT_ORDER) |
+       if (can_assume(LIBFDT_ORDER) ||
            !fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
                /* no further work necessary */
                err = fdt_move(fdt, buf, bufsize);
index 26759d5..94ce4bb 100644 (file)
@@ -32,7 +32,7 @@ static int fdt_sw_probe_(void *fdt)
 /* 'memrsv' state:     Initial state after fdt_create()
  *
  * Allowed functions:
- *     fdt_add_reservmap_entry()
+ *     fdt_add_reservemap_entry()
  *     fdt_finish_reservemap()         [moves to 'struct' state]
  */
 static int fdt_sw_probe_memrsv_(void *fdt)
index 36fadcd..fe49b5d 100644 (file)
@@ -9,6 +9,10 @@
 #include "libfdt_env.h"
 #include "fdt.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define FDT_FIRST_SUPPORTED_VERSION    0x02
 #define FDT_LAST_SUPPORTED_VERSION     0x11
 
@@ -2069,4 +2073,8 @@ int fdt_overlay_apply(void *fdt, void *fdto);
 
 const char *fdt_strerror(int errval);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* LIBFDT_H */
index c9d980c..061ba8c 100644 (file)
@@ -110,13 +110,13 @@ static void write_propval_int(FILE *f, const char *p, size_t len, size_t width)
                        fprintf(f, "%02"PRIx8, *(const uint8_t*)p);
                        break;
                case 2:
-                       fprintf(f, "0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p));
+                       fprintf(f, "0x%02"PRIx16, dtb_ld16(p));
                        break;
                case 4:
-                       fprintf(f, "0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p));
+                       fprintf(f, "0x%02"PRIx32, dtb_ld32(p));
                        break;
                case 8:
-                       fprintf(f, "0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p));
+                       fprintf(f, "0x%02"PRIx64, dtb_ld64(p));
                        break;
                }
                if (p + width < end)
@@ -183,7 +183,7 @@ static enum markertype guess_value_type(struct property *prop)
                        nnotcelllbl++;
        }
 
-       if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
+       if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= (len-nnul))
            && (nnotstringlbl == 0)) {
                return TYPE_STRING;
        } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
index 61dd711..0714799 100644 (file)
@@ -1 +1 @@
-#define DTC_VERSION "DTC 1.6.0-g87a656ae"
+#define DTC_VERSION "DTC 1.6.0-g9d7888cb"
index 5b6ea8e..4e93c12 100644 (file)
@@ -59,10 +59,10 @@ static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, ch
                        sprintf(buf, "0x%"PRIx8, *(uint8_t*)(data + off));
                        break;
                case 2:
-                       sprintf(buf, "0x%"PRIx16, fdt16_to_cpu(*(fdt16_t*)(data + off)));
+                       sprintf(buf, "0x%"PRIx16, dtb_ld16(data + off));
                        break;
                case 4:
-                       sprintf(buf, "0x%"PRIx32, fdt32_to_cpu(*(fdt32_t*)(data + off)));
+                       sprintf(buf, "0x%"PRIx32, dtb_ld32(data + off));
                        m = markers;
                        is_phandle = false;
                        for_each_marker_of_type(m, REF_PHANDLE) {
@@ -73,7 +73,7 @@ static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, ch
                        }
                        break;
                case 8:
-                       sprintf(buf, "0x%"PRIx64, fdt64_to_cpu(*(fdt64_t*)(data + off)));
+                       sprintf(buf, "0x%"PRIx64, dtb_ld64(data + off));
                        break;
                }
 
index ce0b99f..ae19fb0 100644 (file)
@@ -78,7 +78,7 @@ config GCC_PLUGIN_RANDSTRUCT
          source tree isn't cleaned after kernel installation).
 
          The seed used for compilation is located at
-         scripts/gcc-plgins/randomize_layout_seed.h.  It remains after
+         scripts/gcc-plugins/randomize_layout_seed.h.  It remains after
          a make clean to allow for external modules to be compiled with
          the existing seed and will be removed by a make mrproper or
          make distclean.
index be984aa..1be9763 100644 (file)
@@ -96,7 +96,7 @@ lx-symbols command."""
             return ""
         attrs = sect_attrs['attrs']
         section_name_to_address = {
-            attrs[n]['name'].string(): attrs[n]['address']
+            attrs[n]['battr']['attr']['name'].string(): attrs[n]['address']
             for n in range(int(sect_attrs['nsections']))}
         args = []
         for section_name in [".data", ".data..read_mostly", ".rodata", ".bss",
index 955cf3a..224f510 100755 (executable)
@@ -11,7 +11,7 @@ then
        echo "asm/inline/volatile keywords."
        echo
        echo "INFILE: header file to operate on"
-       echo "OUTFILE: output file which the processed header is writen to"
+       echo "OUTFILE: output file which the processed header is written to"
 
        exit 1
 fi
index c0ac8f7..4a61612 100644 (file)
@@ -4,27 +4,19 @@
  * Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>
  */
 
-#include <qglobal.h>
-
-#include <QMainWindow>
-#include <QList>
-#include <qtextbrowser.h>
 #include <QAction>
+#include <QApplication>
+#include <QCloseEvent>
+#include <QDebug>
+#include <QDesktopWidget>
 #include <QFileDialog>
+#include <QLabel>
+#include <QLayout>
+#include <QList>
 #include <QMenu>
-
-#include <qapplication.h>
-#include <qdesktopwidget.h>
-#include <qtoolbar.h>
-#include <qlayout.h>
-#include <qsplitter.h>
-#include <qlineedit.h>
-#include <qlabel.h>
-#include <qpushbutton.h>
-#include <qmenubar.h>
-#include <qmessagebox.h>
-#include <qregexp.h>
-#include <qevent.h>
+#include <QMenuBar>
+#include <QMessageBox>
+#include <QToolBar>
 
 #include <stdlib.h>
 
@@ -445,9 +437,10 @@ void ConfigList::updateList(ConfigItem* item)
        if (rootEntry != &rootmenu && (mode == singleMode ||
            (mode == symbolMode && rootEntry->parent != &rootmenu))) {
                item = (ConfigItem *)topLevelItem(0);
-               if (!item)
+               if (!item && mode != symbolMode) {
                        item = new ConfigItem(this, 0, true);
-               last = item;
+                       last = item;
+               }
        }
        if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
            rootEntry->sym && rootEntry->prompt) {
@@ -545,7 +538,7 @@ void ConfigList::setRootMenu(struct menu *menu)
        rootEntry = menu;
        updateListAll();
        if (currentItem()) {
-               currentItem()->setSelected(hasFocus());
+               setSelected(currentItem(), hasFocus());
                scrollToItem(currentItem());
        }
 }
@@ -873,7 +866,7 @@ void ConfigList::focusInEvent(QFocusEvent *e)
 
        ConfigItem* item = (ConfigItem *)currentItem();
        if (item) {
-               item->setSelected(true);
+               setSelected(item, true);
                menu = item->menu;
        }
        emit gotFocus(menu);
@@ -1021,7 +1014,7 @@ ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
        : Parent(parent), sym(0), _menu(0)
 {
        setObjectName(name);
-
+       setOpenLinks(false);
 
        if (!objectName().isEmpty()) {
                configSettings->beginGroup(objectName());
@@ -1094,7 +1087,7 @@ void ConfigInfoView::menuInfo(void)
                        if (sym->name) {
                                head += " (";
                                if (showDebug())
-                                       head += QString().sprintf("<a href=\"s%p\">", sym);
+                                       head += QString().sprintf("<a href=\"s%s\">", sym->name);
                                head += print_filter(sym->name);
                                if (showDebug())
                                        head += "</a>";
@@ -1103,7 +1096,7 @@ void ConfigInfoView::menuInfo(void)
                } else if (sym->name) {
                        head += "<big><b>";
                        if (showDebug())
-                               head += QString().sprintf("<a href=\"s%p\">", sym);
+                               head += QString().sprintf("<a href=\"s%s\">", sym->name);
                        head += print_filter(sym->name);
                        if (showDebug())
                                head += "</a>";
@@ -1154,13 +1147,16 @@ QString ConfigInfoView::debug_info(struct symbol *sym)
                switch (prop->type) {
                case P_PROMPT:
                case P_MENU:
-                       debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu);
+                       debug += QString().sprintf("prompt: <a href=\"m%s\">", sym->name);
                        debug += print_filter(prop->text);
                        debug += "</a><br>";
                        break;
                case P_DEFAULT:
                case P_SELECT:
                case P_RANGE:
+               case P_COMMENT:
+               case P_IMPLY:
+               case P_SYMBOL:
                        debug += prop_get_type_name(prop->type);
                        debug += ": ";
                        expr_print(prop->expr, expr_print_help, &debug, E_NONE);
@@ -1226,13 +1222,62 @@ void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char
        QString str2 = print_filter(str);
 
        if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
-               *text += QString().sprintf("<a href=\"s%p\">", sym);
+               *text += QString().sprintf("<a href=\"s%s\">", sym->name);
                *text += str2;
                *text += "</a>";
        } else
                *text += str2;
 }
 
+void ConfigInfoView::clicked(const QUrl &url)
+{
+       QByteArray str = url.toEncoded();
+       const std::size_t count = str.size();
+       char *data = new char[count + 1];
+       struct symbol **result;
+       struct menu *m = NULL;
+
+       if (count < 1) {
+               qInfo() << "Clicked link is empty";
+               delete data;
+               return;
+       }
+
+       memcpy(data, str.constData(), count);
+       data[count] = '\0';
+
+       /* Seek for exact match */
+       data[0] = '^';
+       strcat(data, "$");
+       result = sym_re_search(data);
+       if (!result) {
+               qInfo() << "Clicked symbol is invalid:" << data;
+               delete data;
+               return;
+       }
+
+       sym = *result;
+
+       /* Seek for the menu which holds the symbol */
+       for (struct property *prop = sym->prop; prop; prop = prop->next) {
+                   if (prop->type != P_PROMPT && prop->type != P_MENU)
+                           continue;
+                   m = prop->menu;
+                   break;
+       }
+
+       if (!m) {
+               /* Symbol is not visible as a menu */
+               symbolInfo();
+               emit showDebugChanged(true);
+       } else {
+               emit menuSelected(m);
+       }
+
+       free(result);
+       delete data;
+}
+
 QMenu* ConfigInfoView::createStandardContextMenu(const QPoint & pos)
 {
        QMenu* popup = Parent::createStandardContextMenu(pos);
@@ -1402,18 +1447,22 @@ ConfigMainWindow::ConfigMainWindow(void)
        addToolBar(toolBar);
 
        backAction = new QAction(QPixmap(xpm_back), "Back", this);
-         connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack()));
-         backAction->setEnabled(false);
+       connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack()));
+
        QAction *quitAction = new QAction("&Quit", this);
        quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
-         connect(quitAction, SIGNAL(triggered(bool)), SLOT(close()));
+       connect(quitAction, SIGNAL(triggered(bool)), SLOT(close()));
+
        QAction *loadAction = new QAction(QPixmap(xpm_load), "&Load", this);
        loadAction->setShortcut(Qt::CTRL + Qt::Key_L);
-         connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig()));
+       connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig()));
+
        saveAction = new QAction(QPixmap(xpm_save), "&Save", this);
        saveAction->setShortcut(Qt::CTRL + Qt::Key_S);
-         connect(saveAction, SIGNAL(triggered(bool)), SLOT(saveConfig()));
+       connect(saveAction, SIGNAL(triggered(bool)), SLOT(saveConfig()));
+
        conf_set_changed_callback(conf_changed);
+
        // Set saveAction's initial state
        conf_changed();
        configname = xstrdup(conf_get_configname());
@@ -1506,6 +1555,9 @@ ConfigMainWindow::ConfigMainWindow(void)
        helpMenu->addAction(showIntroAction);
        helpMenu->addAction(showAboutAction);
 
+       connect (helpText, SIGNAL (anchorClicked (const QUrl &)),
+                helpText, SLOT (clicked (const QUrl &)) );
+
        connect(configList, SIGNAL(menuChanged(struct menu *)),
                helpText, SLOT(setInfo(struct menu *)));
        connect(configList, SIGNAL(menuSelected(struct menu *)),
@@ -1611,21 +1663,11 @@ void ConfigMainWindow::searchConfig(void)
 void ConfigMainWindow::changeItens(struct menu *menu)
 {
        configList->setRootMenu(menu);
-
-       if (configList->rootEntry->parent == &rootmenu)
-               backAction->setEnabled(false);
-       else
-               backAction->setEnabled(true);
 }
 
 void ConfigMainWindow::changeMenu(struct menu *menu)
 {
        menuList->setRootMenu(menu);
-
-       if (menuList->rootEntry->parent == &rootmenu)
-               backAction->setEnabled(false);
-       else
-               backAction->setEnabled(true);
 }
 
 void ConfigMainWindow::setMenuLink(struct menu *menu)
@@ -1645,22 +1687,26 @@ void ConfigMainWindow::setMenuLink(struct menu *menu)
                        return;
                list->setRootMenu(parent);
                break;
-       case symbolMode:
+       case menuMode:
                if (menu->flags & MENU_ROOT) {
-                       configList->setRootMenu(menu);
+                       menuList->setRootMenu(menu);
                        configList->clearSelection();
-                       list = menuList;
-               } else {
                        list = configList;
+               } else {
                        parent = menu_get_parent_menu(menu->parent);
                        if (!parent)
                                return;
-                       item = menuList->findConfigItem(parent);
+
+                       /* Select the config view */
+                       item = configList->findConfigItem(parent);
                        if (item) {
-                               item->setSelected(true);
-                               menuList->scrollToItem(item);
+                               configList->setSelected(item, true);
+                               configList->scrollToItem(item);
                        }
-                       list->setRootMenu(parent);
+
+                       menuList->setRootMenu(parent);
+                       menuList->clearSelection();
+                       list = menuList;
                }
                break;
        case fullMode:
@@ -1673,9 +1719,10 @@ void ConfigMainWindow::setMenuLink(struct menu *menu)
        if (list) {
                item = list->findConfigItem(menu);
                if (item) {
-                       item->setSelected(true);
+                       list->setSelected(item, true);
                        list->scrollToItem(item);
                        list->setFocus();
+                       helpText->setInfo(menu);
                }
        }
 }
@@ -1688,25 +1735,11 @@ void ConfigMainWindow::listFocusChanged(void)
 
 void ConfigMainWindow::goBack(void)
 {
-       ConfigItem* item, *oldSelection;
-
-       configList->setParentMenu();
+qInfo() << __FUNCTION__;
        if (configList->rootEntry == &rootmenu)
-               backAction->setEnabled(false);
-
-       if (menuList->selectedItems().count() == 0)
                return;
 
-       item = (ConfigItem*)menuList->selectedItems().first();
-       oldSelection = item;
-       while (item) {
-               if (item->menu == configList->rootEntry) {
-                       oldSelection->setSelected(false);
-                       item->setSelected(true);
-                       break;
-               }
-               item = (ConfigItem*)item->parent();
-       }
+       configList->setParentMenu();
 }
 
 void ConfigMainWindow::showSingleView(void)
@@ -1718,6 +1751,8 @@ void ConfigMainWindow::showSingleView(void)
        fullViewAction->setEnabled(true);
        fullViewAction->setChecked(false);
 
+       backAction->setEnabled(true);
+
        menuView->hide();
        menuList->setRootMenu(0);
        configList->mode = singleMode;
@@ -1737,6 +1772,8 @@ void ConfigMainWindow::showSplitView(void)
        fullViewAction->setEnabled(true);
        fullViewAction->setChecked(false);
 
+       backAction->setEnabled(false);
+
        configList->mode = menuMode;
        if (configList->rootEntry == &rootmenu)
                configList->updateListAll();
@@ -1760,6 +1797,8 @@ void ConfigMainWindow::showFullView(void)
        fullViewAction->setEnabled(false);
        fullViewAction->setChecked(true);
 
+       backAction->setEnabled(false);
+
        menuView->hide();
        menuList->setRootMenu(0);
        configList->mode = fullMode;
index c879d79..fb9e972 100644 (file)
@@ -3,17 +3,17 @@
  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
  */
 
-#include <QTextBrowser>
-#include <QTreeWidget>
-#include <QMainWindow>
+#include <QCheckBox>
+#include <QDialog>
 #include <QHeaderView>
-#include <qsettings.h>
+#include <QLineEdit>
+#include <QMainWindow>
 #include <QPushButton>
 #include <QSettings>
-#include <QLineEdit>
 #include <QSplitter>
-#include <QCheckBox>
-#include <QDialog>
+#include <QTextBrowser>
+#include <QTreeWidget>
+
 #include "expr.h"
 
 class ConfigView;
@@ -45,11 +45,17 @@ class ConfigList : public QTreeWidget {
 public:
        ConfigList(ConfigView* p, const char *name = 0);
        void reinit(void);
+       ConfigItem* findConfigItem(struct menu *);
        ConfigView* parent(void) const
        {
                return (ConfigView*)Parent::parent();
        }
-       ConfigItem* findConfigItem(struct menu *);
+       void setSelected(QTreeWidgetItem *item, bool enable) {
+               for (int i = 0; i < selectedItems().size(); i++)
+                       selectedItems().at(i)->setSelected(false);
+
+               item->setSelected(enable);
+       }
 
 protected:
        void keyPressEvent(QKeyEvent *e);
@@ -250,6 +256,7 @@ public slots:
        void setInfo(struct menu *menu);
        void saveSettings(void);
        void setShowDebug(bool);
+       void clicked (const QUrl &url);
 
 signals:
        void showDebugChanged(bool);
index 6aea65c..45f2ab2 100644 (file)
@@ -138,11 +138,19 @@ char *read_text_file(const char *filename)
 
 char *get_line(char **stringp)
 {
+       char *orig = *stringp, *next;
+
        /* do not return the unwanted extra line at EOF */
-       if (*stringp && **stringp == '\0')
+       if (!orig || *orig == '\0')
                return NULL;
 
-       return strsep(stringp, "\n");
+       next = strchr(orig, '\n');
+       if (next)
+               *next++ = '\0';
+
+       *stringp = next;
+
+       return orig;
 }
 
 /* A list of all modules we processed */
index 74eab03..f9b1952 100644 (file)
 #undef has_rel_mcount
 #undef tot_relsize
 #undef get_mcountsym
+#undef find_symtab
+#undef get_shnum
+#undef set_shnum
+#undef get_shstrndx
+#undef get_symindex
 #undef get_sym_str_and_relp
 #undef do_func
 #undef Elf_Addr
 # define __has_rel_mcount      __has64_rel_mcount
 # define has_rel_mcount                has64_rel_mcount
 # define tot_relsize           tot64_relsize
+# define find_symtab           find_symtab64
+# define get_shnum             get_shnum64
+# define set_shnum             set_shnum64
+# define get_shstrndx          get_shstrndx64
+# define get_symindex          get_symindex64
 # define get_sym_str_and_relp  get_sym_str_and_relp_64
 # define do_func               do64
 # define get_mcountsym         get_mcountsym_64
 # define __has_rel_mcount      __has32_rel_mcount
 # define has_rel_mcount                has32_rel_mcount
 # define tot_relsize           tot32_relsize
+# define find_symtab           find_symtab32
+# define get_shnum             get_shnum32
+# define set_shnum             set_shnum32
+# define get_shstrndx          get_shstrndx32
+# define get_symindex          get_symindex32
 # define get_sym_str_and_relp  get_sym_str_and_relp_32
 # define do_func               do32
 # define get_mcountsym         get_mcountsym_32
@@ -173,6 +188,67 @@ static int MIPS_is_fake_mcount(Elf_Rel const *rp)
        return is_fake;
 }
 
+static unsigned int get_symindex(Elf_Sym const *sym, Elf32_Word const *symtab,
+                                Elf32_Word const *symtab_shndx)
+{
+       unsigned long offset;
+       int index;
+
+       if (sym->st_shndx != SHN_XINDEX)
+               return w2(sym->st_shndx);
+
+       offset = (unsigned long)sym - (unsigned long)symtab;
+       index = offset / sizeof(*sym);
+
+       return w(symtab_shndx[index]);
+}
+
+static unsigned int get_shnum(Elf_Ehdr const *ehdr, Elf_Shdr const *shdr0)
+{
+       if (shdr0 && !ehdr->e_shnum)
+               return w(shdr0->sh_size);
+
+       return w2(ehdr->e_shnum);
+}
+
+static void set_shnum(Elf_Ehdr *ehdr, Elf_Shdr *shdr0, unsigned int new_shnum)
+{
+       if (new_shnum >= SHN_LORESERVE) {
+               ehdr->e_shnum = 0;
+               shdr0->sh_size = w(new_shnum);
+       } else
+               ehdr->e_shnum = w2(new_shnum);
+}
+
+static int get_shstrndx(Elf_Ehdr const *ehdr, Elf_Shdr const *shdr0)
+{
+       if (ehdr->e_shstrndx != SHN_XINDEX)
+               return w2(ehdr->e_shstrndx);
+
+       return w(shdr0->sh_link);
+}
+
+static void find_symtab(Elf_Ehdr *const ehdr, Elf_Shdr const *shdr0,
+                       unsigned const nhdr, Elf32_Word **symtab,
+                       Elf32_Word **symtab_shndx)
+{
+       Elf_Shdr const *relhdr;
+       unsigned k;
+
+       *symtab = NULL;
+       *symtab_shndx = NULL;
+
+       for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) {
+               if (relhdr->sh_type == SHT_SYMTAB)
+                       *symtab = (void *)ehdr + relhdr->sh_offset;
+               else if (relhdr->sh_type == SHT_SYMTAB_SHNDX)
+                       *symtab_shndx = (void *)ehdr + relhdr->sh_offset;
+
+               if (*symtab && *symtab_shndx)
+                       break;
+       }
+}
+
 /* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */
 static int append_func(Elf_Ehdr *const ehdr,
                        Elf_Shdr *const shstr,
@@ -188,10 +264,12 @@ static int append_func(Elf_Ehdr *const ehdr,
        char const *mc_name = (sizeof(Elf_Rela) == rel_entsize)
                ? ".rela__mcount_loc"
                :  ".rel__mcount_loc";
-       unsigned const old_shnum = w2(ehdr->e_shnum);
        uint_t const old_shoff = _w(ehdr->e_shoff);
        uint_t const old_shstr_sh_size   = _w(shstr->sh_size);
        uint_t const old_shstr_sh_offset = _w(shstr->sh_offset);
+       Elf_Shdr *const shdr0 = (Elf_Shdr *)(old_shoff + (void *)ehdr);
+       unsigned int const old_shnum = get_shnum(ehdr, shdr0);
+       unsigned int const new_shnum = 2 + old_shnum; /* {.rel,}__mcount_loc */
        uint_t t = 1 + strlen(mc_name) + _w(shstr->sh_size);
        uint_t new_e_shoff;
 
@@ -201,6 +279,8 @@ static int append_func(Elf_Ehdr *const ehdr,
        t += (_align & -t);  /* word-byte align */
        new_e_shoff = t;
 
+       set_shnum(ehdr, shdr0, new_shnum);
+
        /* body for new shstrtab */
        if (ulseek(sb.st_size, SEEK_SET) < 0)
                return -1;
@@ -255,7 +335,6 @@ static int append_func(Elf_Ehdr *const ehdr,
                return -1;
 
        ehdr->e_shoff = _w(new_e_shoff);
-       ehdr->e_shnum = w2(2 + w2(ehdr->e_shnum));  /* {.rel,}__mcount_loc */
        if (ulseek(0, SEEK_SET) < 0)
                return -1;
        if (uwrite(ehdr, sizeof(*ehdr)) < 0)
@@ -434,6 +513,8 @@ static int find_secsym_ndx(unsigned const txtndx,
                                uint_t *const recvalp,
                                unsigned int *sym_index,
                                Elf_Shdr const *const symhdr,
+                               Elf32_Word const *symtab,
+                               Elf32_Word const *symtab_shndx,
                                Elf_Ehdr const *const ehdr)
 {
        Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symhdr->sh_offset)
@@ -445,7 +526,7 @@ static int find_secsym_ndx(unsigned const txtndx,
        for (symp = sym0, t = nsym; t; --t, ++symp) {
                unsigned int const st_bind = ELF_ST_BIND(symp->st_info);
 
-               if (txtndx == w2(symp->st_shndx)
+               if (txtndx == get_symindex(symp, symtab, symtab_shndx)
                        /* avoid STB_WEAK */
                    && (STB_LOCAL == st_bind || STB_GLOBAL == st_bind)) {
                        /* function symbols on ARM have quirks, avoid them */
@@ -516,21 +597,23 @@ static unsigned tot_relsize(Elf_Shdr const *const shdr0,
        return totrelsz;
 }
 
-
 /* Overall supervision for Elf32 ET_REL file. */
 static int do_func(Elf_Ehdr *const ehdr, char const *const fname,
                   unsigned const reltype)
 {
        Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
                + (void *)ehdr);
-       unsigned const nhdr = w2(ehdr->e_shnum);
-       Elf_Shdr *const shstr = &shdr0[w2(ehdr->e_shstrndx)];
+       unsigned const nhdr = get_shnum(ehdr, shdr0);
+       Elf_Shdr *const shstr = &shdr0[get_shstrndx(ehdr, shdr0)];
        char const *const shstrtab = (char const *)(_w(shstr->sh_offset)
                + (void *)ehdr);
 
        Elf_Shdr const *relhdr;
        unsigned k;
 
+       Elf32_Word *symtab;
+       Elf32_Word *symtab_shndx;
+
        /* Upper bound on space: assume all relevant relocs are for mcount. */
        unsigned       totrelsz;
 
@@ -561,6 +644,8 @@ static int do_func(Elf_Ehdr *const ehdr, char const *const fname,
                return -1;
        }
 
+       find_symtab(ehdr, shdr0, nhdr, &symtab, &symtab_shndx);
+
        for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) {
                char const *const txtname = has_rel_mcount(relhdr, shdr0,
                        shstrtab, fname);
@@ -577,6 +662,7 @@ static int do_func(Elf_Ehdr *const ehdr, char const *const fname,
                        result = find_secsym_ndx(w(relhdr->sh_info), txtname,
                                                &recval, &recsym,
                                                &shdr0[symsec_sh_link],
+                                               symtab, symtab_shndx,
                                                ehdr);
                        if (result)
                                goto out;
index e12c490..1d20003 100644 (file)
@@ -188,19 +188,7 @@ DEFINE_LSM(integrity) = {
 int integrity_kernel_read(struct file *file, loff_t offset,
                          void *addr, unsigned long count)
 {
-       mm_segment_t old_fs;
-       char __user *buf = (char __user *)addr;
-       ssize_t ret;
-
-       if (!(file->f_mode & FMODE_READ))
-               return -EBADF;
-
-       old_fs = get_fs();
-       set_fs(KERNEL_DS);
-       ret = __vfs_read(file, buf, count, &offset);
-       set_fs(old_fs);
-
-       return ret;
+       return __kernel_read(file, addr, count, &offset);
 }
 
 /*
index df93ac2..9d94080 100644 (file)
@@ -30,7 +30,7 @@
 
 enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_BINARY_NO_FIELD_LEN,
                     IMA_SHOW_BINARY_OLD_STRING_FMT, IMA_SHOW_ASCII };
-enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
+enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 };
 
 /* digest size for IMA, fits SHA1 or MD5 */
 #define IMA_DIGEST_SIZE                SHA1_DIGEST_SIZE
index 220b149..011c3c7 100644 (file)
@@ -823,13 +823,26 @@ static int ima_calc_boot_aggregate_tfm(char *digest, u16 alg_id,
        if (rc != 0)
                return rc;
 
-       /* cumulative sha1 over tpm registers 0-7 */
+       /* cumulative digest over TPM registers 0-7 */
        for (i = TPM_PCR0; i < TPM_PCR8; i++) {
                ima_pcrread(i, &d);
                /* now accumulate with current aggregate */
                rc = crypto_shash_update(shash, d.digest,
                                         crypto_shash_digestsize(tfm));
        }
+       /*
+        * Extend cumulative digest over TPM registers 8-9, which contain
+        * measurement for the kernel command line (reg. 8) and image (reg. 9)
+        * in a typical PCR allocation. Registers 8-9 are only included in
+        * non-SHA1 boot_aggregate digests to avoid ambiguity.
+        */
+       if (alg_id != TPM_ALG_SHA1) {
+               for (i = TPM_PCR8; i < TPM_PCR10; i++) {
+                       ima_pcrread(i, &d);
+                       rc = crypto_shash_update(shash, d.digest,
+                                               crypto_shash_digestsize(tfm));
+               }
+       }
        if (!rc)
                crypto_shash_final(shash, digest);
        return rc;
index 298b737..16c1894 100644 (file)
@@ -107,7 +107,7 @@ struct ima_digest_data {
                } ng;
                u8 data[2];
        } xattr;
-       u8 digest[0];
+       u8 digest[];
 } __packed;
 
 /*
@@ -119,7 +119,7 @@ struct signature_v2_hdr {
        uint8_t hash_algo;      /* Digest algorithm [enum hash_algo] */
        __be32 keyid;           /* IMA key identifier - not X509/PGP specific */
        __be16 sig_size;        /* signature size */
-       uint8_t sig[0];         /* signature payload */
+       uint8_t sig[];          /* signature payload */
 } __packed;
 
 /* integrity data associated with an inode */
index 0ce3e73..70a7ad3 100644 (file)
@@ -1414,7 +1414,22 @@ EXPORT_SYMBOL(security_inode_copy_up);
 
 int security_inode_copy_up_xattr(const char *name)
 {
-       return call_int_hook(inode_copy_up_xattr, -EOPNOTSUPP, name);
+       struct security_hook_list *hp;
+       int rc;
+
+       /*
+        * The implementation can return 0 (accept the xattr), 1 (discard the
+        * xattr), -EOPNOTSUPP if it does not know anything about the xattr or
+        * any other error code incase of an error.
+        */
+       hlist_for_each_entry(hp,
+               &security_hook_heads.inode_copy_up_xattr, list) {
+               rc = hp->hook.inode_copy_up_xattr(name);
+               if (rc != LSM_RET_DEFAULT(inode_copy_up_xattr))
+                       return rc;
+       }
+
+       return LSM_RET_DEFAULT(inode_copy_up_xattr);
 }
 EXPORT_SYMBOL(security_inode_copy_up_xattr);
 
index da94a1b..0cc7cdd 100644 (file)
@@ -27,6 +27,9 @@ static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
        int s[COND_EXPR_MAXDEPTH];
        int sp = -1;
 
+       if (expr->len == 0)
+               return -1;
+
        for (i = 0; i < expr->len; i++) {
                struct cond_expr_node *node = &expr->nodes[i];
 
@@ -392,27 +395,19 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
 
                rc = next_entry(buf, fp, sizeof(u32) * 2);
                if (rc)
-                       goto err;
+                       return rc;
 
                expr->expr_type = le32_to_cpu(buf[0]);
                expr->bool = le32_to_cpu(buf[1]);
 
-               if (!expr_node_isvalid(p, expr)) {
-                       rc = -EINVAL;
-                       goto err;
-               }
+               if (!expr_node_isvalid(p, expr))
+                       return -EINVAL;
        }
 
        rc = cond_read_av_list(p, fp, &node->true_list, NULL);
        if (rc)
-               goto err;
-       rc = cond_read_av_list(p, fp, &node->false_list, &node->true_list);
-       if (rc)
-               goto err;
-       return 0;
-err:
-       cond_node_destroy(node);
-       return rc;
+               return rc;
+       return cond_read_av_list(p, fp, &node->false_list, &node->true_list);
 }
 
 int cond_read_list(struct policydb *p, void *fp)
index 313919b..ef0afd8 100644 (file)
@@ -2888,8 +2888,12 @@ err:
        if (*names) {
                for (i = 0; i < *len; i++)
                        kfree((*names)[i]);
+               kfree(*names);
        }
        kfree(*values);
+       *len = 0;
+       *names = NULL;
+       *values = NULL;
        goto out;
 }
 
index 509290f..0e53f6f 100644 (file)
@@ -764,6 +764,9 @@ static int snd_compr_stop(struct snd_compr_stream *stream)
 
        retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
        if (!retval) {
+               /* clear flags and stop any drain wait */
+               stream->partial_drain = false;
+               stream->metadata_set = false;
                snd_compr_drain_notify(stream);
                stream->runtime->total_bytes_available = 0;
                stream->runtime->total_bytes_transferred = 0;
@@ -921,6 +924,7 @@ static int snd_compr_partial_drain(struct snd_compr_stream *stream)
        if (stream->next_track == false)
                return -EPERM;
 
+       stream->partial_drain = true;
        retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_PARTIAL_DRAIN);
        if (retval) {
                pr_debug("Partial drain returned failure\n");
index 8c6bc52..9fec307 100644 (file)
@@ -606,7 +606,9 @@ int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len)
 {
        int c;
 
-       if (snd_BUG_ON(!buffer || !buffer->buffer))
+       if (snd_BUG_ON(!buffer))
+               return 1;
+       if (!buffer->buffer)
                return 1;
        if (len <= 0 || buffer->stop || buffer->error)
                return 1;
index e69a4ef..08c10ac 100644 (file)
@@ -91,6 +91,8 @@ int snd_opl3_ioctl(struct snd_hwdep * hw, struct file *file,
                {
                        struct snd_dm_fm_info info;
 
+                       memset(&info, 0, sizeof(info));
+
                        info.fm_mode = opl3->fm_mode;
                        info.rhythm = opl3->rhythm;
                        if (copy_to_user(argp, &info, sizeof(struct snd_dm_fm_info)))
index 20b8f6c..99aec73 100644 (file)
@@ -208,8 +208,8 @@ static const struct config_entry config_table[] = {
        },
 #endif
 
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE)
 /* Cometlake-LP */
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP)
        {
                .flags = FLAG_SOF,
                .device = 0x02c8,
@@ -240,9 +240,7 @@ static const struct config_entry config_table[] = {
                .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
                .device = 0x02c8,
        },
-#endif
 /* Cometlake-H */
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H)
        {
                .flags = FLAG_SOF,
                .device = 0x06c8,
index 2c6d2be..824f4ac 100644 (file)
@@ -72,6 +72,12 @@ static int compare_input_type(const void *ap, const void *bp)
        if (a->type != b->type)
                return (int)(a->type - b->type);
 
+       /* If has both hs_mic and hp_mic, pick the hs_mic ahead of hp_mic. */
+       if (a->is_headset_mic && b->is_headphone_mic)
+               return -1; /* don't swap */
+       else if (a->is_headphone_mic && b->is_headset_mic)
+               return 1; /* swap */
+
        /* In case one has boost and the other one has not,
           pick the one with boost first. */
        return (int)(b->has_boost_on_pin - a->has_boost_on_pin);
index 7e3ae45..803978d 100644 (file)
@@ -2935,6 +2935,10 @@ static int hda_codec_runtime_suspend(struct device *dev)
        struct hda_codec *codec = dev_to_hda_codec(dev);
        unsigned int state;
 
+       /* Nothing to do if card registration fails and the component driver never probes */
+       if (!codec->card)
+               return 0;
+
        cancel_delayed_work_sync(&codec->jackpoll_work);
        state = hda_call_codec_suspend(codec);
        if (codec->link_down_at_suspend ||
@@ -2949,6 +2953,10 @@ static int hda_codec_runtime_resume(struct device *dev)
 {
        struct hda_codec *codec = dev_to_hda_codec(dev);
 
+       /* Nothing to do if card registration fails and the component driver never probes */
+       if (!codec->card)
+               return 0;
+
        codec_display_power(codec, true);
        snd_hdac_codec_link_up(&codec->core);
        hda_call_codec_resume(codec);
index 82e2644..a356fb0 100644 (file)
@@ -41,7 +41,7 @@
 /* 24 unused */
 #define AZX_DCAPS_COUNT_LPIB_DELAY  (1 << 25)  /* Take LPIB as delay */
 #define AZX_DCAPS_PM_RUNTIME   (1 << 26)       /* runtime PM support */
-/* 27 unused */
+#define AZX_DCAPS_SUSPEND_SPURIOUS_WAKEUP (1 << 27) /* Workaround for spurious wakeups after suspend */
 #define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28)  /* CORBRP clears itself after reset */
 #define AZX_DCAPS_NO_MSI64      (1 << 29)      /* Stick to 32-bit MSIs */
 #define AZX_DCAPS_SEPARATE_STREAM_TAG  (1 << 30) /* capture and playback use separate stream tag */
index d20aedd..3fbba2e 100644 (file)
@@ -298,7 +298,8 @@ enum {
 /* PCH for HSW/BDW; with runtime PM */
 /* no i915 binding for this as HSW/BDW has another controller for HDMI */
 #define AZX_DCAPS_INTEL_PCH \
-       (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME)
+       (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\
+        AZX_DCAPS_SUSPEND_SPURIOUS_WAKEUP)
 
 /* HSW HDMI */
 #define AZX_DCAPS_INTEL_HASWELL \
@@ -1028,7 +1029,14 @@ static int azx_suspend(struct device *dev)
        chip = card->private_data;
        bus = azx_bus(chip);
        snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-       pm_runtime_force_suspend(dev);
+       /* An ugly workaround: direct call of __azx_runtime_suspend() and
+        * __azx_runtime_resume() for old Intel platforms that suffer from
+        * spurious wakeups after S3 suspend
+        */
+       if (chip->driver_caps & AZX_DCAPS_SUSPEND_SPURIOUS_WAKEUP)
+               __azx_runtime_suspend(chip);
+       else
+               pm_runtime_force_suspend(dev);
        if (bus->irq >= 0) {
                free_irq(bus->irq, chip);
                bus->irq = -1;
@@ -1057,7 +1065,10 @@ static int azx_resume(struct device *dev)
        if (azx_acquire_irq(chip, 1) < 0)
                return -EIO;
 
-       pm_runtime_force_resume(dev);
+       if (chip->driver_caps & AZX_DCAPS_SUSPEND_SPURIOUS_WAKEUP)
+               __azx_runtime_resume(chip, false);
+       else
+               pm_runtime_force_resume(dev);
        snd_power_change_state(card, SNDRV_CTL_POWER_D0);
 
        trace_azx_resume(chip);
@@ -2470,6 +2481,9 @@ static const struct pci_device_id azx_ids[] = {
        /* Icelake */
        { PCI_DEVICE(0x8086, 0x34c8),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
+       /* Icelake-H */
+       { PCI_DEVICE(0x8086, 0x3dc8),
+         .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
        /* Jasperlake */
        { PCI_DEVICE(0x8086, 0x38c8),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
@@ -2478,9 +2492,14 @@ static const struct pci_device_id azx_ids[] = {
        /* Tigerlake */
        { PCI_DEVICE(0x8086, 0xa0c8),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
+       /* Tigerlake-H */
+       { PCI_DEVICE(0x8086, 0x43c8),
+         .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
        /* Elkhart Lake */
        { PCI_DEVICE(0x8086, 0x4b55),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
+       { PCI_DEVICE(0x8086, 0x4b58),
+         .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
        /* Broxton-P(Apollolake) */
        { PCI_DEVICE(0x8086, 0x5a98),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON },
index fbd7cc6..cd46247 100644 (file)
@@ -259,7 +259,7 @@ static int hinfo_to_pcm_index(struct hda_codec *codec,
                if (get_pcm_rec(spec, pcm_idx)->stream == hinfo)
                        return pcm_idx;
 
-       codec_warn(codec, "HDMI: hinfo %p not registered\n", hinfo);
+       codec_warn(codec, "HDMI: hinfo %p not tied to a PCM\n", hinfo);
        return -EINVAL;
 }
 
@@ -277,7 +277,8 @@ static int hinfo_to_pin_index(struct hda_codec *codec,
                        return pin_idx;
        }
 
-       codec_dbg(codec, "HDMI: hinfo %p not registered\n", hinfo);
+       codec_dbg(codec, "HDMI: hinfo %p (pcm %d) not registered\n", hinfo,
+                 hinfo_to_pcm_index(codec, hinfo));
        return -EINVAL;
 }
 
@@ -1804,33 +1805,43 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
 
 static int hdmi_parse_codec(struct hda_codec *codec)
 {
-       hda_nid_t nid;
+       hda_nid_t start_nid;
+       unsigned int caps;
        int i, nodes;
 
-       nodes = snd_hda_get_sub_nodes(codec, codec->core.afg, &nid);
-       if (!nid || nodes < 0) {
+       nodes = snd_hda_get_sub_nodes(codec, codec->core.afg, &start_nid);
+       if (!start_nid || nodes < 0) {
                codec_warn(codec, "HDMI: failed to get afg sub nodes\n");
                return -EINVAL;
        }
 
-       for (i = 0; i < nodes; i++, nid++) {
-               unsigned int caps;
-               unsigned int type;
+       /*
+        * hdmi_add_pin() assumes total amount of converters to
+        * be known, so first discover all converters
+        */
+       for (i = 0; i < nodes; i++) {
+               hda_nid_t nid = start_nid + i;
 
                caps = get_wcaps(codec, nid);
-               type = get_wcaps_type(caps);
 
                if (!(caps & AC_WCAP_DIGITAL))
                        continue;
 
-               switch (type) {
-               case AC_WID_AUD_OUT:
+               if (get_wcaps_type(caps) == AC_WID_AUD_OUT)
                        hdmi_add_cvt(codec, nid);
-                       break;
-               case AC_WID_PIN:
+       }
+
+       /* discover audio pins */
+       for (i = 0; i < nodes; i++) {
+               hda_nid_t nid = start_nid + i;
+
+               caps = get_wcaps(codec, nid);
+
+               if (!(caps & AC_WCAP_DIGITAL))
+                       continue;
+
+               if (get_wcaps_type(caps) == AC_WID_PIN)
                        hdmi_add_pin(codec, nid);
-                       break;
-               }
        }
 
        return 0;
@@ -2429,6 +2440,7 @@ static void generic_acomp_notifier_set(struct drm_audio_component *acomp,
        mutex_lock(&spec->bind_lock);
        spec->use_acomp_notifier = use_acomp;
        spec->codec->relaxed_resume = use_acomp;
+       spec->codec->bus->keep_power = 0;
        /* reprogram each jack detection logic depending on the notifier */
        for (i = 0; i < spec->num_pins; i++)
                reprogram_jack_detect(spec->codec,
@@ -2523,7 +2535,6 @@ static void generic_acomp_init(struct hda_codec *codec,
        if (!snd_hdac_acomp_init(&codec->bus->core, &spec->drm_audio_ops,
                                 match_bound_vga, 0)) {
                spec->acomp_registered = true;
-               codec->bus->keep_power = 0;
        }
 }
 
@@ -4145,6 +4156,11 @@ HDA_CODEC_ENTRY(0x10de0095, "GPU 95 HDMI/DP",    patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de0097, "GPU 97 HDMI/DP",  patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de0098, "GPU 98 HDMI/DP",  patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de0099, "GPU 99 HDMI/DP",  patch_nvhdmi),
+HDA_CODEC_ENTRY(0x10de009a, "GPU 9a HDMI/DP",  patch_nvhdmi),
+HDA_CODEC_ENTRY(0x10de009d, "GPU 9d HDMI/DP",  patch_nvhdmi),
+HDA_CODEC_ENTRY(0x10de009e, "GPU 9e HDMI/DP",  patch_nvhdmi),
+HDA_CODEC_ENTRY(0x10de009f, "GPU 9f HDMI/DP",  patch_nvhdmi),
+HDA_CODEC_ENTRY(0x10de00a0, "GPU a0 HDMI/DP",  patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de8001, "MCP73 HDMI",      patch_nvhdmi_2ch),
 HDA_CODEC_ENTRY(0x10de8067, "MCP67/68 HDMI",   patch_nvhdmi_2ch),
 HDA_CODEC_ENTRY(0x11069f80, "VX900 HDMI/DP",   patch_via_hdmi),
index 6d73f8b..29f5878 100644 (file)
@@ -2461,6 +2461,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
        SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1458, 0xa0ce, "Gigabyte X570 Aorus Xtreme", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1462, 0x11f7, "MSI-GE63", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1462, 0x1275, "MSI-GL63", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950),
@@ -5974,6 +5975,16 @@ static void alc_fixup_disable_mic_vref(struct hda_codec *codec,
                snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ);
 }
 
+static void  alc285_fixup_hp_gpio_amp_init(struct hda_codec *codec,
+                             const struct hda_fixup *fix, int action)
+{
+       if (action != HDA_FIXUP_ACT_INIT)
+               return;
+
+       msleep(100);
+       alc_write_coef_idx(codec, 0x65, 0x0);
+}
+
 /* for hda_fixup_thinkpad_acpi() */
 #include "thinkpad_helper.c"
 
@@ -6148,6 +6159,13 @@ enum {
        ALC236_FIXUP_HP_MUTE_LED,
        ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
        ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
+       ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS,
+       ALC269VC_FIXUP_ACER_HEADSET_MIC,
+       ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE,
+       ALC289_FIXUP_ASUS_GA401,
+       ALC289_FIXUP_ASUS_GA502,
+       ALC256_FIXUP_ACER_MIC_NO_PRESENCE,
+       ALC285_FIXUP_HP_GPIO_AMP_INIT,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -7113,7 +7131,7 @@ static const struct hda_fixup alc269_fixups[] = {
                        { }
                },
                .chained = true,
-               .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
+               .chain_id = ALC269_FIXUP_HEADSET_MIC
        },
        [ALC294_FIXUP_ASUS_HEADSET_MIC] = {
                .type = HDA_FIXUP_PINS,
@@ -7122,7 +7140,7 @@ static const struct hda_fixup alc269_fixups[] = {
                        { }
                },
                .chained = true,
-               .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
+               .chain_id = ALC269_FIXUP_HEADSET_MIC
        },
        [ALC294_FIXUP_ASUS_SPK] = {
                .type = HDA_FIXUP_VERBS,
@@ -7130,6 +7148,8 @@ static const struct hda_fixup alc269_fixups[] = {
                        /* Set EAPD high */
                        { 0x20, AC_VERB_SET_COEF_INDEX, 0x40 },
                        { 0x20, AC_VERB_SET_PROC_COEF, 0x8800 },
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x0f },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x7774 },
                        { }
                },
                .chained = true,
@@ -7326,6 +7346,64 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC269_FIXUP_HEADSET_MODE
        },
+       [ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x14, 0x90100120 }, /* use as internal speaker */
+                       { 0x18, 0x02a111f0 }, /* use as headset mic, without its own jack detect */
+                       { 0x1a, 0x01011020 }, /* use as line out */
+                       { },
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_HEADSET_MIC
+       },
+       [ALC269VC_FIXUP_ACER_HEADSET_MIC] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x18, 0x02a11030 }, /* use as headset mic */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_HEADSET_MIC
+       },
+       [ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x18, 0x01a11130 }, /* use as headset mic, without its own jack detect */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_HEADSET_MIC
+       },
+       [ALC289_FIXUP_ASUS_GA401] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x19, 0x03a11020 }, /* headset mic with jack detect */
+                       { }
+               },
+       },
+       [ALC289_FIXUP_ASUS_GA502] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x19, 0x03a11020 }, /* headset mic with jack detect */
+                       { }
+               },
+       },
+       [ALC256_FIXUP_ACER_MIC_NO_PRESENCE] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x19, 0x02a11120 }, /* use as headset mic, without its own jack detect */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC256_FIXUP_ASUS_HEADSET_MODE
+       },
+       [ALC285_FIXUP_HP_GPIO_AMP_INIT] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc285_fixup_hp_gpio_amp_init,
+               .chained = true,
+               .chain_id = ALC285_FIXUP_HP_GPIO_LED
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -7341,16 +7419,20 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
        SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS),
        SND_PCI_QUIRK(0x1025, 0x102b, "Acer Aspire C24-860", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1025, 0x1065, "Acer Aspire C20-820", ALC269VC_FIXUP_ACER_HEADSET_MIC),
        SND_PCI_QUIRK(0x1025, 0x106d, "Acer Cloudbook 14", ALC283_FIXUP_CHROME_BOOK),
        SND_PCI_QUIRK(0x1025, 0x1099, "Acer Aspire E5-523G", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1025, 0x110e, "Acer Aspire ES1-432", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1025, 0x1246, "Acer Predator Helios 500", ALC299_FIXUP_PREDATOR_SPK),
+       SND_PCI_QUIRK(0x1025, 0x1247, "Acer vCopperbox", ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS),
+       SND_PCI_QUIRK(0x1025, 0x1248, "Acer Veriton N4660G", ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1025, 0x128f, "Acer Veriton Z6860G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
        SND_PCI_QUIRK(0x1025, 0x1290, "Acer Veriton Z4860G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
        SND_PCI_QUIRK(0x1025, 0x1291, "Acer Veriton Z4660G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
        SND_PCI_QUIRK(0x1025, 0x1308, "Acer Aspire Z24-890", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
        SND_PCI_QUIRK(0x1025, 0x132a, "Acer TravelMate B114-21", ALC233_FIXUP_ACER_HEADSET_MIC),
        SND_PCI_QUIRK(0x1025, 0x1330, "Acer TravelMate X514-51T", ALC255_FIXUP_ACER_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1025, 0x1430, "Acer TravelMate B311R-31", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
        SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS),
        SND_PCI_QUIRK(0x1028, 0x05bd, "Dell Latitude E6440", ALC292_FIXUP_DELL_E7X),
@@ -7470,7 +7552,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
        SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
        SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
-       SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED),
+       SND_PCI_QUIRK(0x103c, 0x8729, "HP", ALC285_FIXUP_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_AMP_INIT),
        SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED),
        SND_PCI_QUIRK(0x103c, 0x877d, "HP", ALC236_FIXUP_HP_MUTE_LED),
        SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
@@ -7492,6 +7576,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK),
        SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC),
        SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1043, 0x194e, "ASUS UX563FD", ALC294_FIXUP_ASUS_HPE),
        SND_PCI_QUIRK(0x1043, 0x19ce, "ASUS B9450FA", ALC294_FIXUP_ASUS_HPE),
        SND_PCI_QUIRK(0x1043, 0x19e1, "ASUS UX581LV", ALC295_FIXUP_ASUS_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
@@ -7501,6 +7586,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC),
+       SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502),
+       SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401),
        SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2),
        SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
@@ -7520,11 +7607,13 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x10cf, 0x1629, "Lifebook U7x7", ALC255_FIXUP_LIFEBOOK_U7x7_HEADSET_MIC),
        SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
        SND_PCI_QUIRK(0x10ec, 0x10f2, "Intel Reference board", ALC700_FIXUP_INTEL_REFERENCE),
+       SND_PCI_QUIRK(0x10ec, 0x1230, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
        SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_HEADSET_MODE),
        SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC),
        SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
        SND_PCI_QUIRK(0x144d, 0xc176, "Samsung Notebook 9 Pro (NP930MBE-K04US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
        SND_PCI_QUIRK(0x144d, 0xc740, "Samsung Ativ book 8 (NP870Z5G)", ALC269_FIXUP_ATIV_BOOK_8),
+       SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
        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),
@@ -7568,8 +7657,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x224c, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x224d, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x225d, "Thinkpad T480", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
-       SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Yoga 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK),
-       SND_PCI_QUIRK(0x17aa, 0x2293, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK),
+       SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK),
        SND_PCI_QUIRK(0x17aa, 0x22be, "Thinkpad X1 Carbon 8th", ALC285_FIXUP_THINKPAD_HEADSET_JACK),
        SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
        SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
index d8f554f..e6386de 100644 (file)
@@ -342,11 +342,34 @@ static int acp3x_dma_close(struct snd_soc_component *component,
 {
        struct snd_soc_pcm_runtime *prtd;
        struct i2s_dev_data *adata;
+       struct i2s_stream_instance *ins;
 
        prtd = substream->private_data;
        component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
        adata = dev_get_drvdata(component->dev);
+       ins = substream->runtime->private_data;
+       if (!ins)
+               return -EINVAL;
 
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               switch (ins->i2s_instance) {
+               case I2S_BT_INSTANCE:
+                       adata->play_stream = NULL;
+                       break;
+               case I2S_SP_INSTANCE:
+               default:
+                       adata->i2ssp_play_stream = NULL;
+               }
+       } else {
+               switch (ins->i2s_instance) {
+               case I2S_BT_INSTANCE:
+                       adata->capture_stream = NULL;
+                       break;
+               case I2S_SP_INSTANCE:
+               default:
+                       adata->i2ssp_capture_stream = NULL;
+               }
+       }
 
        /* Disable ACP irq, when the current stream is being closed and
         * another stream is also not active.
@@ -354,13 +377,6 @@ static int acp3x_dma_close(struct snd_soc_component *component,
        if (!adata->play_stream && !adata->capture_stream &&
                !adata->i2ssp_play_stream && !adata->i2ssp_capture_stream)
                rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               adata->play_stream = NULL;
-               adata->i2ssp_play_stream = NULL;
-       } else {
-               adata->capture_stream = NULL;
-               adata->i2ssp_capture_stream = NULL;
-       }
        return 0;
 }
 
index f25ce50..ebf4388 100644 (file)
@@ -232,9 +232,7 @@ static int snd_acp3x_probe(struct pci_dev *pci,
        }
        pm_runtime_set_autosuspend_delay(&pci->dev, 2000);
        pm_runtime_use_autosuspend(&pci->dev);
-       pm_runtime_set_active(&pci->dev);
        pm_runtime_put_noidle(&pci->dev);
-       pm_runtime_enable(&pci->dev);
        pm_runtime_allow(&pci->dev);
        return 0;
 
@@ -303,7 +301,7 @@ static void snd_acp3x_remove(struct pci_dev *pci)
        ret = acp3x_deinit(adata->acp3x_base);
        if (ret)
                dev_err(&pci->dev, "ACP de-init failed\n");
-       pm_runtime_disable(&pci->dev);
+       pm_runtime_forbid(&pci->dev);
        pm_runtime_get_noresume(&pci->dev);
        pci_disable_msi(pci);
        pci_release_regions(pci);
index e437193..4a82690 100644 (file)
@@ -2,6 +2,7 @@
 # Renoir platform Support
 snd-rn-pci-acp3x-objs  := rn-pci-acp3x.o
 snd-acp3x-pdm-dma-objs := acp3x-pdm-dma.o
-obj-$(CONFIG_SND_SOC_AMD_RENOIR)        += snd-rn-pci-acp3x.o
-obj-$(CONFIG_SND_SOC_AMD_RENOIR)        += snd-acp3x-pdm-dma.o
-obj-$(CONFIG_SND_SOC_AMD_RENOIR_MACH)  += acp3x-rn.o
+snd-acp3x-rn-objs      := acp3x-rn.o
+obj-$(CONFIG_SND_SOC_AMD_RENOIR)       += snd-rn-pci-acp3x.o
+obj-$(CONFIG_SND_SOC_AMD_RENOIR)       += snd-acp3x-pdm-dma.o
+obj-$(CONFIG_SND_SOC_AMD_RENOIR_MACH)  += snd-acp3x-rn.o
index de003ac..473efe9 100644 (file)
@@ -441,13 +441,13 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component)
        ret = snd_hda_codec_set_name(hcodec, hcodec->preset->name);
        if (ret < 0) {
                dev_err(&hdev->dev, "name failed %s\n", hcodec->preset->name);
-               goto error;
+               goto error_pm;
        }
 
        ret = snd_hdac_regmap_init(&hcodec->core);
        if (ret < 0) {
                dev_err(&hdev->dev, "regmap init failed\n");
-               goto error;
+               goto error_pm;
        }
 
        patch = (hda_codec_patch_t)hcodec->preset->driver_data;
@@ -455,7 +455,7 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component)
                ret = patch(hcodec);
                if (ret < 0) {
                        dev_err(&hdev->dev, "patch failed %d\n", ret);
-                       goto error;
+                       goto error_regmap;
                }
        } else {
                dev_dbg(&hdev->dev, "no patch file found\n");
@@ -467,7 +467,7 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component)
        ret = snd_hda_codec_parse_pcms(hcodec);
        if (ret < 0) {
                dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret);
-               goto error;
+               goto error_regmap;
        }
 
        /* HDMI controls need to be created in machine drivers */
@@ -476,7 +476,7 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component)
                if (ret < 0) {
                        dev_err(&hdev->dev, "unable to create controls %d\n",
                                ret);
-                       goto error;
+                       goto error_regmap;
                }
        }
 
@@ -496,7 +496,9 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component)
 
        return 0;
 
-error:
+error_regmap:
+       snd_hdac_regmap_exit(hdev);
+error_pm:
        pm_runtime_put(&hdev->dev);
 error_no_pm:
        snd_hdac_ext_bus_link_put(hdev->bus, hlink);
@@ -518,6 +520,8 @@ static void hdac_hda_codec_remove(struct snd_soc_component *component)
 
        pm_runtime_disable(&hdev->dev);
        snd_hdac_ext_bus_link_put(hdev->bus, hlink);
+
+       snd_hdac_regmap_exit(hdev);
 }
 
 static const struct snd_soc_dapm_route hdac_hda_dapm_routes[] = {
index 96718e3..d87402a 100644 (file)
@@ -779,13 +779,6 @@ static int max98373_probe(struct snd_soc_component *component)
        regmap_write(max98373->regmap,
                MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2,
                0x1);
-       /* Set inital volume (0dB) */
-       regmap_write(max98373->regmap,
-               MAX98373_R203D_AMP_DIG_VOL_CTRL,
-               0x00);
-       regmap_write(max98373->regmap,
-               MAX98373_R203E_AMP_PATH_GAIN,
-               0x00);
        /* Enable DC blocker */
        regmap_write(max98373->regmap,
                MAX98373_R203F_AMP_DSP_CFG,
@@ -869,7 +862,6 @@ static const struct snd_soc_component_driver soc_codec_dev_max98373 = {
        .num_dapm_widgets       = ARRAY_SIZE(max98373_dapm_widgets),
        .dapm_routes            = max98373_audio_map,
        .num_dapm_routes        = ARRAY_SIZE(max98373_audio_map),
-       .idle_bias_on           = 1,
        .use_pmdown_time        = 1,
        .endianness             = 1,
        .non_legacy_dai_naming  = 1,
index 0d63ebf..e6613b5 100644 (file)
@@ -700,8 +700,8 @@ static bool max98390_readable_register(struct device *dev, unsigned int reg)
        case MAX98390_IRQ_CTRL ... MAX98390_WDOG_CTRL:
        case MAX98390_MEAS_ADC_THERM_WARN_THRESH
                ... MAX98390_BROWNOUT_INFINITE_HOLD:
-       case MAX98390_BROWNOUT_LVL_HOLD ... THERMAL_COILTEMP_RD_BACK_BYTE0:
-       case DSMIG_DEBUZZER_THRESHOLD ... MAX98390_R24FF_REV_ID:
+       case MAX98390_BROWNOUT_LVL_HOLD ... DSMIG_DEBUZZER_THRESHOLD:
+       case DSM_VOL_ENA ... MAX98390_R24FF_REV_ID:
                return true;
        default:
                return false;
@@ -717,7 +717,7 @@ static bool max98390_volatile_reg(struct device *dev, unsigned int reg)
        case MAX98390_BROWNOUT_LOWEST_STATUS:
        case MAX98390_ENV_TRACK_BOOST_VOUT_READ:
        case DSM_STBASS_HPF_B0_BYTE0 ... DSM_DEBUZZER_ATTACK_TIME_BYTE2:
-       case THERMAL_RDC_RD_BACK_BYTE1 ... THERMAL_COILTEMP_RD_BACK_BYTE0:
+       case THERMAL_RDC_RD_BACK_BYTE1 ... DSMIG_DEBUZZER_THRESHOLD:
        case DSM_THERMAL_GAIN ... DSM_WBDRC_GAIN:
                return true;
        default:
index 67e2e94..2cccb31 100644 (file)
@@ -34,30 +34,32 @@ static const struct reg_default rt1015_reg[] = {
        { 0x0000, 0x0000 },
        { 0x0004, 0xa000 },
        { 0x0006, 0x0003 },
-       { 0x000a, 0x0802 },
-       { 0x000c, 0x0020 },
+       { 0x000a, 0x081e },
+       { 0x000c, 0x0006 },
        { 0x000e, 0x0000 },
        { 0x0010, 0x0000 },
        { 0x0012, 0x0000 },
+       { 0x0014, 0x0000 },
+       { 0x0016, 0x0000 },
+       { 0x0018, 0x0000 },
        { 0x0020, 0x8000 },
-       { 0x0022, 0x471b },
-       { 0x006a, 0x0000 },
-       { 0x006c, 0x4020 },
+       { 0x0022, 0x8043 },
        { 0x0076, 0x0000 },
        { 0x0078, 0x0000 },
-       { 0x007a, 0x0000 },
+       { 0x007a, 0x0002 },
        { 0x007c, 0x10ec },
        { 0x007d, 0x1015 },
        { 0x00f0, 0x5000 },
-       { 0x00f2, 0x0774 },
-       { 0x00f3, 0x8400 },
+       { 0x00f2, 0x004c },
+       { 0x00f3, 0xecfe },
        { 0x00f4, 0x0000 },
+       { 0x00f6, 0x0400 },
        { 0x0100, 0x0028 },
        { 0x0102, 0xff02 },
-       { 0x0104, 0x8232 },
+       { 0x0104, 0xa213 },
        { 0x0106, 0x200c },
-       { 0x010c, 0x002f },
-       { 0x010e, 0xc000 },
+       { 0x010c, 0x0000 },
+       { 0x010e, 0x0058 },
        { 0x0111, 0x0200 },
        { 0x0112, 0x0400 },
        { 0x0114, 0x0022 },
@@ -65,38 +67,46 @@ static const struct reg_default rt1015_reg[] = {
        { 0x0118, 0x0000 },
        { 0x011a, 0x0123 },
        { 0x011c, 0x4567 },
-       { 0x0300, 0xdddd },
-       { 0x0302, 0x0000 },
-       { 0x0311, 0x9330 },
-       { 0x0313, 0x0000 },
-       { 0x0314, 0x0000 },
+       { 0x0300, 0x203d },
+       { 0x0302, 0x001e },
+       { 0x0311, 0x0000 },
+       { 0x0313, 0x6014 },
+       { 0x0314, 0x00a2 },
        { 0x031a, 0x00a0 },
        { 0x031c, 0x001f },
        { 0x031d, 0xffff },
        { 0x031e, 0x0000 },
        { 0x031f, 0x0000 },
+       { 0x0320, 0x0000 },
        { 0x0321, 0x0000 },
-       { 0x0322, 0x0000 },
-       { 0x0328, 0x0000 },
-       { 0x0329, 0x0000 },
-       { 0x032a, 0x0000 },
-       { 0x032b, 0x0000 },
-       { 0x032c, 0x0000 },
-       { 0x032d, 0x0000 },
-       { 0x032e, 0x030e },
-       { 0x0330, 0x0080 },
+       { 0x0322, 0xd7df },
+       { 0x0328, 0x10b2 },
+       { 0x0329, 0x0175 },
+       { 0x032a, 0x36ad },
+       { 0x032b, 0x7e55 },
+       { 0x032c, 0x0520 },
+       { 0x032d, 0xaa00 },
+       { 0x032e, 0x570e },
+       { 0x0330, 0xe180 },
        { 0x0332, 0x0034 },
-       { 0x0334, 0x0000 },
-       { 0x0336, 0x0000 },
+       { 0x0334, 0x0001 },
+       { 0x0336, 0x0010 },
+       { 0x0338, 0x0000 },
+       { 0x04fa, 0x0030 },
+       { 0x04fc, 0x35c8 },
+       { 0x04fe, 0x0800 },
+       { 0x0500, 0x0400 },
+       { 0x0502, 0x1000 },
+       { 0x0504, 0x0000 },
        { 0x0506, 0x04ff },
-       { 0x0508, 0x0030 },
-       { 0x050a, 0x0018 },
-       { 0x0519, 0x307f },
-       { 0x051a, 0xffff },
-       { 0x051b, 0x4000 },
+       { 0x0508, 0x0010 },
+       { 0x050a, 0x001a },
+       { 0x0519, 0x1c68 },
+       { 0x051a, 0x0ccc },
+       { 0x051b, 0x0666 },
        { 0x051d, 0x0000 },
        { 0x051f, 0x0000 },
-       { 0x0536, 0x1000 },
+       { 0x0536, 0x061c },
        { 0x0538, 0x0000 },
        { 0x053a, 0x0000 },
        { 0x053c, 0x0000 },
@@ -110,19 +120,18 @@ static const struct reg_default rt1015_reg[] = {
        { 0x0544, 0x0000 },
        { 0x0568, 0x0000 },
        { 0x056a, 0x0000 },
-       { 0x1000, 0x0000 },
-       { 0x1002, 0x6505 },
+       { 0x1000, 0x0040 },
+       { 0x1002, 0x5405 },
        { 0x1006, 0x5515 },
-       { 0x1007, 0x003f },
-       { 0x1009, 0x770f },
-       { 0x100a, 0x01ff },
-       { 0x100c, 0x0000 },
+       { 0x1007, 0x05f7 },
+       { 0x1009, 0x0b0a },
+       { 0x100a, 0x00ef },
        { 0x100d, 0x0003 },
        { 0x1010, 0xa433 },
        { 0x1020, 0x0000 },
-       { 0x1200, 0x3d02 },
-       { 0x1202, 0x0813 },
-       { 0x1204, 0x0211 },
+       { 0x1200, 0x5a01 },
+       { 0x1202, 0x6524 },
+       { 0x1204, 0x1f00 },
        { 0x1206, 0x0000 },
        { 0x1208, 0x0000 },
        { 0x120a, 0x0000 },
@@ -130,16 +139,16 @@ static const struct reg_default rt1015_reg[] = {
        { 0x120e, 0x0000 },
        { 0x1210, 0x0000 },
        { 0x1212, 0x0000 },
-       { 0x1300, 0x0701 },
-       { 0x1302, 0x12f9 },
-       { 0x1304, 0x3405 },
+       { 0x1300, 0x10a1 },
+       { 0x1302, 0x12ff },
+       { 0x1304, 0x0400 },
        { 0x1305, 0x0844 },
-       { 0x1306, 0x1611 },
+       { 0x1306, 0x4611 },
        { 0x1308, 0x555e },
        { 0x130a, 0x0000 },
-       { 0x130c, 0x2400},
-       { 0x130e, 0x7700 },
-       { 0x130f, 0x0000 },
+       { 0x130c, 0x2000 },
+       { 0x130e, 0x0100 },
+       { 0x130f, 0x0001 },
        { 0x1310, 0x0000 },
        { 0x1312, 0x0000 },
        { 0x1314, 0x0000 },
@@ -209,6 +218,9 @@ static bool rt1015_volatile_register(struct device *dev, unsigned int reg)
        case RT1015_DC_CALIB_CLSD7:
        case RT1015_DC_CALIB_CLSD8:
        case RT1015_S_BST_TIMING_INTER1:
+       case RT1015_OSCK_STA:
+       case RT1015_MONO_DYNA_CTRL1:
+       case RT1015_MONO_DYNA_CTRL5:
                return true;
 
        default:
@@ -224,6 +236,12 @@ static bool rt1015_readable_register(struct device *dev, unsigned int reg)
        case RT1015_CLK3:
        case RT1015_PLL1:
        case RT1015_PLL2:
+       case RT1015_DUM_RW1:
+       case RT1015_DUM_RW2:
+       case RT1015_DUM_RW3:
+       case RT1015_DUM_RW4:
+       case RT1015_DUM_RW5:
+       case RT1015_DUM_RW6:
        case RT1015_CLK_DET:
        case RT1015_SIL_DET:
        case RT1015_CUSTOMER_ID:
@@ -235,6 +253,7 @@ static bool rt1015_readable_register(struct device *dev, unsigned int reg)
        case RT1015_PAD_DRV2:
        case RT1015_GAT_BOOST:
        case RT1015_PRO_ALT:
+       case RT1015_OSCK_STA:
        case RT1015_MAN_I2C:
        case RT1015_DAC1:
        case RT1015_DAC2:
@@ -272,6 +291,13 @@ static bool rt1015_readable_register(struct device *dev, unsigned int reg)
        case RT1015_SMART_BST_CTRL2:
        case RT1015_ANA_CTRL1:
        case RT1015_ANA_CTRL2:
+       case RT1015_PWR_STATE_CTRL:
+       case RT1015_MONO_DYNA_CTRL:
+       case RT1015_MONO_DYNA_CTRL1:
+       case RT1015_MONO_DYNA_CTRL2:
+       case RT1015_MONO_DYNA_CTRL3:
+       case RT1015_MONO_DYNA_CTRL4:
+       case RT1015_MONO_DYNA_CTRL5:
        case RT1015_SPK_VOL:
        case RT1015_SHORT_DETTOP1:
        case RT1015_SHORT_DETTOP2:
index 6fbe802..8169962 100644 (file)
 #define RT1015_CLK3                            0x0006
 #define RT1015_PLL1                            0x000a
 #define RT1015_PLL2                            0x000c
+#define RT1015_DUM_RW1                         0x000e
+#define RT1015_DUM_RW2                         0x0010
+#define RT1015_DUM_RW3                         0x0012
+#define RT1015_DUM_RW4                         0x0014
+#define RT1015_DUM_RW5                         0x0016
+#define RT1015_DUM_RW6                         0x0018
 #define RT1015_CLK_DET                         0x0020
 #define RT1015_SIL_DET                         0x0022
 #define RT1015_CUSTOMER_ID                     0x0076
@@ -32,6 +38,7 @@
 #define RT1015_PAD_DRV2                                0x00f2
 #define RT1015_GAT_BOOST                       0x00f3
 #define RT1015_PRO_ALT                         0x00f4
+#define RT1015_OSCK_STA                                0x00f6
 #define RT1015_MAN_I2C                         0x0100
 #define RT1015_DAC1                            0x0102
 #define RT1015_DAC2                            0x0104
 #define RT1015_ANA_CTRL1                       0x0334
 #define RT1015_ANA_CTRL2                       0x0336
 #define RT1015_PWR_STATE_CTRL                  0x0338
-#define RT1015_SPK_VOL                         0x0506
+#define RT1015_MONO_DYNA_CTRL                  0x04fa
+#define RT1015_MONO_DYNA_CTRL1                 0x04fc
+#define RT1015_MONO_DYNA_CTRL2                 0x04fe
+#define RT1015_MONO_DYNA_CTRL3                 0x0500
+#define RT1015_MONO_DYNA_CTRL4                 0x0502
+#define RT1015_MONO_DYNA_CTRL5                 0x0504
+#define RT1015_SPK_VOL                                 0x0506
 #define RT1015_SHORT_DETTOP1                   0x0508
 #define RT1015_SHORT_DETTOP2                   0x050a
 #define RT1015_SPK_DC_DETECT1                  0x0519
index 9593a9a..e8d14ee 100644 (file)
@@ -272,13 +272,13 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic)
                regmap_read(rt286->regmap, RT286_GET_MIC1_SENSE, &buf);
                *mic = buf & 0x80000000;
        }
-       if (!*mic) {
+
+       if (!*hp) {
                snd_soc_dapm_disable_pin(dapm, "HV");
                snd_soc_dapm_disable_pin(dapm, "VREF");
-       }
-       if (!*hp)
                snd_soc_dapm_disable_pin(dapm, "LDO1");
-       snd_soc_dapm_sync(dapm);
+               snd_soc_dapm_sync(dapm);
+       }
 
        return 0;
 }
index 70fee68..dfbc0ca 100644 (file)
 #include "rt5670.h"
 #include "rt5670-dsp.h"
 
-#define RT5670_DEV_GPIO     BIT(0)
-#define RT5670_IN2_DIFF     BIT(1)
-#define RT5670_DMIC_EN      BIT(2)
-#define RT5670_DMIC1_IN2P   BIT(3)
-#define RT5670_DMIC1_GPIO6  BIT(4)
-#define RT5670_DMIC1_GPIO7  BIT(5)
-#define RT5670_DMIC2_INR    BIT(6)
-#define RT5670_DMIC2_GPIO8  BIT(7)
-#define RT5670_DMIC3_GPIO5  BIT(8)
-#define RT5670_JD_MODE1     BIT(9)
-#define RT5670_JD_MODE2     BIT(10)
-#define RT5670_JD_MODE3     BIT(11)
+#define RT5670_DEV_GPIO                        BIT(0)
+#define RT5670_IN2_DIFF                        BIT(1)
+#define RT5670_DMIC_EN                 BIT(2)
+#define RT5670_DMIC1_IN2P              BIT(3)
+#define RT5670_DMIC1_GPIO6             BIT(4)
+#define RT5670_DMIC1_GPIO7             BIT(5)
+#define RT5670_DMIC2_INR               BIT(6)
+#define RT5670_DMIC2_GPIO8             BIT(7)
+#define RT5670_DMIC3_GPIO5             BIT(8)
+#define RT5670_JD_MODE1                        BIT(9)
+#define RT5670_JD_MODE2                        BIT(10)
+#define RT5670_JD_MODE3                        BIT(11)
+#define RT5670_GPIO1_IS_EXT_SPK_EN     BIT(12)
 
 static unsigned long rt5670_quirk;
 static unsigned int quirk_override;
@@ -602,9 +603,9 @@ int rt5670_set_jack_detect(struct snd_soc_component *component,
 EXPORT_SYMBOL_GPL(rt5670_set_jack_detect);
 
 static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
-static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0);
+static const DECLARE_TLV_DB_MINMAX(dac_vol_tlv, -6562, 0);
 static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
-static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
+static const DECLARE_TLV_DB_MINMAX(adc_vol_tlv, -1762, 3000);
 static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
 
 /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
@@ -1447,6 +1448,33 @@ static int rt5670_hp_event(struct snd_soc_dapm_widget *w,
        return 0;
 }
 
+static int rt5670_spk_event(struct snd_soc_dapm_widget *w,
+       struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+       struct rt5670_priv *rt5670 = snd_soc_component_get_drvdata(component);
+
+       if (!rt5670->pdata.gpio1_is_ext_spk_en)
+               return 0;
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2,
+                                  RT5670_GP1_OUT_MASK, RT5670_GP1_OUT_HI);
+               break;
+
+       case SND_SOC_DAPM_PRE_PMD:
+               regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2,
+                                  RT5670_GP1_OUT_MASK, RT5670_GP1_OUT_LO);
+               break;
+
+       default:
+               return 0;
+       }
+
+       return 0;
+}
+
 static int rt5670_bst1_event(struct snd_soc_dapm_widget *w,
        struct snd_kcontrol *kcontrol, int event)
 {
@@ -1860,7 +1888,9 @@ static const struct snd_soc_dapm_widget rt5670_specific_dapm_widgets[] = {
 };
 
 static const struct snd_soc_dapm_widget rt5672_specific_dapm_widgets[] = {
-       SND_SOC_DAPM_PGA("SPO Amp", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA_E("SPO Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
+                          rt5670_spk_event, SND_SOC_DAPM_PRE_PMD |
+                          SND_SOC_DAPM_POST_PMU),
        SND_SOC_DAPM_OUTPUT("SPOLP"),
        SND_SOC_DAPM_OUTPUT("SPOLN"),
        SND_SOC_DAPM_OUTPUT("SPORP"),
@@ -2857,14 +2887,14 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = {
        },
        {
                .callback = rt5670_quirk_cb,
-               .ident = "Lenovo Thinkpad Tablet 10",
+               .ident = "Lenovo Miix 2 10",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
                        DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Miix 2 10"),
                },
                .driver_data = (unsigned long *)(RT5670_DMIC_EN |
                                                 RT5670_DMIC1_IN2P |
-                                                RT5670_DEV_GPIO |
+                                                RT5670_GPIO1_IS_EXT_SPK_EN |
                                                 RT5670_JD_MODE2),
        },
        {
@@ -2924,6 +2954,10 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,
                rt5670->pdata.dev_gpio = true;
                dev_info(&i2c->dev, "quirk dev_gpio\n");
        }
+       if (rt5670_quirk & RT5670_GPIO1_IS_EXT_SPK_EN) {
+               rt5670->pdata.gpio1_is_ext_spk_en = true;
+               dev_info(&i2c->dev, "quirk GPIO1 is external speaker enable\n");
+       }
        if (rt5670_quirk & RT5670_IN2_DIFF) {
                rt5670->pdata.in2_diff = true;
                dev_info(&i2c->dev, "quirk IN2_DIFF\n");
@@ -3023,6 +3057,13 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,
                                   RT5670_GP1_PF_MASK, RT5670_GP1_PF_OUT);
        }
 
+       if (rt5670->pdata.gpio1_is_ext_spk_en) {
+               regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1,
+                                  RT5670_GP1_PIN_MASK, RT5670_GP1_PIN_GPIO1);
+               regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2,
+                                  RT5670_GP1_PF_MASK, RT5670_GP1_PF_OUT);
+       }
+
        if (rt5670->pdata.jd_mode) {
                regmap_update_bits(rt5670->regmap, RT5670_GLB_CLK,
                                   RT5670_SCLK_SRC_MASK, RT5670_SCLK_SRC_RCCLK);
index a8c3e44..de02033 100644 (file)
 #define RT5670_PWR_VREF2_BIT                   4
 #define RT5670_PWR_FV2                         (0x1 << 3)
 #define RT5670_PWR_FV2_BIT                     3
-#define RT5670_LDO_SEL_MASK                    (0x3)
+#define RT5670_LDO_SEL_MASK                    (0x7)
 #define RT5670_LDO_SEL_SFT                     0
 
 /* Power Management for Analog 2 (0x64) */
index d324512..d503b5b 100644 (file)
@@ -932,7 +932,9 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert)
                        RT5682_PWR_ANLG_1, RT5682_PWR_FV2, RT5682_PWR_FV2);
                snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3,
                        RT5682_PWR_CBJ, RT5682_PWR_CBJ);
-
+               snd_soc_component_update_bits(component,
+                       RT5682_HP_CHARGE_PUMP_1,
+                       RT5682_OSW_L_MASK | RT5682_OSW_R_MASK, 0);
                snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
                        RT5682_TRIG_JD_MASK, RT5682_TRIG_JD_HIGH);
 
@@ -956,17 +958,21 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert)
                        rt5682->jack_type = SND_JACK_HEADPHONE;
                        break;
                }
+
+               snd_soc_component_update_bits(component,
+                       RT5682_HP_CHARGE_PUMP_1,
+                       RT5682_OSW_L_MASK | RT5682_OSW_R_MASK,
+                       RT5682_OSW_L_EN | RT5682_OSW_R_EN);
        } else {
                rt5682_enable_push_button_irq(component, false);
                snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
                        RT5682_TRIG_JD_MASK, RT5682_TRIG_JD_LOW);
-               if (snd_soc_dapm_get_pin_status(dapm, "MICBIAS"))
+               if (!snd_soc_dapm_get_pin_status(dapm, "MICBIAS"))
                        snd_soc_component_update_bits(component,
-                               RT5682_PWR_ANLG_1, RT5682_PWR_VREF2, 0);
-               else
+                               RT5682_PWR_ANLG_1, RT5682_PWR_MB, 0);
+               if (!snd_soc_dapm_get_pin_status(dapm, "Vref2"))
                        snd_soc_component_update_bits(component,
-                               RT5682_PWR_ANLG_1,
-                               RT5682_PWR_VREF2 | RT5682_PWR_MB, 0);
+                               RT5682_PWR_ANLG_1, RT5682_PWR_VREF2, 0);
                snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3,
                        RT5682_PWR_CBJ, 0);
 
@@ -985,16 +991,17 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component,
 
        rt5682->hs_jack = hs_jack;
 
-       if (!rt5682->is_sdw) {
-               if (!hs_jack) {
-                       regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2,
-                               RT5682_JD1_EN_MASK, RT5682_JD1_DIS);
-                       regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL,
-                               RT5682_POW_JDH | RT5682_POW_JDL, 0);
-                       cancel_delayed_work_sync(&rt5682->jack_detect_work);
-                       return 0;
-               }
+       if (!hs_jack) {
+               regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2,
+                       RT5682_JD1_EN_MASK, RT5682_JD1_DIS);
+               regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL,
+                       RT5682_POW_JDH | RT5682_POW_JDL, 0);
+               cancel_delayed_work_sync(&rt5682->jack_detect_work);
+
+               return 0;
+       }
 
+       if (!rt5682->is_sdw) {
                switch (rt5682->pdata.jd_src) {
                case RT5682_JD1:
                        snd_soc_component_update_bits(component,
@@ -1075,7 +1082,8 @@ void rt5682_jack_detect_handler(struct work_struct *work)
                        /* jack was out, report jack type */
                        rt5682->jack_type =
                                rt5682_headset_detect(rt5682->component, 1);
-               } else {
+               } else if ((rt5682->jack_type & SND_JACK_HEADSET) ==
+                       SND_JACK_HEADSET) {
                        /* jack is already in, report button event */
                        rt5682->jack_type = SND_JACK_HEADSET;
                        btn_type = rt5682_button_detect(rt5682->component);
@@ -1601,8 +1609,7 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = {
                0, set_filter_clk, SND_SOC_DAPM_PRE_PMU),
        SND_SOC_DAPM_SUPPLY("Vref1", RT5682_PWR_ANLG_1, RT5682_PWR_VREF1_BIT, 0,
                rt5682_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
-       SND_SOC_DAPM_SUPPLY("Vref2", RT5682_PWR_ANLG_1, RT5682_PWR_VREF2_BIT, 0,
-               NULL, 0),
+       SND_SOC_DAPM_SUPPLY("Vref2", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_SUPPLY("MICBIAS", SND_SOC_NOPM, 0, 0, NULL, 0),
 
        /* ASRC */
@@ -2485,6 +2492,15 @@ static int rt5682_wclk_prepare(struct clk_hw *hw)
        snd_soc_dapm_force_enable_pin_unlocked(dapm, "MICBIAS");
        snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1,
                                RT5682_PWR_MB, RT5682_PWR_MB);
+
+       snd_soc_dapm_force_enable_pin_unlocked(dapm, "Vref2");
+       snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1,
+                       RT5682_PWR_VREF2 | RT5682_PWR_FV2,
+                       RT5682_PWR_VREF2);
+       usleep_range(55000, 60000);
+       snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1,
+                       RT5682_PWR_FV2, RT5682_PWR_FV2);
+
        snd_soc_dapm_force_enable_pin_unlocked(dapm, "I2S1");
        snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL2F");
        snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL2B");
@@ -2510,9 +2526,12 @@ static void rt5682_wclk_unprepare(struct clk_hw *hw)
        snd_soc_dapm_mutex_lock(dapm);
 
        snd_soc_dapm_disable_pin_unlocked(dapm, "MICBIAS");
+       snd_soc_dapm_disable_pin_unlocked(dapm, "Vref2");
        if (!rt5682->jack_type)
                snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1,
+                               RT5682_PWR_VREF2 | RT5682_PWR_FV2 |
                                RT5682_PWR_MB, 0);
+
        snd_soc_dapm_disable_pin_unlocked(dapm, "I2S1");
        snd_soc_dapm_disable_pin_unlocked(dapm, "PLL2F");
        snd_soc_dapm_disable_pin_unlocked(dapm, "PLL2B");
@@ -2829,12 +2848,13 @@ static int rt5682_probe(struct snd_soc_component *component)
                                return ret;
                        }
                        rt5682->mclk = NULL;
-               } else {
-                       /* Register CCF DAI clock control */
-                       ret = rt5682_register_dai_clks(component);
-                       if (ret)
-                               return ret;
                }
+
+               /* Register CCF DAI clock control */
+               ret = rt5682_register_dai_clks(component);
+               if (ret)
+                       return ret;
+
                /* Initial setup for CCF */
                rt5682->lrck[RT5682_AIF1] = CLK_48;
 #endif
index 06ba365..7cfc896 100644 (file)
@@ -186,7 +186,7 @@ SOC_DAPM_SINGLE("PCM Playback Switch", WM8974_MONOMIX, 0, 1, 0),
 
 /* Boost mixer */
 static const struct snd_kcontrol_new wm8974_boost_mixer[] = {
-SOC_DAPM_SINGLE("Aux Switch", WM8974_INPPGA, 6, 1, 0),
+SOC_DAPM_SINGLE("Aux Switch", WM8974_INPPGA, 6, 1, 1),
 };
 
 /* Input PGA */
@@ -474,6 +474,10 @@ static int wm8974_set_dai_fmt(struct snd_soc_dai *codec_dai,
                iface |= 0x0008;
                break;
        case SND_SOC_DAIFMT_DSP_A:
+               if ((fmt & SND_SOC_DAIFMT_INV_MASK) == SND_SOC_DAIFMT_IB_IF ||
+                   (fmt & SND_SOC_DAIFMT_INV_MASK) == SND_SOC_DAIFMT_NB_IF) {
+                       return -EINVAL;
+               }
                iface |= 0x00018;
                break;
        default:
index 77665b1..7e1c13c 100644 (file)
@@ -32,6 +32,7 @@ enum asrc_pair_index {
  * @dma_chan: inputer and output DMA channels
  * @dma_data: private dma data
  * @pos: hardware pointer position
+ * @req_dma_chan: flag to release dev_to_dev chan
  * @private: pair private area
  */
 struct fsl_asrc_pair {
@@ -45,6 +46,7 @@ struct fsl_asrc_pair {
        struct dma_chan *dma_chan[2];
        struct imx_dma_data dma_data;
        unsigned int pos;
+       bool req_dma_chan;
 
        void *private;
 };
index d6a3fc5..5f01a58 100644 (file)
@@ -135,6 +135,8 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
        struct snd_dmaengine_dai_dma_data *dma_params_be = NULL;
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct fsl_asrc_pair *pair = runtime->private_data;
+       struct dma_chan *tmp_chan = NULL, *be_chan = NULL;
+       struct snd_soc_component *component_be = NULL;
        struct fsl_asrc *asrc = pair->asrc;
        struct dma_slave_config config_fe, config_be;
        enum asrc_pair_index index = pair->index;
@@ -142,7 +144,6 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
        int stream = substream->stream;
        struct imx_dma_data *tmp_data;
        struct snd_soc_dpcm *dpcm;
-       struct dma_chan *tmp_chan;
        struct device *dev_be;
        u8 dir = tx ? OUT : IN;
        dma_cap_mask_t mask;
@@ -197,18 +198,30 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
        dma_cap_set(DMA_SLAVE, mask);
        dma_cap_set(DMA_CYCLIC, mask);
 
+       /*
+        * The Back-End device might have already requested a DMA channel,
+        * so try to reuse it first, and then request a new one upon NULL.
+        */
+       component_be = snd_soc_lookup_component_nolocked(dev_be, SND_DMAENGINE_PCM_DRV_NAME);
+       if (component_be) {
+               be_chan = soc_component_to_pcm(component_be)->chan[substream->stream];
+               tmp_chan = be_chan;
+       }
+       if (!tmp_chan)
+               tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
+
        /*
         * An EDMA DEV_TO_DEV channel is fixed and bound with DMA event of each
         * peripheral, unlike SDMA channel that is allocated dynamically. So no
-        * need to configure dma_request and dma_request2, but get dma_chan via
-        * dma_request_slave_channel directly with dma name of Front-End device
+        * need to configure dma_request and dma_request2, but get dma_chan of
+        * Back-End device directly via dma_request_slave_channel.
         */
        if (!asrc->use_edma) {
                /* Get DMA request of Back-End */
-               tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
                tmp_data = tmp_chan->private;
                pair->dma_data.dma_request = tmp_data->dma_request;
-               dma_release_channel(tmp_chan);
+               if (!be_chan)
+                       dma_release_channel(tmp_chan);
 
                /* Get DMA request of Front-End */
                tmp_chan = asrc->get_dma_channel(pair, dir);
@@ -220,9 +233,11 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
 
                pair->dma_chan[dir] =
                        dma_request_channel(mask, filter, &pair->dma_data);
+               pair->req_dma_chan = true;
        } else {
-               pair->dma_chan[dir] =
-                       asrc->get_dma_channel(pair, dir);
+               pair->dma_chan[dir] = tmp_chan;
+               /* Do not flag to release if we are reusing the Back-End one */
+               pair->req_dma_chan = !be_chan;
        }
 
        if (!pair->dma_chan[dir]) {
@@ -261,7 +276,8 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
        ret = dmaengine_slave_config(pair->dma_chan[dir], &config_be);
        if (ret) {
                dev_err(dev, "failed to config DMA channel for Back-End\n");
-               dma_release_channel(pair->dma_chan[dir]);
+               if (pair->req_dma_chan)
+                       dma_release_channel(pair->dma_chan[dir]);
                return ret;
        }
 
@@ -273,19 +289,22 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
 static int fsl_asrc_dma_hw_free(struct snd_soc_component *component,
                                struct snd_pcm_substream *substream)
 {
+       bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct fsl_asrc_pair *pair = runtime->private_data;
+       u8 dir = tx ? OUT : IN;
 
        snd_pcm_set_runtime_buffer(substream, NULL);
 
-       if (pair->dma_chan[IN])
-               dma_release_channel(pair->dma_chan[IN]);
+       if (pair->dma_chan[!dir])
+               dma_release_channel(pair->dma_chan[!dir]);
 
-       if (pair->dma_chan[OUT])
-               dma_release_channel(pair->dma_chan[OUT]);
+       /* release dev_to_dev chan if we aren't reusing the Back-End one */
+       if (pair->dma_chan[dir] && pair->req_dma_chan)
+               dma_release_channel(pair->dma_chan[dir]);
 
-       pair->dma_chan[IN] = NULL;
-       pair->dma_chan[OUT] = NULL;
+       pair->dma_chan[!dir] = NULL;
+       pair->dma_chan[dir] = NULL;
 
        return 0;
 }
index 0c813a4..69aeb0e 100644 (file)
@@ -265,12 +265,20 @@ static int fsl_mqs_remove(struct platform_device *pdev)
 static int fsl_mqs_runtime_resume(struct device *dev)
 {
        struct fsl_mqs *mqs_priv = dev_get_drvdata(dev);
+       int ret;
 
-       if (mqs_priv->ipg)
-               clk_prepare_enable(mqs_priv->ipg);
+       ret = clk_prepare_enable(mqs_priv->ipg);
+       if (ret) {
+               dev_err(dev, "failed to enable ipg clock\n");
+               return ret;
+       }
 
-       if (mqs_priv->mclk)
-               clk_prepare_enable(mqs_priv->mclk);
+       ret = clk_prepare_enable(mqs_priv->mclk);
+       if (ret) {
+               dev_err(dev, "failed to enable mclk clock\n");
+               clk_disable_unprepare(mqs_priv->ipg);
+               return ret;
+       }
 
        if (mqs_priv->use_gpr)
                regmap_write(mqs_priv->regmap, IOMUXC_GPR2,
@@ -292,11 +300,8 @@ static int fsl_mqs_runtime_suspend(struct device *dev)
                regmap_read(mqs_priv->regmap, REG_MQS_CTRL,
                            &mqs_priv->reg_mqs_ctrl);
 
-       if (mqs_priv->mclk)
-               clk_disable_unprepare(mqs_priv->mclk);
-
-       if (mqs_priv->ipg)
-               clk_disable_unprepare(mqs_priv->ipg);
+       clk_disable_unprepare(mqs_priv->mclk);
+       clk_disable_unprepare(mqs_priv->ipg);
 
        return 0;
 }
index bad89b0..1a2fa7f 100644 (file)
@@ -678,8 +678,9 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream,
        struct regmap *regs = ssi->regs;
        u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
        unsigned long clkrate, baudrate, tmprate;
-       unsigned int slots = params_channels(hw_params);
-       unsigned int slot_width = 32;
+       unsigned int channels = params_channels(hw_params);
+       unsigned int slot_width = params_width(hw_params);
+       unsigned int slots = 2;
        u64 sub, savesub = 100000;
        unsigned int freq;
        bool baudclk_is_used;
@@ -688,10 +689,14 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream,
        /* Override slots and slot_width if being specifically set... */
        if (ssi->slots)
                slots = ssi->slots;
-       /* ...but keep 32 bits if slots is 2 -- I2S Master mode */
-       if (ssi->slot_width && slots != 2)
+       if (ssi->slot_width)
                slot_width = ssi->slot_width;
 
+       /* ...but force 32 bits for stereo audio using I2S Master Mode */
+       if (channels == 2 &&
+           (ssi->i2s_net & SSI_SCR_I2S_MODE_MASK) == SSI_SCR_I2S_MODE_MASTER)
+               slot_width = 32;
+
        /* Generate bit clock based on the slot number and slot width */
        freq = slots * slot_width * params_rate(hw_params);
 
index 9ad35d9..97b4f54 100644 (file)
@@ -317,8 +317,8 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
        if (ret < 0)
                goto out_put_node;
 
-       dai_link->dpcm_playback         = 1;
-       dai_link->dpcm_capture          = 1;
+       snd_soc_dai_link_set_capabilities(dai_link);
+
        dai_link->ops                   = &graph_ops;
        dai_link->init                  = asoc_simple_dai_init;
 
index 55e9f88..04d4d28 100644 (file)
@@ -231,8 +231,8 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
        if (ret < 0)
                goto out_put_node;
 
-       dai_link->dpcm_playback         = 1;
-       dai_link->dpcm_capture          = 1;
+       snd_soc_dai_link_set_capabilities(dai_link);
+
        dai_link->ops                   = &simple_ops;
        dai_link->init                  = asoc_simple_dai_init;
 
index a2a5798..5dc489a 100644 (file)
@@ -492,7 +492,7 @@ config SND_SOC_INTEL_SOF_PCM512x_MACH
 
 endif ## SND_SOC_SOF_HDA_LINK || SND_SOC_SOF_BAYTRAIL
 
-if (SND_SOC_SOF_COMETLAKE_LP && SND_SOC_SOF_HDA_LINK)
+if (SND_SOC_SOF_COMETLAKE && SND_SOC_SOF_HDA_LINK)
 
 config SND_SOC_INTEL_CML_LP_DA7219_MAX98357A_MACH
        tristate "CML_LP with DA7219 and MAX98357A in I2S Mode"
@@ -520,7 +520,7 @@ config SND_SOC_INTEL_SOF_CML_RT1011_RT5682_MACH
          Say Y if you have such a device.
          If unsure select "N".
 
-endif ## SND_SOC_SOF_COMETLAKE_LP && SND_SOC_SOF_HDA_LINK
+endif ## SND_SOC_SOF_COMETLAKE && SND_SOC_SOF_HDA_LINK
 
 if SND_SOC_SOF_JASPERLAKE
 
index 5f96d7a..bed4d5f 100644 (file)
@@ -354,6 +354,7 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = {
        {
                .name = "Codec DSP",
                .stream_name = "Wake on Voice",
+               .capture_only = 1,
                .ops = &bdw_rt5677_dsp_ops,
                SND_SOC_DAILINK_REG(dsp),
        },
index 9e5fc94..ecbc58e 100644 (file)
@@ -543,8 +543,10 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
 
        if (cnt) {
                ret = device_add_properties(codec_dev, props);
-               if (ret)
+               if (ret) {
+                       put_device(codec_dev);
                        return ret;
+               }
        }
 
        devm_acpi_dev_add_driver_gpios(codec_dev, byt_cht_es8316_gpios);
index 7a43c70..22e4327 100644 (file)
@@ -253,21 +253,20 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
        params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
 
        /*
-        * Default mode for SSP configuration is TDM 4 slot
+        * Default mode for SSP configuration is TDM 4 slot. One board/design,
+        * the Lenovo Miix 2 10 uses not 1 but 2 codecs connected to SSP2. The
+        * second piggy-backed, output-only codec is inside the keyboard-dock
+        * (which has extra speakers). Unlike the main rt5672 codec, we cannot
+        * configure this codec, it is hard coded to use 2 channel 24 bit I2S.
+        * Since we only support 2 channels anyways, there is no need for TDM
+        * on any cht-bsw-rt5672 designs. So we simply use I2S 2ch everywhere.
         */
-       ret = snd_soc_dai_set_fmt(asoc_rtd_to_codec(rtd, 0),
-                                 SND_SOC_DAIFMT_DSP_B |
-                                 SND_SOC_DAIFMT_IB_NF |
+       ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0),
+                                 SND_SOC_DAIFMT_I2S     |
+                                 SND_SOC_DAIFMT_NB_NF   |
                                  SND_SOC_DAIFMT_CBS_CFS);
        if (ret < 0) {
-               dev_err(rtd->dev, "can't set format to TDM %d\n", ret);
-               return ret;
-       }
-
-       /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */
-       ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 0), 0xF, 0xF, 4, 24);
-       if (ret < 0) {
-               dev_err(rtd->dev, "can't set codec TDM slot %d\n", ret);
+               dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
                return ret;
        }
 
index f51b28d..92f51d0 100644 (file)
@@ -72,7 +72,7 @@ config SND_SOC_QDSP6_ASM_DAI
 
 config SND_SOC_QDSP6
        tristate "SoC ALSA audio driver for QDSP6"
-       depends on QCOM_APR && HAS_DMA
+       depends on QCOM_APR
        select SND_SOC_QDSP6_COMMON
        select SND_SOC_QDSP6_CORE
        select SND_SOC_QDSP6_AFE
index 6c20bdd..8ada4ec 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <linux/module.h>
 #include "common.h"
+#include "qdsp6/q6afe.h"
 
 int qcom_snd_parse_of(struct snd_soc_card *card)
 {
@@ -101,6 +102,15 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
                        }
                        link->no_pcm = 1;
                        link->ignore_pmdown_time = 1;
+
+                       if (q6afe_is_rx_port(link->id)) {
+                               link->dpcm_playback = 1;
+                               link->dpcm_capture = 0;
+                       } else {
+                               link->dpcm_playback = 0;
+                               link->dpcm_capture = 1;
+                       }
+
                } else {
                        dlc = devm_kzalloc(dev, sizeof(*dlc), GFP_KERNEL);
                        if (!dlc)
@@ -113,12 +123,12 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
                        link->codecs->dai_name = "snd-soc-dummy-dai";
                        link->codecs->name = "snd-soc-dummy";
                        link->dynamic = 1;
+                       link->dpcm_playback = 1;
+                       link->dpcm_capture = 1;
                }
 
                link->ignore_suspend = 1;
                link->nonatomic = 1;
-               link->dpcm_playback = 1;
-               link->dpcm_capture = 1;
                link->stream_name = link->name;
                link++;
 
index e0945f7..0ce4eb6 100644 (file)
@@ -800,6 +800,14 @@ int q6afe_get_port_id(int index)
 }
 EXPORT_SYMBOL_GPL(q6afe_get_port_id);
 
+int q6afe_is_rx_port(int index)
+{
+       if (index < 0 || index >= AFE_PORT_MAX)
+               return -EINVAL;
+
+       return port_maps[index].is_rx;
+}
+EXPORT_SYMBOL_GPL(q6afe_is_rx_port);
 static int afe_apr_send_pkt(struct q6afe *afe, struct apr_pkt *pkt,
                            struct q6afe_port *port)
 {
index c7ed542..1a0f80a 100644 (file)
@@ -198,6 +198,7 @@ int q6afe_port_start(struct q6afe_port *port);
 int q6afe_port_stop(struct q6afe_port *port);
 void q6afe_port_put(struct q6afe_port *port);
 int q6afe_get_port_id(int index);
+int q6afe_is_rx_port(int index);
 void q6afe_hdmi_port_prepare(struct q6afe_port *port,
                            struct q6afe_hdmi_cfg *cfg);
 void q6afe_slim_port_prepare(struct q6afe_port *port,
index 0e0e8f7..ae4b2ca 100644 (file)
@@ -25,6 +25,7 @@
 #define ASM_STREAM_CMD_FLUSH                   0x00010BCE
 #define ASM_SESSION_CMD_PAUSE                  0x00010BD3
 #define ASM_DATA_CMD_EOS                       0x00010BDB
+#define ASM_DATA_EVENT_RENDERED_EOS            0x00010C1C
 #define ASM_NULL_POPP_TOPOLOGY                 0x00010C68
 #define ASM_STREAM_CMD_FLUSH_READBUFS          0x00010C09
 #define ASM_STREAM_CMD_SET_ENCDEC_PARAM                0x00010C10
@@ -622,9 +623,6 @@ static int32_t q6asm_stream_callback(struct apr_device *adev,
                case ASM_SESSION_CMD_SUSPEND:
                        client_event = ASM_CLIENT_EVENT_CMD_SUSPEND_DONE;
                        break;
-               case ASM_DATA_CMD_EOS:
-                       client_event = ASM_CLIENT_EVENT_CMD_EOS_DONE;
-                       break;
                case ASM_STREAM_CMD_FLUSH:
                        client_event = ASM_CLIENT_EVENT_CMD_FLUSH_DONE;
                        break;
@@ -727,6 +725,9 @@ static int32_t q6asm_stream_callback(struct apr_device *adev,
                        spin_unlock_irqrestore(&ac->lock, flags);
                }
 
+               break;
+       case ASM_DATA_EVENT_RENDERED_EOS:
+               client_event = ASM_CLIENT_EVENT_CMD_EOS_DONE;
                break;
        }
 
index f45e5aa..9539b0d 100644 (file)
@@ -219,19 +219,32 @@ static int rockchip_sound_dmic_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
+static int rockchip_sound_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+       return snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE,
+                       8000, 96000);
+}
+
 static const struct snd_soc_ops rockchip_sound_max98357a_ops = {
+       .startup = rockchip_sound_startup,
        .hw_params = rockchip_sound_max98357a_hw_params,
 };
 
 static const struct snd_soc_ops rockchip_sound_rt5514_ops = {
+       .startup = rockchip_sound_startup,
        .hw_params = rockchip_sound_rt5514_hw_params,
 };
 
 static const struct snd_soc_ops rockchip_sound_da7219_ops = {
+       .startup = rockchip_sound_startup,
        .hw_params = rockchip_sound_da7219_hw_params,
 };
 
 static const struct snd_soc_ops rockchip_sound_dmic_ops = {
+       .startup = rockchip_sound_startup,
        .hw_params = rockchip_sound_dmic_hw_params,
 };
 
index 7cd42fc..1707414 100644 (file)
@@ -590,8 +590,10 @@ static int rockchip_pdm_resume(struct device *dev)
        int ret;
 
        ret = pm_runtime_get_sync(dev);
-       if (ret < 0)
+       if (ret < 0) {
+               pm_runtime_put(dev);
                return ret;
+       }
 
        ret = regcache_sync(pdm->regmap);
 
index 7b38720..2b8abf8 100644 (file)
@@ -310,7 +310,7 @@ struct snd_soc_component *snd_soc_rtdcom_lookup(struct snd_soc_pcm_runtime *rtd,
 }
 EXPORT_SYMBOL_GPL(snd_soc_rtdcom_lookup);
 
-static struct snd_soc_component
+struct snd_soc_component
 *snd_soc_lookup_component_nolocked(struct device *dev, const char *driver_name)
 {
        struct snd_soc_component *component;
@@ -329,6 +329,7 @@ static struct snd_soc_component
 
        return found_component;
 }
+EXPORT_SYMBOL_GPL(snd_soc_lookup_component_nolocked);
 
 struct snd_soc_component *snd_soc_lookup_component(struct device *dev,
                                                   const char *driver_name)
@@ -2571,6 +2572,33 @@ int snd_soc_register_component(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(snd_soc_register_component);
 
+/**
+ * snd_soc_unregister_component_by_driver - Unregister component using a given driver
+ * from the ASoC core
+ *
+ * @dev: The device to unregister
+ * @component_driver: The component driver to unregister
+ */
+void snd_soc_unregister_component_by_driver(struct device *dev,
+                                           const struct snd_soc_component_driver *component_driver)
+{
+       struct snd_soc_component *component;
+
+       if (!component_driver)
+               return;
+
+       mutex_lock(&client_mutex);
+       component = snd_soc_lookup_component_nolocked(dev, component_driver->name);
+       if (!component)
+               goto out;
+
+       snd_soc_del_component_unlocked(component);
+
+out:
+       mutex_unlock(&client_mutex);
+}
+EXPORT_SYMBOL_GPL(snd_soc_unregister_component_by_driver);
+
 /**
  * snd_soc_unregister_component - Unregister all related component
  * from the ASoC core
index b05e18b..4571599 100644 (file)
@@ -391,6 +391,44 @@ bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir)
        return stream->channels_min;
 }
 
+/*
+ * snd_soc_dai_link_set_capabilities() - set dai_link properties based on its DAIs
+ */
+void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link)
+{
+       struct snd_soc_dai_link_component *cpu;
+       struct snd_soc_dai_link_component *codec;
+       struct snd_soc_dai *dai;
+       bool supported[SNDRV_PCM_STREAM_LAST + 1];
+       int direction;
+       int i;
+
+       for_each_pcm_streams(direction) {
+               supported[direction] = true;
+
+               for_each_link_cpus(dai_link, i, cpu) {
+                       dai = snd_soc_find_dai(cpu);
+                       if (!dai || !snd_soc_dai_stream_valid(dai, direction)) {
+                               supported[direction] = false;
+                               break;
+                       }
+               }
+               if (!supported[direction])
+                       continue;
+               for_each_link_codecs(dai_link, i, codec) {
+                       dai = snd_soc_find_dai(codec);
+                       if (!dai || !snd_soc_dai_stream_valid(dai, direction)) {
+                               supported[direction] = false;
+                               break;
+                       }
+               }
+       }
+
+       dai_link->dpcm_playback = supported[SNDRV_PCM_STREAM_PLAYBACK];
+       dai_link->dpcm_capture  = supported[SNDRV_PCM_STREAM_CAPTURE];
+}
+EXPORT_SYMBOL_GPL(snd_soc_dai_link_set_capabilities);
+
 void snd_soc_dai_action(struct snd_soc_dai *dai,
                        int stream, int action)
 {
index a9ea172..4534a1c 100644 (file)
@@ -9,9 +9,48 @@
 #include <sound/soc.h>
 #include <sound/dmaengine_pcm.h>
 
+static void devm_dai_release(struct device *dev, void *res)
+{
+       snd_soc_unregister_dai(*(struct snd_soc_dai **)res);
+}
+
+/**
+ * devm_snd_soc_register_dai - resource-managed dai registration
+ * @dev: Device used to manage component
+ * @component: The component the DAIs are registered for
+ * @dai_drv: DAI driver to use for the DAI
+ * @legacy_dai_naming: if %true, use legacy single-name format;
+ *     if %false, use multiple-name format;
+ */
+struct snd_soc_dai *devm_snd_soc_register_dai(struct device *dev,
+                                             struct snd_soc_component *component,
+                                             struct snd_soc_dai_driver *dai_drv,
+                                             bool legacy_dai_naming)
+{
+       struct snd_soc_dai **ptr;
+       struct snd_soc_dai *dai;
+
+       ptr = devres_alloc(devm_dai_release, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return NULL;
+
+       dai = snd_soc_register_dai(component, dai_drv, legacy_dai_naming);
+       if (dai) {
+               *ptr = dai;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+
+       return dai;
+}
+EXPORT_SYMBOL_GPL(devm_snd_soc_register_dai);
+
 static void devm_component_release(struct device *dev, void *res)
 {
-       snd_soc_unregister_component(*(struct device **)res);
+       const struct snd_soc_component_driver **cmpnt_drv = res;
+
+       snd_soc_unregister_component_by_driver(dev, *cmpnt_drv);
 }
 
 /**
@@ -28,7 +67,7 @@ int devm_snd_soc_register_component(struct device *dev,
                         const struct snd_soc_component_driver *cmpnt_drv,
                         struct snd_soc_dai_driver *dai_drv, int num_dai)
 {
-       struct device **ptr;
+       const struct snd_soc_component_driver **ptr;
        int ret;
 
        ptr = devres_alloc(devm_component_release, sizeof(*ptr), GFP_KERNEL);
@@ -37,7 +76,7 @@ int devm_snd_soc_register_component(struct device *dev,
 
        ret = snd_soc_register_component(dev, cmpnt_drv, dai_drv, num_dai);
        if (ret == 0) {
-               *ptr = dev;
+               *ptr = cmpnt_drv;
                devres_add(dev, ptr);
        } else {
                devres_free(ptr);
index f728309..6184440 100644 (file)
  */
 #define SND_DMAENGINE_PCM_FLAG_NO_RESIDUE BIT(31)
 
-struct dmaengine_pcm {
-       struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1];
-       const struct snd_dmaengine_pcm_config *config;
-       struct snd_soc_component component;
-       unsigned int flags;
-};
-
-static struct dmaengine_pcm *soc_component_to_pcm(struct snd_soc_component *p)
-{
-       return container_of(p, struct dmaengine_pcm, component);
-}
-
 static struct device *dmaengine_dma_dev(struct dmaengine_pcm *pcm,
        struct snd_pcm_substream *substream)
 {
@@ -490,7 +478,7 @@ void snd_dmaengine_pcm_unregister(struct device *dev)
 
        pcm = soc_component_to_pcm(component);
 
-       snd_soc_unregister_component(dev);
+       snd_soc_unregister_component_by_driver(dev, component->driver);
        dmaengine_pcm_release_chan(pcm);
        kfree(pcm);
 }
index 2c114b4..c517064 100644 (file)
@@ -2630,15 +2630,15 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new)
        int count, paths;
        int ret;
 
+       if (!fe->dai_link->dynamic)
+               return 0;
+
        if (fe->num_cpus > 1) {
                dev_err(fe->dev,
                        "%s doesn't support Multi CPU yet\n", __func__);
                return -EINVAL;
        }
 
-       if (!fe->dai_link->dynamic)
-               return 0;
-
        /* only check active links */
        if (!snd_soc_dai_active(asoc_rtd_to_cpu(fe, 0)))
                return 0;
index 9e89633..6eaa00c 100644 (file)
@@ -1261,17 +1261,29 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg,
                list_add(&routes[i]->dobj.list, &tplg->comp->dobj_list);
 
                ret = soc_tplg_add_route(tplg, routes[i]);
-               if (ret < 0)
+               if (ret < 0) {
+                       /*
+                        * this route was added to the list, it will
+                        * be freed in remove_route() so increment the
+                        * counter to skip it in the error handling
+                        * below.
+                        */
+                       i++;
                        break;
+               }
 
                /* add route, but keep going if some fail */
                snd_soc_dapm_add_routes(dapm, routes[i], 1);
        }
 
-       /* free memory allocated for all dapm routes in case of error */
-       if (ret < 0)
-               for (i = 0; i < count ; i++)
-                       kfree(routes[i]);
+       /*
+        * free memory allocated for all dapm routes not added to the
+        * list in case of error
+        */
+       if (ret < 0) {
+               while (i < count)
+                       kfree(routes[i++]);
+       }
 
        /*
         * free pointer to array of dapm routes as this is no longer needed.
@@ -1359,7 +1371,6 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create(
                if (err < 0) {
                        dev_err(tplg->dev, "ASoC: failed to init %s\n",
                                mc->hdr.name);
-                       soc_tplg_free_tlv(tplg, &kc[i]);
                        goto err_sm;
                }
        }
@@ -1367,6 +1378,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create(
 
 err_sm:
        for (; i >= 0; i--) {
+               soc_tplg_free_tlv(tplg, &kc[i]);
                sm = (struct soc_mixer_control *)kc[i].private_value;
                kfree(sm);
                kfree(kc[i].name);
@@ -1851,7 +1863,7 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
        list_add(&dai_drv->dobj.list, &tplg->comp->dobj_list);
 
        /* register the DAI to the component */
-       dai = snd_soc_register_dai(tplg->comp, dai_drv, false);
+       dai = devm_snd_soc_register_dai(tplg->comp->dev, tplg->comp, dai_drv, false);
        if (!dai)
                return -ENOMEM;
 
@@ -1859,7 +1871,6 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
        ret = snd_soc_dapm_new_dai_widgets(dapm, dai);
        if (ret != 0) {
                dev_err(dai->dev, "Failed to create DAI widgets %d\n", ret);
-               snd_soc_unregister_dai(dai);
                return ret;
        }
 
index 339c493..adc7c37 100644 (file)
@@ -345,15 +345,15 @@ int snd_sof_device_remove(struct device *dev)
        struct snd_sof_pdata *pdata = sdev->pdata;
        int ret;
 
-       ret = snd_sof_dsp_power_down_notify(sdev);
-       if (ret < 0)
-               dev_warn(dev, "error: %d failed to prepare DSP for device removal",
-                        ret);
-
        if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE))
                cancel_work_sync(&sdev->probe_work);
 
        if (sdev->fw_state > SOF_FW_BOOT_NOT_STARTED) {
+               ret = snd_sof_dsp_power_down_notify(sdev);
+               if (ret < 0)
+                       dev_warn(dev, "error: %d failed to prepare DSP for device removal",
+                                ret);
+
                snd_sof_fw_unload(sdev);
                snd_sof_ipc_free(sdev);
                snd_sof_free_debug(sdev);
index 63f9c20..a4fa845 100644 (file)
@@ -375,6 +375,14 @@ static int imx8_ipc_pcm_params(struct snd_sof_dev *sdev,
 static struct snd_soc_dai_driver imx8_dai[] = {
 {
        .name = "esai-port",
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
 },
 };
 
index fa86a9e..287114a 100644 (file)
@@ -240,6 +240,14 @@ static int imx8m_ipc_pcm_params(struct snd_sof_dev *sdev,
 static struct snd_soc_dai_driver imx8m_dai[] = {
 {
        .name = "sai-port",
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 32,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 32,
+       },
 },
 };
 
index c9a2bee..3aaf25e 100644 (file)
@@ -25,8 +25,7 @@ config SND_SOC_SOF_INTEL_PCI
        select SND_SOC_SOF_CANNONLAKE  if SND_SOC_SOF_CANNONLAKE_SUPPORT
        select SND_SOC_SOF_COFFEELAKE  if SND_SOC_SOF_COFFEELAKE_SUPPORT
        select SND_SOC_SOF_ICELAKE     if SND_SOC_SOF_ICELAKE_SUPPORT
-       select SND_SOC_SOF_COMETLAKE_LP if SND_SOC_SOF_COMETLAKE_LP_SUPPORT
-       select SND_SOC_SOF_COMETLAKE_H if SND_SOC_SOF_COMETLAKE_H_SUPPORT
+       select SND_SOC_SOF_COMETLAKE   if SND_SOC_SOF_COMETLAKE_SUPPORT
        select SND_SOC_SOF_TIGERLAKE   if SND_SOC_SOF_TIGERLAKE_SUPPORT
        select SND_SOC_SOF_ELKHARTLAKE if SND_SOC_SOF_ELKHARTLAKE_SUPPORT
        select SND_SOC_SOF_JASPERLAKE  if SND_SOC_SOF_JASPERLAKE_SUPPORT
@@ -201,34 +200,22 @@ config SND_SOC_SOF_ICELAKE
          This option is not user-selectable but automagically handled by
          'select' statements at a higher level
 
-config SND_SOC_SOF_COMETLAKE_LP
+config SND_SOC_SOF_COMETLAKE
        tristate
        select SND_SOC_SOF_HDA_COMMON
        help
          This option is not user-selectable but automagically handled by
          'select' statements at a higher level
 
-config SND_SOC_SOF_COMETLAKE_LP_SUPPORT
-       bool "SOF support for CometLake-LP"
-       help
-         This adds support for Sound Open Firmware for Intel(R) platforms
-         using the Cometlake-LP processors.
-         Say Y if you have such a device.
-         If unsure select "N".
+config SND_SOC_SOF_COMETLAKE_SUPPORT
+       bool
 
-config SND_SOC_SOF_COMETLAKE_H
-       tristate
-       select SND_SOC_SOF_HDA_COMMON
-       help
-         This option is not user-selectable but automagically handled by
-         'select' statements at a higher level
-
-config SND_SOC_SOF_COMETLAKE_H_SUPPORT
-       bool "SOF support for CometLake-H"
+config SND_SOC_SOF_COMETLAKE_LP_SUPPORT
+       bool "SOF support for CometLake"
+       select SND_SOC_SOF_COMETLAKE_SUPPORT
        help
          This adds support for Sound Open Firmware for Intel(R) platforms
-         using the Cometlake-H processors.
-         Say Y if you have such a device.
+         using the Cometlake processors.
          If unsure select "N".
 
 config SND_SOC_SOF_TIGERLAKE_SUPPORT
index 7f65dcc..1bda14c 100644 (file)
@@ -653,11 +653,16 @@ irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context)
                if (status & AZX_INT_CTRL_EN) {
                        rirb_status = snd_hdac_chip_readb(bus, RIRBSTS);
                        if (rirb_status & RIRB_INT_MASK) {
+                               /*
+                                * Clearing the interrupt status here ensures
+                                * that no interrupt gets masked after the RIRB
+                                * wp is read in snd_hdac_bus_update_rirb.
+                                */
+                               snd_hdac_chip_writeb(bus, RIRBSTS,
+                                                    RIRB_INT_MASK);
                                active = true;
                                if (rirb_status & RIRB_INT_RESPONSE)
                                        snd_hdac_bus_update_rirb(bus);
-                               snd_hdac_chip_writeb(bus, RIRBSTS,
-                                                    RIRB_INT_MASK);
                        }
                }
 #endif
index b04b728..5e159ab 100644 (file)
@@ -36,7 +36,7 @@ struct sof_probe_point_desc {
 struct sof_ipc_probe_dma_add_params {
        struct sof_ipc_cmd_hdr hdr;
        unsigned int num_elems;
-       struct sof_probe_dma dma[0];
+       struct sof_probe_dma dma[];
 } __packed;
 
 struct sof_ipc_probe_info_params {
@@ -51,19 +51,19 @@ struct sof_ipc_probe_info_params {
 struct sof_ipc_probe_dma_remove_params {
        struct sof_ipc_cmd_hdr hdr;
        unsigned int num_elems;
-       unsigned int stream_tag[0];
+       unsigned int stream_tag[];
 } __packed;
 
 struct sof_ipc_probe_point_add_params {
        struct sof_ipc_cmd_hdr hdr;
        unsigned int num_elems;
-       struct sof_probe_point_desc desc[0];
+       struct sof_probe_point_desc desc[];
 } __packed;
 
 struct sof_ipc_probe_point_remove_params {
        struct sof_ipc_cmd_hdr hdr;
        unsigned int num_elems;
-       unsigned int buffer_id[0];
+       unsigned int buffer_id[];
 } __packed;
 
 int sof_ipc_probe_init(struct snd_sof_dev *sdev,
index b13697d..aa3532b 100644 (file)
@@ -151,9 +151,7 @@ static const struct sof_dev_desc cfl_desc = {
 };
 #endif
 
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP) || \
-       IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H)
-
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE)
 static const struct sof_dev_desc cml_desc = {
        .machines               = snd_soc_acpi_intel_cml_machines,
        .alt_machines           = snd_soc_acpi_intel_cml_sdw_machines,
@@ -411,8 +409,11 @@ static const struct pci_device_id sof_pci_ids[] = {
                .driver_data = (unsigned long)&cfl_desc},
 #endif
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE)
-       { PCI_DEVICE(0x8086, 0x34C8),
+       { PCI_DEVICE(0x8086, 0x34C8), /* ICL-LP */
+               .driver_data = (unsigned long)&icl_desc},
+       { PCI_DEVICE(0x8086, 0x3dc8), /* ICL-H */
                .driver_data = (unsigned long)&icl_desc},
+
 #endif
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE)
        { PCI_DEVICE(0x8086, 0x38c8),
@@ -420,17 +421,20 @@ static const struct pci_device_id sof_pci_ids[] = {
        { PCI_DEVICE(0x8086, 0x4dc8),
                .driver_data = (unsigned long)&jsl_desc},
 #endif
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP)
-       { PCI_DEVICE(0x8086, 0x02c8),
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE)
+       { PCI_DEVICE(0x8086, 0x02c8), /* CML-LP */
                .driver_data = (unsigned long)&cml_desc},
-#endif
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H)
-       { PCI_DEVICE(0x8086, 0x06c8),
+       { PCI_DEVICE(0x8086, 0x06c8), /* CML-H */
+               .driver_data = (unsigned long)&cml_desc},
+       { PCI_DEVICE(0x8086, 0xa3f0), /* CML-S */
                .driver_data = (unsigned long)&cml_desc},
 #endif
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE)
-       { PCI_DEVICE(0x8086, 0xa0c8),
+       { PCI_DEVICE(0x8086, 0xa0c8), /* TGL-LP */
+               .driver_data = (unsigned long)&tgl_desc},
+       { PCI_DEVICE(0x8086, 0x43c8), /* TGL-H */
                .driver_data = (unsigned long)&tgl_desc},
+
 #endif
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE)
        { PCI_DEVICE(0x8086, 0x4b55),
index d6219fb..de43267 100644 (file)
@@ -84,10 +84,10 @@ struct snd_usb_endpoint {
        dma_addr_t sync_dma;            /* DMA address of syncbuf */
 
        unsigned int pipe;              /* the data i/o pipe */
-       unsigned int framesize[2];      /* small/large frame sizes in samples */
-       unsigned int sample_rem;        /* remainder from division fs/fps */
+       unsigned int packsize[2];       /* small/large packet sizes in samples */
+       unsigned int sample_rem;        /* remainder from division fs/pps */
        unsigned int sample_accum;      /* sample accumulator */
-       unsigned int fps;               /* frames per second */
+       unsigned int pps;               /* packets per second */
        unsigned int freqn;             /* nominal sampling rate in fs/fps in Q16.16 format */
        unsigned int freqm;             /* momentary sampling rate in fs/fps in Q16.16 format */
        int        freqshift;           /* how much to shift the feedback value to get Q16.16 */
index 9bea7d3..8876026 100644 (file)
@@ -159,11 +159,11 @@ int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep)
                return ep->maxframesize;
 
        ep->sample_accum += ep->sample_rem;
-       if (ep->sample_accum >= ep->fps) {
-               ep->sample_accum -= ep->fps;
-               ret = ep->framesize[1];
+       if (ep->sample_accum >= ep->pps) {
+               ep->sample_accum -= ep->pps;
+               ret = ep->packsize[1];
        } else {
-               ret = ep->framesize[0];
+               ret = ep->packsize[0];
        }
 
        return ret;
@@ -1088,15 +1088,15 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
 
        if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_FULL) {
                ep->freqn = get_usb_full_speed_rate(rate);
-               ep->fps = 1000;
+               ep->pps = 1000 >> ep->datainterval;
        } else {
                ep->freqn = get_usb_high_speed_rate(rate);
-               ep->fps = 8000;
+               ep->pps = 8000 >> ep->datainterval;
        }
 
-       ep->sample_rem = rate % ep->fps;
-       ep->framesize[0] = rate / ep->fps;
-       ep->framesize[1] = (rate + (ep->fps - 1)) / ep->fps;
+       ep->sample_rem = rate % ep->pps;
+       ep->packsize[0] = rate / ep->pps;
+       ep->packsize[1] = (rate + (ep->pps - 1)) / ep->pps;
 
        /* calculate the frequency in 16.16 format */
        ep->freqm = ep->freqn;
index 5ffb457..1b28d01 100644 (file)
@@ -394,8 +394,9 @@ skip_rate:
        return nr_rates;
 }
 
-/* Line6 Helix series don't support the UAC2_CS_RANGE usb function
- * call. Return a static table of known clock rates.
+/* Line6 Helix series and the Rode Rodecaster Pro don't support the
+ * UAC2_CS_RANGE usb function call. Return a static table of known
+ * clock rates.
  */
 static int line6_parse_audio_format_rates_quirk(struct snd_usb_audio *chip,
                                                struct audioformat *fp)
@@ -408,6 +409,7 @@ static int line6_parse_audio_format_rates_quirk(struct snd_usb_audio *chip,
        case USB_ID(0x0e41, 0x4248): /* Line6 Helix >= fw 2.82 */
        case USB_ID(0x0e41, 0x4249): /* Line6 Helix Rack >= fw 2.82 */
        case USB_ID(0x0e41, 0x424a): /* Line6 Helix LT >= fw 2.82 */
+       case USB_ID(0x19f7, 0x0011): /* Rode Rodecaster Pro */
                return set_fixed_rate(fp, 48000, SNDRV_PCM_RATE_48000);
        }
 
index 663d608..970c9bd 100644 (file)
@@ -286,6 +286,8 @@ int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm)
                urb->interval = LINE6_ISO_INTERVAL;
                urb->error_count = 0;
                urb->complete = audio_in_callback;
+               if (usb_urb_ep_type_check(urb))
+                       return -EINVAL;
        }
 
        return 0;
index 7629116..2746d96 100644 (file)
@@ -840,7 +840,7 @@ void line6_disconnect(struct usb_interface *interface)
        if (WARN_ON(usbdev != line6->usbdev))
                return;
 
-       cancel_delayed_work(&line6->startup_work);
+       cancel_delayed_work_sync(&line6->startup_work);
 
        if (line6->urb_listen != NULL)
                line6_stop_listen(line6);
index 01930ce..8233c61 100644 (file)
@@ -431,6 +431,8 @@ int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm)
                urb->interval = LINE6_ISO_INTERVAL;
                urb->error_count = 0;
                urb->complete = audio_out_callback;
+               if (usb_urb_ep_type_check(urb))
+                       return -EINVAL;
        }
 
        return 0;
index 047b905..354f576 100644 (file)
@@ -1499,6 +1499,8 @@ void snd_usbmidi_disconnect(struct list_head *p)
        spin_unlock_irq(&umidi->disc_lock);
        up_write(&umidi->disc_rwsem);
 
+       del_timer_sync(&umidi->error_timer);
+
        for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
                struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i];
                if (ep->out)
@@ -1525,7 +1527,6 @@ void snd_usbmidi_disconnect(struct list_head *p)
                        ep->in = NULL;
                }
        }
-       del_timer_sync(&umidi->error_timer);
 }
 EXPORT_SYMBOL(snd_usbmidi_disconnect);
 
@@ -2301,16 +2302,22 @@ void snd_usbmidi_input_stop(struct list_head *p)
 }
 EXPORT_SYMBOL(snd_usbmidi_input_stop);
 
-static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint *ep)
+static void snd_usbmidi_input_start_ep(struct snd_usb_midi *umidi,
+                                      struct snd_usb_midi_in_endpoint *ep)
 {
        unsigned int i;
+       unsigned long flags;
 
        if (!ep)
                return;
        for (i = 0; i < INPUT_URBS; ++i) {
                struct urb *urb = ep->urbs[i];
-               urb->dev = ep->umidi->dev;
-               snd_usbmidi_submit_urb(urb, GFP_KERNEL);
+               spin_lock_irqsave(&umidi->disc_lock, flags);
+               if (!atomic_read(&urb->use_count)) {
+                       urb->dev = ep->umidi->dev;
+                       snd_usbmidi_submit_urb(urb, GFP_ATOMIC);
+               }
+               spin_unlock_irqrestore(&umidi->disc_lock, flags);
        }
 }
 
@@ -2326,7 +2333,7 @@ void snd_usbmidi_input_start(struct list_head *p)
        if (umidi->input_running || !umidi->opened[1])
                return;
        for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
-               snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
+               snd_usbmidi_input_start_ep(umidi, umidi->endpoints[i].in);
        umidi->input_running = 1;
 }
 EXPORT_SYMBOL(snd_usbmidi_input_start);
index 15769f2..eab0fd4 100644 (file)
@@ -581,8 +581,9 @@ static int check_matrix_bitmap(unsigned char *bmap,
  * if failed, give up and free the control instance.
  */
 
-int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list,
-                             struct snd_kcontrol *kctl)
+int snd_usb_mixer_add_list(struct usb_mixer_elem_list *list,
+                          struct snd_kcontrol *kctl,
+                          bool is_std_info)
 {
        struct usb_mixer_interface *mixer = list->mixer;
        int err;
@@ -596,6 +597,7 @@ int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list,
                return err;
        }
        list->kctl = kctl;
+       list->is_std_info = is_std_info;
        list->next_id_elem = mixer->id_elems[list->id];
        mixer->id_elems[list->id] = list;
        return 0;
@@ -3234,8 +3236,11 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid)
        unitid = delegate_notify(mixer, unitid, NULL, NULL);
 
        for_each_mixer_elem(list, mixer, unitid) {
-               struct usb_mixer_elem_info *info =
-                       mixer_elem_list_to_info(list);
+               struct usb_mixer_elem_info *info;
+
+               if (!list->is_std_info)
+                       continue;
+               info = mixer_elem_list_to_info(list);
                /* invalidate cache, so the value is read from the device */
                info->cached = 0;
                snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
@@ -3315,6 +3320,8 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
 
                if (!list->kctl)
                        continue;
+               if (!list->is_std_info)
+                       continue;
 
                info = mixer_elem_list_to_info(list);
                if (count > 1 && info->control != control)
index 41ec9dc..c29e27a 100644 (file)
@@ -66,6 +66,7 @@ struct usb_mixer_elem_list {
        struct usb_mixer_elem_list *next_id_elem; /* list of controls with same id */
        struct snd_kcontrol *kctl;
        unsigned int id;
+       bool is_std_info;
        usb_mixer_elem_dump_func_t dump;
        usb_mixer_elem_resume_func_t resume;
 };
@@ -103,8 +104,12 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid);
 int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
                                int request, int validx, int value_set);
 
-int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list,
-                             struct snd_kcontrol *kctl);
+int snd_usb_mixer_add_list(struct usb_mixer_elem_list *list,
+                          struct snd_kcontrol *kctl,
+                          bool is_std_info);
+
+#define snd_usb_mixer_add_control(list, kctl) \
+       snd_usb_mixer_add_list(list, kctl, true)
 
 void snd_usb_mixer_elem_init_std(struct usb_mixer_elem_list *list,
                                 struct usb_mixer_interface *mixer,
index b6bcf2f..cec1cfd 100644 (file)
@@ -158,7 +158,8 @@ static int add_single_ctl_with_resume(struct usb_mixer_interface *mixer,
                return -ENOMEM;
        }
        kctl->private_free = snd_usb_mixer_elem_free;
-       return snd_usb_mixer_add_control(list, kctl);
+       /* don't use snd_usb_mixer_add_control() here, this is a special list element */
+       return snd_usb_mixer_add_list(list, kctl, false);
 }
 
 /*
index 8a05dcb..a69d9e7 100644 (file)
@@ -367,6 +367,9 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
                ifnum = 0;
                goto add_sync_ep_from_ifnum;
        case USB_ID(0x07fd, 0x0008): /* MOTU M Series */
+       case USB_ID(0x31e9, 0x0001): /* Solid State Logic SSL2 */
+       case USB_ID(0x31e9, 0x0002): /* Solid State Logic SSL2+ */
+       case USB_ID(0x0d9a, 0x00df): /* RTX6001 */
                ep = 0x81;
                ifnum = 2;
                goto add_sync_ep_from_ifnum;
@@ -1786,6 +1789,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
                return 0;
        case SNDRV_PCM_TRIGGER_STOP:
                stop_endpoints(subs);
+               subs->data_endpoint->retire_data_urb = NULL;
                subs->running = 0;
                return 0;
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
index 4ec4910..9092cc0 100644 (file)
@@ -3633,4 +3633,56 @@ ALC1220_VB_DESKTOP(0x26ce, 0x0a01), /* Asrock TRX40 Creator */
        }
 },
 
+/*
+ * MacroSilicon MS2109 based HDMI capture cards
+ *
+ * These claim 96kHz 1ch in the descriptors, but are actually 48kHz 2ch.
+ * They also need QUIRK_AUDIO_ALIGN_TRANSFER, which makes one wonder if
+ * they pretend to be 96kHz mono as a workaround for stereo being broken
+ * by that...
+ *
+ * They also have swapped L-R channels, but that's for userspace to deal
+ * with.
+ */
+{
+       USB_DEVICE(0x534d, 0x2109),
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               .vendor_name = "MacroSilicon",
+               .product_name = "MS2109",
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = &(const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_ALIGN_TRANSFER,
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_STANDARD_MIXER,
+                       },
+                       {
+                               .ifnum = 3,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                                       .channels = 2,
+                                       .iface = 3,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .attributes = 0,
+                                       .endpoint = 0x82,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC |
+                                               USB_ENDPOINT_SYNC_ASYNC,
+                                       .rates = SNDRV_PCM_RATE_CONTINUOUS,
+                                       .rate_min = 48000,
+                                       .rate_max = 48000,
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
+
 #undef USB_DEVICE_VENDOR_SPEC
index bca0179..fca7273 100644 (file)
@@ -1532,6 +1532,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
 static bool is_itf_usb_dsd_dac(unsigned int id)
 {
        switch (id) {
+       case USB_ID(0x154e, 0x1002): /* Denon DCD-1500RE */
        case USB_ID(0x154e, 0x1003): /* Denon DA-300USB */
        case USB_ID(0x154e, 0x3005): /* Marantz HD-DAC1 */
        case USB_ID(0x154e, 0x3006): /* Marantz SA-14S1 */
@@ -1673,6 +1674,14 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
             chip->usb_id == USB_ID(0x0951, 0x16ad)) &&
            (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
                usleep_range(1000, 2000);
+
+       /*
+        * Samsung USBC Headset (AKG) need a tiny delay after each
+        * class compliant request. (Model number: AAM625R or AAM627R)
+        */
+       if (chip->usb_id == USB_ID(0x04e8, 0xa051) &&
+           (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
+               usleep_range(5000, 6000);
 }
 
 /*
@@ -1856,6 +1865,7 @@ struct registration_quirk {
 static const struct registration_quirk registration_quirks[] = {
        REG_QUIRK_ENTRY(0x0951, 0x16d8, 2),     /* Kingston HyperX AMP */
        REG_QUIRK_ENTRY(0x0951, 0x16ed, 2),     /* Kingston HyperX Cloud Alpha S */
+       REG_QUIRK_ENTRY(0x0951, 0x16ea, 2),     /* Kingston HyperX Cloud Flight S */
        { 0 }                                   /* terminator */
 };
 
index db18994..02dabc9 100644 (file)
 #define X86_FEATURE_AVX512_4FMAPS      (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */
 #define X86_FEATURE_FSRM               (18*32+ 4) /* Fast Short Rep Mov */
 #define X86_FEATURE_AVX512_VP2INTERSECT (18*32+ 8) /* AVX-512 Intersect for D/Q */
+#define X86_FEATURE_SRBDS_CTRL         (18*32+ 9) /* "" SRBDS mitigation MSR available */
 #define X86_FEATURE_MD_CLEAR           (18*32+10) /* VERW clears CPU buffers */
 #define X86_FEATURE_TSX_FORCE_ABORT    (18*32+13) /* "" TSX_FORCE_ABORT */
 #define X86_FEATURE_PCONFIG            (18*32+18) /* Intel PCONFIG */
 #define X86_BUG_SWAPGS                 X86_BUG(21) /* CPU is affected by speculation through SWAPGS */
 #define X86_BUG_TAA                    X86_BUG(22) /* CPU is affected by TSX Async Abort(TAA) */
 #define X86_BUG_ITLB_MULTIHIT          X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */
+#define X86_BUG_SRBDS                  X86_BUG(24) /* CPU may leak RNG bits if not mitigated */
 
 #endif /* _ASM_X86_CPUFEATURES_H */
index ef452b8..e8370e6 100644 (file)
 #define TSX_CTRL_RTM_DISABLE           BIT(0)  /* Disable RTM feature */
 #define TSX_CTRL_CPUID_CLEAR           BIT(1)  /* Disable TSX enumeration */
 
+/* SRBDS support */
+#define MSR_IA32_MCU_OPT_CTRL          0x00000123
+#define RNGDS_MITG_DIS                 BIT(0)
+
 #define MSR_IA32_SYSENTER_CS           0x00000174
 #define MSR_IA32_SYSENTER_ESP          0x00000175
 #define MSR_IA32_SYSENTER_EIP          0x00000176
index 43e2490..0780f97 100644 (file)
@@ -385,22 +385,26 @@ struct kvm_sync_regs {
 #define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT (1 << 4)
 
 #define KVM_STATE_NESTED_FORMAT_VMX    0
-#define KVM_STATE_NESTED_FORMAT_SVM    1       /* unused */
+#define KVM_STATE_NESTED_FORMAT_SVM    1
 
 #define KVM_STATE_NESTED_GUEST_MODE    0x00000001
 #define KVM_STATE_NESTED_RUN_PENDING   0x00000002
 #define KVM_STATE_NESTED_EVMCS         0x00000004
 #define KVM_STATE_NESTED_MTF_PENDING   0x00000008
+#define KVM_STATE_NESTED_GIF_SET       0x00000100
 
 #define KVM_STATE_NESTED_SMM_GUEST_MODE        0x00000001
 #define KVM_STATE_NESTED_SMM_VMXON     0x00000002
 
 #define KVM_STATE_NESTED_VMX_VMCS_SIZE 0x1000
 
+#define KVM_STATE_NESTED_SVM_VMCB_SIZE 0x1000
+
+#define KVM_STATE_VMX_PREEMPTION_TIMER_DEADLINE        0x00000001
+
 struct kvm_vmx_nested_state_data {
        __u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
        __u8 shadow_vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
-       __u64 preemption_timer_deadline;
 };
 
 struct kvm_vmx_nested_state_hdr {
@@ -410,6 +414,18 @@ struct kvm_vmx_nested_state_hdr {
        struct {
                __u16 flags;
        } smm;
+
+       __u32 flags;
+       __u64 preemption_timer_deadline;
+};
+
+struct kvm_svm_nested_state_data {
+       /* Save area only used if KVM_STATE_NESTED_RUN_PENDING.  */
+       __u8 vmcb12[KVM_STATE_NESTED_SVM_VMCB_SIZE];
+};
+
+struct kvm_svm_nested_state_hdr {
+       __u64 vmcb_pa;
 };
 
 /* for KVM_CAP_NESTED_STATE */
@@ -420,6 +436,7 @@ struct kvm_nested_state {
 
        union {
                struct kvm_vmx_nested_state_hdr vmx;
+               struct kvm_svm_nested_state_hdr svm;
 
                /* Pad the header to 128 bytes.  */
                __u8 pad[120];
@@ -432,6 +449,7 @@ struct kvm_nested_state {
         */
        union {
                struct kvm_vmx_nested_state_data vmx[0];
+               struct kvm_svm_nested_state_data svm[0];
        } data;
 };
 
index 30d7d04..be5e2e7 100644 (file)
@@ -2,7 +2,14 @@
 #ifndef _UAPI_ASM_X86_UNISTD_H
 #define _UAPI_ASM_X86_UNISTD_H
 
-/* x32 syscall flag bit */
+/*
+ * x32 syscall flag bit.  Some user programs expect syscall NR macros
+ * and __X32_SYSCALL_BIT to have type int, even though syscall numbers
+ * are, for practical purposes, unsigned long.
+ *
+ * Fortunately, expressions like (nr & ~__X32_SYSCALL_BIT) do the right
+ * thing regardless.
+ */
 #define __X32_SYSCALL_BIT      0x40000000
 
 #ifndef __KERNEL__
index e95b72e..b8ff9e8 100644 (file)
        { EXIT_REASON_UMWAIT,                "UMWAIT" }, \
        { EXIT_REASON_TPAUSE,                "TPAUSE" }
 
+#define VMX_EXIT_REASON_FLAGS \
+       { VMX_EXIT_REASONS_FAILED_VMENTRY,      "FAILED_VMENTRY" }
+
 #define VMX_ABORT_SAVE_GUEST_MSR_FAIL        1
 #define VMX_ABORT_LOAD_HOST_PDPTE_FAIL       2
 #define VMX_ABORT_LOAD_HOST_MSR_FAIL         4
index df767af..45f8e1b 100644 (file)
@@ -8,6 +8,8 @@
 #include <asm/alternative-asm.h>
 #include <asm/export.h>
 
+.pushsection .noinstr.text, "ax"
+
 /*
  * We build a jump to memcpy_orig by default which gets NOPped out on
  * the majority of x86 CPUs which set REP_GOOD. In addition, CPUs which
@@ -184,6 +186,8 @@ SYM_FUNC_START(memcpy_orig)
        retq
 SYM_FUNC_END(memcpy_orig)
 
+.popsection
+
 #ifndef CONFIG_UML
 
 MCSAFE_TEST_CTL
index 0efaf45..e0878f5 100644 (file)
 #include <linux/kernel.h>
 #include <linux/bootconfig.h>
 
-static int xbc_show_array(struct xbc_node *node)
+static int xbc_show_value(struct xbc_node *node)
 {
        const char *val;
+       char q;
        int i = 0;
 
        xbc_array_for_each_value(node, val) {
-               printf("\"%s\"%s", val, node->next ? ", " : ";\n");
+               if (strchr(val, '"'))
+                       q = '\'';
+               else
+                       q = '"';
+               printf("%c%s%c%s", q, val, q, node->next ? ", " : ";\n");
                i++;
        }
        return i;
@@ -48,10 +53,7 @@ static void xbc_show_compact_tree(void)
                        continue;
                } else if (cnode && xbc_node_is_value(cnode)) {
                        printf("%s = ", xbc_node_get_data(node));
-                       if (cnode->next)
-                               xbc_show_array(cnode);
-                       else
-                               printf("\"%s\";\n", xbc_node_get_data(cnode));
+                       xbc_show_value(cnode);
                } else {
                        printf("%s;\n", xbc_node_get_data(node));
                }
@@ -205,11 +207,13 @@ int show_xbc(const char *path)
        }
 
        ret = load_xbc_from_initrd(fd, &buf);
-       if (ret < 0)
+       if (ret < 0) {
                pr_err("Failed to load a boot config from initrd: %d\n", ret);
-       else
-               xbc_show_compact_tree();
-
+               goto out;
+       }
+       xbc_show_compact_tree();
+       ret = 0;
+out:
        close(fd);
        free(buf);
 
index eff16b7..3c2ab9e 100755 (executable)
@@ -55,6 +55,9 @@ echo "Apply command test"
 xpass $BOOTCONF -a $TEMPCONF $INITRD
 new_size=$(stat -c %s $INITRD)
 
+echo "Show command test"
+xpass $BOOTCONF $INITRD
+
 echo "File size check"
 xpass test $new_size -eq $(expr $bconf_size + $initrd_size + 9 + 12)
 
@@ -114,6 +117,13 @@ xpass grep -q "bar" $OUTFILE
 xpass grep -q "baz" $OUTFILE
 xpass grep -q "qux" $OUTFILE
 
+echo "Double/single quotes test"
+echo "key = '\"string\"';" > $TEMPCONF
+$BOOTCONF -a $TEMPCONF $INITRD
+$BOOTCONF $INITRD > $TEMPCONF
+cat $TEMPCONF
+xpass grep \'\"string\"\' $TEMPCONF
+
 echo "=== expected failure cases ==="
 for i in samples/bad-* ; do
   xfail $BOOTCONF -a $i $INITRD
index 3110164..70c78fa 100644 (file)
@@ -49,7 +49,7 @@ MAP COMMANDS
 |              | **lru_percpu_hash** | **lpm_trie** | **array_of_maps** | **hash_of_maps**
 |              | **devmap** | **devmap_hash** | **sockmap** | **cpumap** | **xskmap** | **sockhash**
 |              | **cgroup_storage** | **reuseport_sockarray** | **percpu_cgroup_storage**
-|              | **queue** | **stack** | **sk_storage** | **struct_ops** }
+|              | **queue** | **stack** | **sk_storage** | **struct_ops** | **ringbuf** }
 
 DESCRIPTION
 ===========
index c5fac80..1d3b606 100644 (file)
@@ -49,6 +49,7 @@ const char * const map_type_name[] = {
        [BPF_MAP_TYPE_STACK]                    = "stack",
        [BPF_MAP_TYPE_SK_STORAGE]               = "sk_storage",
        [BPF_MAP_TYPE_STRUCT_OPS]               = "struct_ops",
+       [BPF_MAP_TYPE_RINGBUF]                  = "ringbuf",
 };
 
 const size_t map_type_name_size = ARRAY_SIZE(map_type_name);
@@ -1590,7 +1591,7 @@ static int do_help(int argc, char **argv)
                "                 lru_percpu_hash | lpm_trie | array_of_maps | hash_of_maps |\n"
                "                 devmap | devmap_hash | sockmap | cpumap | xskmap | sockhash |\n"
                "                 cgroup_storage | reuseport_sockarray | percpu_cgroup_storage |\n"
-               "                 queue | stack | sk_storage | struct_ops }\n"
+               "                 queue | stack | sk_storage | struct_ops | ringbuf }\n"
                "       " HELP_SPEC_OPTIONS "\n"
                "",
                bin_name, argv[-2]);
index 4671fbf..7f475d5 100644 (file)
@@ -18,8 +18,7 @@
  * position @h. For example
  * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.
  */
-#if !defined(__ASSEMBLY__) && \
-       (!defined(CONFIG_CC_IS_GCC) || CONFIG_GCC_VERSION >= 49000)
+#if !defined(__ASSEMBLY__)
 #include <linux/build_bug.h>
 #define GENMASK_INPUT_CHECK(h, l) \
        (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
index 3a3201e..f4a0130 100644 (file)
@@ -855,9 +855,11 @@ __SYSCALL(__NR_clone3, sys_clone3)
 __SYSCALL(__NR_openat2, sys_openat2)
 #define __NR_pidfd_getfd 438
 __SYSCALL(__NR_pidfd_getfd, sys_pidfd_getfd)
+#define __NR_faccessat2 439
+__SYSCALL(__NR_faccessat2, sys_faccessat2)
 
 #undef __NR_syscalls
-#define __NR_syscalls 439
+#define __NR_syscalls 440
 
 /*
  * 32 bit systems traditionally used different
index 2813e57..14b67cd 100644 (file)
@@ -1969,6 +1969,30 @@ enum drm_i915_perf_property_id {
         */
        DRM_I915_PERF_PROP_HOLD_PREEMPTION,
 
+       /**
+        * Specifying this pins all contexts to the specified SSEU power
+        * configuration for the duration of the recording.
+        *
+        * This parameter's value is a pointer to a struct
+        * drm_i915_gem_context_param_sseu.
+        *
+        * This property is available in perf revision 4.
+        */
+       DRM_I915_PERF_PROP_GLOBAL_SSEU,
+
+       /**
+        * This optional parameter specifies the timer interval in nanoseconds
+        * at which the i915 driver will check the OA buffer for available data.
+        * Minimum allowed value is 100 microseconds. A default value is used by
+        * the driver if this parameter is not specified. Note that larger timer
+        * values will reduce cpu consumption during OA perf captures. However,
+        * excessively large values would potentially result in OA buffer
+        * overwrites as captures reach end of the OA buffer.
+        *
+        * This property is available in perf revision 5.
+        */
+       DRM_I915_PERF_PROP_POLL_OA_PERIOD,
+
        DRM_I915_PERF_PROP_MAX /* non-ABI */
 };
 
index 1968481..8bd3305 100644 (file)
@@ -3168,16 +3168,15 @@ union bpf_attr {
  *     Return
  *             The id is returned or 0 in case the id could not be retrieved.
  *
- * void *bpf_ringbuf_output(void *ringbuf, void *data, u64 size, u64 flags)
+ * int bpf_ringbuf_output(void *ringbuf, void *data, u64 size, u64 flags)
  *     Description
  *             Copy *size* bytes from *data* into a ring buffer *ringbuf*.
- *             If BPF_RB_NO_WAKEUP is specified in *flags*, no notification of
- *             new data availability is sent.
- *             IF BPF_RB_FORCE_WAKEUP is specified in *flags*, notification of
- *             new data availability is sent unconditionally.
+ *             If **BPF_RB_NO_WAKEUP** is specified in *flags*, no notification
+ *             of new data availability is sent.
+ *             If **BPF_RB_FORCE_WAKEUP** is specified in *flags*, notification
+ *             of new data availability is sent unconditionally.
  *     Return
- *             0, on success;
- *             < 0, on error.
+ *             0 on success, or a negative error in case of failure.
  *
  * void *bpf_ringbuf_reserve(void *ringbuf, u64 size, u64 flags)
  *     Description
@@ -3189,20 +3188,20 @@ union bpf_attr {
  * void bpf_ringbuf_submit(void *data, u64 flags)
  *     Description
  *             Submit reserved ring buffer sample, pointed to by *data*.
- *             If BPF_RB_NO_WAKEUP is specified in *flags*, no notification of
- *             new data availability is sent.
- *             IF BPF_RB_FORCE_WAKEUP is specified in *flags*, notification of
- *             new data availability is sent unconditionally.
+ *             If **BPF_RB_NO_WAKEUP** is specified in *flags*, no notification
+ *             of new data availability is sent.
+ *             If **BPF_RB_FORCE_WAKEUP** is specified in *flags*, notification
+ *             of new data availability is sent unconditionally.
  *     Return
  *             Nothing. Always succeeds.
  *
  * void bpf_ringbuf_discard(void *data, u64 flags)
  *     Description
  *             Discard reserved ring buffer sample, pointed to by *data*.
- *             If BPF_RB_NO_WAKEUP is specified in *flags*, no notification of
- *             new data availability is sent.
- *             IF BPF_RB_FORCE_WAKEUP is specified in *flags*, notification of
- *             new data availability is sent unconditionally.
+ *             If **BPF_RB_NO_WAKEUP** is specified in *flags*, no notification
+ *             of new data availability is sent.
+ *             If **BPF_RB_FORCE_WAKEUP** is specified in *flags*, notification
+ *             of new data availability is sent unconditionally.
  *     Return
  *             Nothing. Always succeeds.
  *
@@ -3210,16 +3209,18 @@ union bpf_attr {
  *     Description
  *             Query various characteristics of provided ring buffer. What
  *             exactly is queries is determined by *flags*:
- *               - BPF_RB_AVAIL_DATA - amount of data not yet consumed;
- *               - BPF_RB_RING_SIZE - the size of ring buffer;
- *               - BPF_RB_CONS_POS - consumer position (can wrap around);
- *               - BPF_RB_PROD_POS - producer(s) position (can wrap around);
- *             Data returned is just a momentary snapshots of actual values
+ *
+ *             * **BPF_RB_AVAIL_DATA**: Amount of data not yet consumed.
+ *             * **BPF_RB_RING_SIZE**: The size of ring buffer.
+ *             * **BPF_RB_CONS_POS**: Consumer position (can wrap around).
+ *             * **BPF_RB_PROD_POS**: Producer(s) position (can wrap around).
+ *
+ *             Data returned is just a momentary snapshot of actual values
  *             and could be inaccurate, so this facility should be used to
  *             power heuristics and for reporting, not to make 100% correct
  *             calculation.
  *     Return
- *             Requested value, or 0, if flags are not recognized.
+ *             Requested value, or 0, if *flags* are not recognized.
  *
  * int bpf_csum_level(struct sk_buff *skb, u64 level)
  *     Description
index ca88b7b..2f86b2a 100644 (file)
 #define DN_ATTRIB      0x00000020      /* File changed attibutes */
 #define DN_MULTISHOT   0x80000000      /* Don't remove notifier */
 
+/*
+ * The constants AT_REMOVEDIR and AT_EACCESS have the same value.  AT_EACCESS is
+ * meaningful only to faccessat, while AT_REMOVEDIR is meaningful only to
+ * unlinkat.  The two functions do completely different things and therefore,
+ * the flags can be allowed to overlap.  For example, passing AT_REMOVEDIR to
+ * faccessat would be undefined behavior and thus treating it equivalent to
+ * AT_EACCESS is valid undefined behavior.
+ */
 #define AT_FDCWD               -100    /* Special value used to indicate
                                            openat should use the current
                                            working directory. */
 #define AT_SYMLINK_NOFOLLOW    0x100   /* Do not follow symbolic links.  */
+#define AT_EACCESS             0x200   /* Test access permitted for
+                                           effective IDs, not real IDs.  */
 #define AT_REMOVEDIR           0x200   /* Remove directory instead of
                                            unlinking file.  */
 #define AT_SYMLINK_FOLLOW      0x400   /* Follow symbolic links.  */
index 379a612..f44eb0a 100644 (file)
@@ -262,6 +262,7 @@ struct fsxattr {
 #define FS_EA_INODE_FL                 0x00200000 /* Inode used for large EA */
 #define FS_EOFBLOCKS_FL                        0x00400000 /* Reserved for ext4 */
 #define FS_NOCOW_FL                    0x00800000 /* Do not cow file */
+#define FS_DAX_FL                      0x02000000 /* Inode is DAX */
 #define FS_INLINE_DATA_FL              0x10000000 /* Reserved for ext4 */
 #define FS_PROJINHERIT_FL              0x20000000 /* Create with parents projid */
 #define FS_CASEFOLD_FL                 0x40000000 /* Folder is case insensitive */
index a10e3cd..7875709 100644 (file)
@@ -19,7 +19,8 @@
 #define FSCRYPT_POLICY_FLAGS_PAD_MASK          0x03
 #define FSCRYPT_POLICY_FLAG_DIRECT_KEY         0x04
 #define FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64     0x08
-#define FSCRYPT_POLICY_FLAGS_VALID             0x0F
+#define FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32     0x10
+#define FSCRYPT_POLICY_FLAGS_VALID             0x1F
 
 /* Encryption algorithms */
 #define FSCRYPT_MODE_AES_256_XTS               1
index fdd632c..4fdf303 100644 (file)
@@ -188,10 +188,13 @@ struct kvm_s390_cmma_log {
 struct kvm_hyperv_exit {
 #define KVM_EXIT_HYPERV_SYNIC          1
 #define KVM_EXIT_HYPERV_HCALL          2
+#define KVM_EXIT_HYPERV_SYNDBG         3
        __u32 type;
+       __u32 pad1;
        union {
                struct {
                        __u32 msr;
+                       __u32 pad2;
                        __u64 control;
                        __u64 evt_page;
                        __u64 msg_page;
@@ -201,6 +204,15 @@ struct kvm_hyperv_exit {
                        __u64 result;
                        __u64 params[2];
                } hcall;
+               struct {
+                       __u32 msr;
+                       __u32 pad2;
+                       __u64 control;
+                       __u64 status;
+                       __u64 send_page;
+                       __u64 recv_page;
+                       __u64 pending_page;
+               } syndbg;
        } u;
 };
 
@@ -1017,6 +1029,8 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_S390_VCPU_RESETS 179
 #define KVM_CAP_S390_PROTECTED 180
 #define KVM_CAP_PPC_SECURE_GUEST 181
+#define KVM_CAP_HALT_POLL 182
+#define KVM_CAP_ASYNC_PF_INT 183
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
index d119278..82cc58f 100644 (file)
@@ -123,7 +123,10 @@ struct statx {
        __u32   stx_dev_major;  /* ID of device containing file [uncond] */
        __u32   stx_dev_minor;
        /* 0x90 */
-       __u64   __spare2[14];   /* Spare space for future expansion */
+       __u64   stx_mnt_id;
+       __u64   __spare2;
+       /* 0xa0 */
+       __u64   __spare3[12];   /* Spare space for future expansion */
        /* 0x100 */
 };
 
@@ -148,6 +151,7 @@ struct statx {
 #define STATX_BLOCKS           0x00000400U     /* Want/got stx_blocks */
 #define STATX_BASIC_STATS      0x000007ffU     /* The stuff in the normal stat struct */
 #define STATX_BTIME            0x00000800U     /* Want/got stx_btime */
+#define STATX_MNT_ID           0x00001000U     /* Got stx_mnt_id */
 
 #define STATX__RESERVED                0x80000000U     /* Reserved for future struct statx expansion */
 
@@ -177,7 +181,9 @@ struct statx {
 #define STATX_ATTR_NODUMP              0x00000040 /* [I] File is not to be dumped */
 #define STATX_ATTR_ENCRYPTED           0x00000800 /* [I] File requires key to decrypt in fs */
 #define STATX_ATTR_AUTOMOUNT           0x00001000 /* Dir: Automount trigger */
+#define STATX_ATTR_MOUNT_ROOT          0x00002000 /* Root of a mount */
 #define STATX_ATTR_VERITY              0x00100000 /* [I] Verity protected file */
+#define STATX_ATTR_DAX                 0x00002000 /* [I] File is DAX */
 
 
 #endif /* _UAPI_LINUX_STAT_H */
index 9fe72e4..0c23496 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/types.h>
 #include <linux/ioctl.h>
 
+#define VHOST_FILE_UNBIND -1
+
 /* ioctls */
 
 #define VHOST_VIRTIO 0xAF
 /* Get the max ring size. */
 #define VHOST_VDPA_GET_VRING_NUM       _IOR(VHOST_VIRTIO, 0x76, __u16)
 
+/* Set event fd for config interrupt*/
+#define VHOST_VDPA_SET_CONFIG_CALL     _IOW(VHOST_VIRTIO, 0x77, int)
 #endif
index 1b6015b..dbef24e 100644 (file)
@@ -233,6 +233,8 @@ LIBBPF_API int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf,
 LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf,
                                 __u32 *buf_len, __u32 *prog_id, __u32 *fd_type,
                                 __u64 *probe_offset, __u64 *probe_addr);
+
+enum bpf_stats_type; /* defined in up-to-date linux/bpf.h */
 LIBBPF_API int bpf_enable_stats(enum bpf_stats_type type);
 
 #ifdef __cplusplus
index df59fd4..e0af36b 100644 (file)
 #include <stdbool.h>
 #include <stddef.h>
 #include <limits.h>
-#ifndef __WORDSIZE
-#define __WORDSIZE (__SIZEOF_LONG__ * 8)
-#endif
 
 static inline size_t hash_bits(size_t h, int bits)
 {
        /* shuffle bits and return requested number of upper bits */
-       return (h * 11400714819323198485llu) >> (__WORDSIZE - bits);
+#if (__SIZEOF_SIZE_T__ == __SIZEOF_LONG_LONG__)
+       /* LP64 case */
+       return (h * 11400714819323198485llu) >> (__SIZEOF_LONG_LONG__ * 8 - bits);
+#elif (__SIZEOF_SIZE_T__ <= __SIZEOF_LONG__)
+       return (h * 2654435769lu) >> (__SIZEOF_LONG__ * 8 - bits);
+#else
+#      error "Unsupported size_t size"
+#endif
 }
 
 typedef size_t (*hashmap_hash_fn)(const void *key, void *ctx);
index 477c679..11e4725 100644 (file)
@@ -4818,7 +4818,13 @@ bpf_core_reloc_fields(struct bpf_object *obj, const char *targ_btf_path)
                        err = -EINVAL;
                        goto out;
                }
-               prog = bpf_object__find_program_by_title(obj, sec_name);
+               prog = NULL;
+               for (i = 0; i < obj->nr_programs; i++) {
+                       if (!strcmp(obj->programs[i].section_name, sec_name)) {
+                               prog = &obj->programs[i];
+                               break;
+                       }
+               }
                if (!prog) {
                        pr_warn("failed to find program '%s' for CO-RE offset relocation\n",
                                sec_name);
@@ -6653,7 +6659,7 @@ static const struct bpf_sec_def section_defs[] = {
                .expected_attach_type = BPF_TRACE_ITER,
                .is_attach_btf = true,
                .attach_fn = attach_iter),
-       BPF_EAPROG_SEC("xdp_devmap",            BPF_PROG_TYPE_XDP,
+       BPF_EAPROG_SEC("xdp_devmap/",           BPF_PROG_TYPE_XDP,
                                                BPF_XDP_DEVMAP),
        BPF_PROG_SEC("xdp",                     BPF_PROG_TYPE_XDP),
        BPF_PROG_SEC("perf_event",              BPF_PROG_TYPE_PERF_EVENT),
index dbb9efb..39ebf61 100644 (file)
@@ -237,6 +237,9 @@ static int get_value(struct parse_opt_ctx_t *p,
                return err;
 
        case OPTION_CALLBACK:
+               if (opt->set)
+                       *(bool *)opt->set = true;
+
                if (unset)
                        return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
                if (opt->flags & PARSE_OPT_NOARG)
index e1bd2a9..5b36c58 100644 (file)
@@ -1425,13 +1425,28 @@ static unsigned int type_size(const char *name)
        return 0;
 }
 
+static int append(char **buf, const char *delim, const char *str)
+{
+       char *new_buf;
+
+       new_buf = realloc(*buf, strlen(*buf) + strlen(delim) + strlen(str) + 1);
+       if (!new_buf)
+               return -1;
+       strcat(new_buf, delim);
+       strcat(new_buf, str);
+       *buf = new_buf;
+       return 0;
+}
+
 static int event_read_fields(struct tep_event *event, struct tep_format_field **fields)
 {
        struct tep_format_field *field = NULL;
        enum tep_event_type type;
        char *token;
        char *last_token;
+       char *delim = " ";
        int count = 0;
+       int ret;
 
        do {
                unsigned int size_dynamic = 0;
@@ -1490,24 +1505,51 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field **
                                        field->flags |= TEP_FIELD_IS_POINTER;
 
                                if (field->type) {
-                                       char *new_type;
-                                       new_type = realloc(field->type,
-                                                          strlen(field->type) +
-                                                          strlen(last_token) + 2);
-                                       if (!new_type) {
-                                               free(last_token);
-                                               goto fail;
-                                       }
-                                       field->type = new_type;
-                                       strcat(field->type, " ");
-                                       strcat(field->type, last_token);
+                                       ret = append(&field->type, delim, last_token);
                                        free(last_token);
+                                       if (ret < 0)
+                                               goto fail;
                                } else
                                        field->type = last_token;
                                last_token = token;
+                               delim = " ";
                                continue;
                        }
 
+                       /* Handle __attribute__((user)) */
+                       if ((type == TEP_EVENT_DELIM) &&
+                           strcmp("__attribute__", last_token) == 0 &&
+                           token[0] == '(') {
+                               int depth = 1;
+                               int ret;
+
+                               ret = append(&field->type, " ", last_token);
+                               ret |= append(&field->type, "", "(");
+                               if (ret < 0)
+                                       goto fail;
+
+                               delim = " ";
+                               while ((type = read_token(&token)) != TEP_EVENT_NONE) {
+                                       if (type == TEP_EVENT_DELIM) {
+                                               if (token[0] == '(')
+                                                       depth++;
+                                               else if (token[0] == ')')
+                                                       depth--;
+                                               if (!depth)
+                                                       break;
+                                               ret = append(&field->type, "", token);
+                                               delim = "";
+                                       } else {
+                                               ret = append(&field->type, delim, token);
+                                               delim = " ";
+                                       }
+                                       if (ret < 0)
+                                               goto fail;
+                                       free(last_token);
+                                       last_token = token;
+                               }
+                               continue;
+                       }
                        break;
                }
 
@@ -1523,8 +1565,6 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field **
                if (strcmp(token, "[") == 0) {
                        enum tep_event_type last_type = type;
                        char *brackets = token;
-                       char *new_brackets;
-                       int len;
 
                        field->flags |= TEP_FIELD_IS_ARRAY;
 
@@ -1536,29 +1576,27 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field **
                                field->arraylen = 0;
 
                        while (strcmp(token, "]") != 0) {
+                               const char *delim;
+
                                if (last_type == TEP_EVENT_ITEM &&
                                    type == TEP_EVENT_ITEM)
-                                       len = 2;
+                                       delim = " ";
                                else
-                                       len = 1;
+                                       delim = "";
+
                                last_type = type;
 
-                               new_brackets = realloc(brackets,
-                                                      strlen(brackets) +
-                                                      strlen(token) + len);
-                               if (!new_brackets) {
+                               ret = append(&brackets, delim, token);
+                               if (ret < 0) {
                                        free(brackets);
                                        goto fail;
                                }
-                               brackets = new_brackets;
-                               if (len == 2)
-                                       strcat(brackets, " ");
-                               strcat(brackets, token);
                                /* We only care about the last token */
                                field->arraylen = strtoul(token, NULL, 0);
                                free_token(token);
                                type = read_token(&token);
                                if (type == TEP_EVENT_NONE) {
+                                       free(brackets);
                                        do_warning_event(event, "failed to find token");
                                        goto fail;
                                }
@@ -1566,13 +1604,11 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field **
 
                        free_token(token);
 
-                       new_brackets = realloc(brackets, strlen(brackets) + 2);
-                       if (!new_brackets) {
+                       ret = append(&brackets, "", "]");
+                       if (ret < 0) {
                                free(brackets);
                                goto fail;
                        }
-                       brackets = new_brackets;
-                       strcat(brackets, "]");
 
                        /* add brackets to type */
 
@@ -1582,34 +1618,23 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field **
                         * the format: type [] item;
                         */
                        if (type == TEP_EVENT_ITEM) {
-                               char *new_type;
-                               new_type = realloc(field->type,
-                                                  strlen(field->type) +
-                                                  strlen(field->name) +
-                                                  strlen(brackets) + 2);
-                               if (!new_type) {
+                               ret = append(&field->type, " ", field->name);
+                               if (ret < 0) {
                                        free(brackets);
                                        goto fail;
                                }
-                               field->type = new_type;
-                               strcat(field->type, " ");
-                               strcat(field->type, field->name);
+                               ret = append(&field->type, "", brackets);
+
                                size_dynamic = type_size(field->name);
                                free_token(field->name);
-                               strcat(field->type, brackets);
                                field->name = field->alias = token;
                                type = read_token(&token);
                        } else {
-                               char *new_type;
-                               new_type = realloc(field->type,
-                                                  strlen(field->type) +
-                                                  strlen(brackets) + 1);
-                               if (!new_type) {
+                               ret = append(&field->type, "", brackets);
+                               if (ret < 0) {
                                        free(brackets);
                                        goto fail;
                                }
-                               field->type = new_type;
-                               strcat(field->type, brackets);
                        }
                        free(brackets);
                }
@@ -2046,19 +2071,16 @@ process_op(struct tep_event *event, struct tep_print_arg *arg, char **tok)
                /* could just be a type pointer */
                if ((strcmp(arg->op.op, "*") == 0) &&
                    type == TEP_EVENT_DELIM && (strcmp(token, ")") == 0)) {
-                       char *new_atom;
+                       int ret;
 
                        if (left->type != TEP_PRINT_ATOM) {
                                do_warning_event(event, "bad pointer type");
                                goto out_free;
                        }
-                       new_atom = realloc(left->atom.atom,
-                                           strlen(left->atom.atom) + 3);
-                       if (!new_atom)
+                       ret = append(&left->atom.atom, " ", "*");
+                       if (ret < 0)
                                goto out_warn_free;
 
-                       left->atom.atom = new_atom;
-                       strcat(left->atom.atom, " *");
                        free(arg->op.op);
                        *arg = *left;
                        free(left);
@@ -3062,6 +3084,37 @@ err:
        return TEP_EVENT_ERROR;
 }
 
+static enum tep_event_type
+process_builtin_expect(struct tep_event *event, struct tep_print_arg *arg, char **tok)
+{
+       enum tep_event_type type;
+       char *token = NULL;
+
+       /* Handle __builtin_expect( cond, #) */
+       type = process_arg(event, arg, &token);
+
+       if (type != TEP_EVENT_DELIM || token[0] != ',')
+               goto out_free;
+
+       free_token(token);
+
+       /* We don't care what the second parameter is of the __builtin_expect() */
+       if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
+               goto out_free;
+
+       if (read_expected(TEP_EVENT_DELIM, ")") < 0)
+               goto out_free;
+
+       free_token(token);
+       type = read_token_item(tok);
+       return type;
+
+out_free:
+       free_token(token);
+       *tok = NULL;
+       return TEP_EVENT_ERROR;
+}
+
 static enum tep_event_type
 process_function(struct tep_event *event, struct tep_print_arg *arg,
                 char *token, char **tok)
@@ -3106,6 +3159,10 @@ process_function(struct tep_event *event, struct tep_print_arg *arg,
                free_token(token);
                return process_dynamic_array_len(event, arg, tok);
        }
+       if (strcmp(token, "__builtin_expect") == 0) {
+               free_token(token);
+               return process_builtin_expect(event, arg, tok);
+       }
 
        func = find_func_handler(event->tep, token);
        if (func) {
@@ -3151,18 +3208,15 @@ process_arg_token(struct tep_event *event, struct tep_print_arg *arg,
                }
                /* atoms can be more than one token long */
                while (type == TEP_EVENT_ITEM) {
-                       char *new_atom;
-                       new_atom = realloc(atom,
-                                          strlen(atom) + strlen(token) + 2);
-                       if (!new_atom) {
+                       int ret;
+
+                       ret = append(&atom, " ", token);
+                       if (ret < 0) {
                                free(atom);
                                *tok = NULL;
                                free_token(token);
                                return TEP_EVENT_ERROR;
                        }
-                       atom = new_atom;
-                       strcat(atom, " ");
-                       strcat(atom, token);
                        free_token(token);
                        type = read_token_item(&token);
                }
index 27f3b07..f1640d6 100644 (file)
@@ -361,6 +361,7 @@ translate_data(struct kbuffer *kbuf, void *data, void **rptr,
                break;
 
        case KBUFFER_TYPE_TIME_EXTEND:
+       case KBUFFER_TYPE_TIME_STAMP:
                extend = read_4(kbuf, data);
                data += 4;
                extend <<= TS_SHIFT;
@@ -369,10 +370,6 @@ translate_data(struct kbuffer *kbuf, void *data, void **rptr,
                *length = 0;
                break;
 
-       case KBUFFER_TYPE_TIME_STAMP:
-               data += 12;
-               *length = 0;
-               break;
        case 0:
                *length = read_4(kbuf, data) - 4;
                *length = (*length + 3) & ~3;
@@ -397,7 +394,11 @@ static unsigned int update_pointers(struct kbuffer *kbuf)
 
        type_len = translate_data(kbuf, ptr, &ptr, &delta, &length);
 
-       kbuf->timestamp += delta;
+       if (type_len == KBUFFER_TYPE_TIME_STAMP)
+               kbuf->timestamp = delta;
+       else
+               kbuf->timestamp += delta;
+
        kbuf->index = calc_index(kbuf, ptr);
        kbuf->next = kbuf->index + length;
 
@@ -454,7 +455,9 @@ static int __next_event(struct kbuffer *kbuf)
                if (kbuf->next >= kbuf->size)
                        return -1;
                type = update_pointers(kbuf);
-       } while (type == KBUFFER_TYPE_TIME_EXTEND || type == KBUFFER_TYPE_PADDING);
+       } while (type == KBUFFER_TYPE_TIME_EXTEND ||
+                type == KBUFFER_TYPE_TIME_STAMP ||
+                type == KBUFFER_TYPE_PADDING);
 
        return 0;
 }
@@ -546,6 +549,34 @@ int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer)
        return 0;
 }
 
+/**
+ * kbuffer_subbuf_timestamp - read the timestamp from a sub buffer
+ * @kbuf:      The kbuffer to load
+ * @subbuf:    The subbuffer to read from.
+ *
+ * Return the timestamp from a subbuffer.
+ */
+unsigned long long kbuffer_subbuf_timestamp(struct kbuffer *kbuf, void *subbuf)
+{
+       return kbuf->read_8(subbuf);
+}
+
+/**
+ * kbuffer_ptr_delta - read the delta field from a record
+ * @kbuf:      The kbuffer to load
+ * @ptr:       The record in the buffe.
+ *
+ * Return the timestamp delta from a record
+ */
+unsigned int kbuffer_ptr_delta(struct kbuffer *kbuf, void *ptr)
+{
+       unsigned int type_len_ts;
+
+       type_len_ts = read_4(kbuf, ptr);
+       return ts4host(kbuf, type_len_ts);
+}
+
+
 /**
  * kbuffer_read_event - read the next event in the kbuffer subbuffer
  * @kbuf:      The kbuffer to read from
index ed4d697..5fa8292 100644 (file)
@@ -49,6 +49,8 @@ int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer);
 void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts);
 void *kbuffer_next_event(struct kbuffer *kbuf, unsigned long long *ts);
 unsigned long long kbuffer_timestamp(struct kbuffer *kbuf);
+unsigned long long kbuffer_subbuf_timestamp(struct kbuffer *kbuf, void *subbuf);
+unsigned int kbuffer_ptr_delta(struct kbuffer *kbuf, void *ptr);
 
 void *kbuffer_translate_data(int swap, void *data, unsigned int *size);
 
index eda15a5..3c59677 100644 (file)
@@ -84,4 +84,6 @@ unsigned long arch_jump_destination(struct instruction *insn);
 
 unsigned long arch_dest_rela_offset(int addend);
 
+const char *arch_nop_insn(int len);
+
 #endif /* _ARCH_H */
index 4b504fc..9872195 100644 (file)
@@ -565,3 +565,21 @@ void arch_initial_func_cfi_state(struct cfi_init_state *state)
        state->regs[16].base = CFI_CFA;
        state->regs[16].offset = -8;
 }
+
+const char *arch_nop_insn(int len)
+{
+       static const char nops[5][5] = {
+               /* 1 */ { 0x90 },
+               /* 2 */ { 0x66, 0x90 },
+               /* 3 */ { 0x0f, 0x1f, 0x00 },
+               /* 4 */ { 0x0f, 0x1f, 0x40, 0x00 },
+               /* 5 */ { 0x0f, 0x1f, 0x44, 0x00, 0x00 },
+       };
+
+       if (len < 1 || len > 5) {
+               WARN("invalid NOP size: %d\n", len);
+               return NULL;
+       }
+
+       return nops[len-1];
+}
diff --git a/tools/objtool/arch/x86/include/arch_elf.h b/tools/objtool/arch/x86/include/arch_elf.h
new file mode 100644 (file)
index 0000000..69cc426
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _OBJTOOL_ARCH_ELF
+#define _OBJTOOL_ARCH_ELF
+
+#define R_NONE R_X86_64_NONE
+
+#endif /* _OBJTOOL_ARCH_ELF */
index 5fbb90a..5e0d70a 100644 (file)
@@ -12,6 +12,7 @@
 #include "check.h"
 #include "special.h"
 #include "warn.h"
+#include "arch_elf.h"
 
 #include <linux/hashtable.h>
 #include <linux/kernel.h>
@@ -765,6 +766,24 @@ static int add_call_destinations(struct objtool_file *file)
                } else
                        insn->call_dest = rela->sym;
 
+               /*
+                * Many compilers cannot disable KCOV with a function attribute
+                * so they need a little help, NOP out any KCOV calls from noinstr
+                * text.
+                */
+               if (insn->sec->noinstr &&
+                   !strncmp(insn->call_dest->name, "__sanitizer_cov_", 16)) {
+                       if (rela) {
+                               rela->type = R_NONE;
+                               elf_write_rela(file->elf, rela);
+                       }
+
+                       elf_write_insn(file->elf, insn->sec,
+                                      insn->offset, insn->len,
+                                      arch_nop_insn(insn->len));
+                       insn->type = INSN_NOP;
+               }
+
                /*
                 * Whatever stack impact regular CALLs have, should be undone
                 * by the RETURN of the called function.
@@ -2190,10 +2209,36 @@ static inline const char *call_dest_name(struct instruction *insn)
        return "{dynamic}";
 }
 
+static inline bool noinstr_call_dest(struct symbol *func)
+{
+       /*
+        * We can't deal with indirect function calls at present;
+        * assume they're instrumented.
+        */
+       if (!func)
+               return false;
+
+       /*
+        * If the symbol is from a noinstr section; we good.
+        */
+       if (func->sec->noinstr)
+               return true;
+
+       /*
+        * The __ubsan_handle_*() calls are like WARN(), they only happen when
+        * something 'BAD' happened. At the risk of taking the machine down,
+        * let them proceed to get the message out.
+        */
+       if (!strncmp(func->name, "__ubsan_handle_", 15))
+               return true;
+
+       return false;
+}
+
 static int validate_call(struct instruction *insn, struct insn_state *state)
 {
        if (state->noinstr && state->instr <= 0 &&
-           (!insn->call_dest || !insn->call_dest->sec->noinstr)) {
+           !noinstr_call_dest(insn->call_dest)) {
                WARN_FUNC("call to %s() leaves .noinstr.text section",
                                insn->sec, insn->offset, call_dest_name(insn));
                return 1;
@@ -2740,13 +2785,13 @@ int check(const char *_objname, bool orc)
 
        objname = _objname;
 
-       file.elf = elf_open_read(objname, orc ? O_RDWR : O_RDONLY);
+       file.elf = elf_open_read(objname, O_RDWR);
        if (!file.elf)
                return 1;
 
        INIT_LIST_HEAD(&file.insn_list);
        hash_init(file.insn_hash);
-       file.c_file = find_section_by_name(file.elf, ".comment");
+       file.c_file = !vmlinux && find_section_by_name(file.elf, ".comment");
        file.ignore_unreachables = no_unreachable;
        file.hints = false;
 
@@ -2801,7 +2846,9 @@ int check(const char *_objname, bool orc)
                ret = create_orc_sections(&file);
                if (ret < 0)
                        goto out;
+       }
 
+       if (file.elf->changed) {
                ret = elf_write(file.elf);
                if (ret < 0)
                        goto out;
index 8422567..26d11d8 100644 (file)
@@ -529,8 +529,9 @@ static int read_relas(struct elf *elf)
                        rela->addend = rela->rela.r_addend;
                        rela->offset = rela->rela.r_offset;
                        symndx = GELF_R_SYM(rela->rela.r_info);
-                       rela->sym = find_symbol_by_index(elf, symndx);
                        rela->sec = sec;
+                       rela->idx = i;
+                       rela->sym = find_symbol_by_index(elf, symndx);
                        if (!rela->sym) {
                                WARN("can't find rela entry symbol %d for %s",
                                     symndx, sec->name);
@@ -713,6 +714,8 @@ struct section *elf_create_section(struct elf *elf, const char *name,
        elf_hash_add(elf->section_hash, &sec->hash, sec->idx);
        elf_hash_add(elf->section_name_hash, &sec->name_hash, str_hash(sec->name));
 
+       elf->changed = true;
+
        return sec;
 }
 
@@ -746,7 +749,7 @@ struct section *elf_create_rela_section(struct elf *elf, struct section *base)
        return sec;
 }
 
-int elf_rebuild_rela_section(struct section *sec)
+int elf_rebuild_rela_section(struct elf *elf, struct section *sec)
 {
        struct rela *rela;
        int nr, idx = 0, size;
@@ -763,6 +766,9 @@ int elf_rebuild_rela_section(struct section *sec)
                return -1;
        }
 
+       sec->changed = true;
+       elf->changed = true;
+
        sec->data->d_buf = relas;
        sec->data->d_size = size;
 
@@ -779,7 +785,44 @@ int elf_rebuild_rela_section(struct section *sec)
        return 0;
 }
 
-int elf_write(const struct elf *elf)
+int elf_write_insn(struct elf *elf, struct section *sec,
+                  unsigned long offset, unsigned int len,
+                  const char *insn)
+{
+       Elf_Data *data = sec->data;
+
+       if (data->d_type != ELF_T_BYTE || data->d_off) {
+               WARN("write to unexpected data for section: %s", sec->name);
+               return -1;
+       }
+
+       memcpy(data->d_buf + offset, insn, len);
+       elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY);
+
+       elf->changed = true;
+
+       return 0;
+}
+
+int elf_write_rela(struct elf *elf, struct rela *rela)
+{
+       struct section *sec = rela->sec;
+
+       rela->rela.r_info = GELF_R_INFO(rela->sym->idx, rela->type);
+       rela->rela.r_addend = rela->addend;
+       rela->rela.r_offset = rela->offset;
+
+       if (!gelf_update_rela(sec->data, rela->idx, &rela->rela)) {
+               WARN_ELF("gelf_update_rela");
+               return -1;
+       }
+
+       elf->changed = true;
+
+       return 0;
+}
+
+int elf_write(struct elf *elf)
 {
        struct section *sec;
        Elf_Scn *s;
@@ -796,6 +839,8 @@ int elf_write(const struct elf *elf)
                                WARN_ELF("gelf_update_shdr");
                                return -1;
                        }
+
+                       sec->changed = false;
                }
        }
 
@@ -808,6 +853,8 @@ int elf_write(const struct elf *elf)
                return -1;
        }
 
+       elf->changed = false;
+
        return 0;
 }
 
index f4fe1d6..7324e77 100644 (file)
@@ -64,9 +64,10 @@ struct rela {
        GElf_Rela rela;
        struct section *sec;
        struct symbol *sym;
-       unsigned int type;
        unsigned long offset;
+       unsigned int type;
        int addend;
+       int idx;
        bool jump_table_start;
 };
 
@@ -76,6 +77,7 @@ struct elf {
        Elf *elf;
        GElf_Ehdr ehdr;
        int fd;
+       bool changed;
        char *name;
        struct list_head sections;
        DECLARE_HASHTABLE(symbol_hash, ELF_HASH_BITS);
@@ -118,7 +120,11 @@ struct elf *elf_open_read(const char *name, int flags);
 struct section *elf_create_section(struct elf *elf, const char *name, size_t entsize, int nr);
 struct section *elf_create_rela_section(struct elf *elf, struct section *base);
 void elf_add_rela(struct elf *elf, struct rela *rela);
-int elf_write(const struct elf *elf);
+int elf_write_insn(struct elf *elf, struct section *sec,
+                  unsigned long offset, unsigned int len,
+                  const char *insn);
+int elf_write_rela(struct elf *elf, struct rela *rela);
+int elf_write(struct elf *elf);
 void elf_close(struct elf *elf);
 
 struct section *find_section_by_name(const struct elf *elf, const char *name);
@@ -130,7 +136,7 @@ struct rela *find_rela_by_dest(const struct elf *elf, struct section *sec, unsig
 struct rela *find_rela_by_dest_range(const struct elf *elf, struct section *sec,
                                     unsigned long offset, unsigned int len);
 struct symbol *find_func_containing(struct section *sec, unsigned long offset);
-int elf_rebuild_rela_section(struct section *sec);
+int elf_rebuild_rela_section(struct elf *elf, struct section *sec);
 
 #define for_each_sec(file, sec)                                                \
        list_for_each_entry(sec, &file->elf->sections, list)
index c954998..4c37f80 100644 (file)
@@ -222,7 +222,7 @@ int create_orc_sections(struct objtool_file *file)
                }
        }
 
-       if (elf_rebuild_rela_section(ip_relasec))
+       if (elf_rebuild_rela_section(file->elf, ip_relasec))
                return -1;
 
        return 0;
index 877ca6b..5136338 100644 (file)
@@ -396,6 +396,18 @@ else
       NO_LIBBPF := 1
       NO_JVMTI := 1
     else
+      ifneq ($(filter s% -fsanitize=address%,$(EXTRA_CFLAGS),),)
+        ifneq ($(shell ldconfig -p | grep libasan >/dev/null 2>&1; echo $$?), 0)
+          msg := $(error No libasan found, please install libasan);
+        endif
+      endif
+
+      ifneq ($(filter s% -fsanitize=undefined%,$(EXTRA_CFLAGS),),)
+        ifneq ($(shell ldconfig -p | grep libubsan >/dev/null 2>&1; echo $$?), 0)
+          msg := $(error No libubsan found, please install libubsan);
+        endif
+      endif
+
       ifneq ($(filter s% -static%,$(LDFLAGS),),)
         msg := $(error No static glibc found, please install glibc-static);
       else
index 37b844f..78847b3 100644 (file)
 435    common  clone3                  sys_clone3
 437    common  openat2                 sys_openat2
 438    common  pidfd_getfd             sys_pidfd_getfd
+439    common  faccessat2              sys_faccessat2
 
 #
 # x32-specific system call numbers start at 512 to avoid cache impact
index 839ef52..6ce4512 100644 (file)
@@ -641,6 +641,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
                        }
                        evsel->core.attr.freq = 0;
                        evsel->core.attr.sample_period = 1;
+                       evsel->no_aux_samples = true;
                        intel_pt_evsel = evsel;
                        opts->full_auxtrace = true;
                }
index e108d90..a37e791 100644 (file)
@@ -852,20 +852,20 @@ static int record__open(struct record *rec)
         * event synthesis.
         */
        if (opts->initial_delay || target__has_cpu(&opts->target)) {
-               if (perf_evlist__add_dummy(evlist))
-                       return -ENOMEM;
+               pos = perf_evlist__get_tracking_event(evlist);
+               if (!evsel__is_dummy_event(pos)) {
+                       /* Set up dummy event. */
+                       if (perf_evlist__add_dummy(evlist))
+                               return -ENOMEM;
+                       pos = evlist__last(evlist);
+                       perf_evlist__set_tracking_event(evlist, pos);
+               }
 
-               /* Disable tracking of mmaps on lead event. */
-               pos = evlist__first(evlist);
-               pos->tracking = 0;
-               /* Set up dummy event. */
-               pos = evlist__last(evlist);
-               pos->tracking = 1;
                /*
                 * Enable the dummy event when the process is forked for
                 * initial_delay, immediately for system wide.
                 */
-               if (opts->initial_delay)
+               if (opts->initial_delay && !pos->immediate)
                        pos->core.attr.enable_on_exec = 1;
                else
                        pos->immediate = 1;
index b63b3fb..5f1d2a8 100644 (file)
@@ -478,8 +478,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
        if (rep->time_str)
                ret += fprintf(fp, " (time slices: %s)", rep->time_str);
 
-       if (symbol_conf.show_ref_callgraph &&
-           strstr(evname, "call-graph=no")) {
+       if (symbol_conf.show_ref_callgraph && evname && strstr(evname, "call-graph=no")) {
                ret += fprintf(fp, ", show reference callgraph");
        }
 
index 5da2436..4474577 100644 (file)
@@ -462,7 +462,7 @@ static int perf_evsel__check_attr(struct evsel *evsel, struct perf_session *sess
                return -EINVAL;
 
        if (PRINT_FIELD(IREGS) &&
-           evsel__check_stype(evsel, PERF_SAMPLE_REGS_INTR, "IREGS", PERF_OUTPUT_IREGS))
+           evsel__do_check_stype(evsel, PERF_SAMPLE_REGS_INTR, "IREGS", PERF_OUTPUT_IREGS, allow_user_set))
                return -EINVAL;
 
        if (PRINT_FIELD(UREGS) &&
@@ -3837,6 +3837,9 @@ int cmd_script(int argc, const char **argv)
        if (err)
                goto out_delete;
 
+       if (zstd_init(&(session->zstd_data), 0) < 0)
+               pr_warning("Decompression initialization failed. Reported data may be incomplete.\n");
+
        err = __cmd_script(&script);
 
        flush_scripting();
index 2df2e23..24c4ba2 100644 (file)
        {
                "Unit": "CPU-M-CF",
                "EventCode": "265",
-               "EventName": "DFLT_CCERROR",
+               "EventName": "DFLT_CCFINISH",
                "BriefDescription": "Increments by one for every DEFLATE CONVERSION CALL instruction executed that ended in Condition Codes 0, 1 or 2",
                "PublicDescription": "Increments by one for every DEFLATE CONVERSION CALL instruction executed that ended in Condition Codes 0, 1 or 2"
        },
index 7bd73a9..d187e46 100644 (file)
@@ -1055,7 +1055,7 @@ def cbr(id, raw_buf):
        cbr = data[0]
        MHz = (data[4] + 500) / 1000
        percent = ((cbr * 1000 / data[2]) + 5) / 10
-       value = struct.pack("!hiqiiiiii", 4, 8, id, 4, cbr, 4, MHz, 4, percent)
+       value = struct.pack("!hiqiiiiii", 4, 8, id, 4, cbr, 4, int(MHz), 4, int(percent))
        cbr_file.write(value)
 
 def mwait(id, raw_buf):
index 26d7be7..7daa8bb 100755 (executable)
@@ -768,7 +768,8 @@ class CallGraphModel(CallGraphModelBase):
                                                " FROM calls"
                                                " INNER JOIN call_paths ON calls.call_path_id = call_paths.id"
                                                " INNER JOIN symbols ON call_paths.symbol_id = symbols.id"
-                                               " WHERE symbols.name" + match +
+                                               " WHERE calls.id <> 0"
+                                               " AND symbols.name" + match +
                                                " GROUP BY comm_id, thread_id, call_path_id"
                                                " ORDER BY comm_id, thread_id, call_path_id")
 
@@ -963,7 +964,8 @@ class CallTreeModel(CallGraphModelBase):
                                                " FROM calls"
                                                " INNER JOIN call_paths ON calls.call_path_id = call_paths.id"
                                                " INNER JOIN symbols ON call_paths.symbol_id = symbols.id"
-                                               " WHERE symbols.name" + match +
+                                               " WHERE calls.id <> 0"
+                                               " AND symbols.name" + match +
                                                " ORDER BY comm_id, thread_id, call_time, calls.id")
 
        def FindPath(self, query):
@@ -1050,6 +1052,7 @@ class TreeWindowBase(QMdiSubWindow):
                                child = self.model.index(row, 0, parent)
                                if child.internalPointer().dbid == dbid:
                                        found = True
+                                       self.view.setExpanded(parent, True)
                                        self.view.setCurrentIndex(child)
                                        parent = child
                                        break
@@ -1127,6 +1130,7 @@ class CallTreeWindow(TreeWindowBase):
                                child = self.model.index(row, 0, parent)
                                if child.internalPointer().dbid == dbid:
                                        found = True
+                                       self.view.setExpanded(parent, True)
                                        self.view.setCurrentIndex(child)
                                        parent = child
                                        break
@@ -1139,6 +1143,7 @@ class CallTreeWindow(TreeWindowBase):
                                return
                        last_child = None
                        for row in xrange(n):
+                               self.view.setExpanded(parent, True)
                                child = self.model.index(row, 0, parent)
                                child_call_time = child.internalPointer().call_time
                                if child_call_time < time:
@@ -1151,9 +1156,11 @@ class CallTreeWindow(TreeWindowBase):
                        if not last_child:
                                if not found:
                                        child = self.model.index(0, 0, parent)
+                                       self.view.setExpanded(parent, True)
                                        self.view.setCurrentIndex(child)
                                return
                        found = True
+                       self.view.setExpanded(parent, True)
                        self.view.setCurrentIndex(last_child)
                        parent = last_child
 
index 61f3be9..6578001 100755 (executable)
@@ -17,6 +17,7 @@
 from __future__ import print_function
 import sys
 import os
+import io
 import argparse
 import json
 
@@ -81,7 +82,7 @@ class FlameGraphCLI:
 
         if self.args.format == "html":
             try:
-                with open(self.args.template) as f:
+                with io.open(self.args.template, encoding="utf-8") as f:
                     output_str = f.read().replace("/** @flamegraph_json **/",
                                                   json_str)
             except IOError as e:
@@ -93,11 +94,12 @@ class FlameGraphCLI:
             output_fn = self.args.output or "stacks.json"
 
         if output_fn == "-":
-            sys.stdout.write(output_str)
+            with io.open(sys.stdout.fileno(), "w", encoding="utf-8", closefd=False) as out:
+                out.write(output_str)
         else:
             print("dumping data to {}".format(output_fn))
             try:
-                with open(output_fn, "w") as out:
+                with io.open(output_fn, "w", encoding="utf-8") as out:
                     out.write(output_str)
             except IOError as e:
                 print("Error writing output file: {}".format(e), file=sys.stderr)
index 811cc0e..110f0c6 100644 (file)
@@ -65,6 +65,7 @@ size_t syscall_arg__scnprintf_statx_mask(char *bf, size_t size, struct syscall_a
        P_FLAG(SIZE);
        P_FLAG(BLOCKS);
        P_FLAG(BTIME);
+       P_FLAG(MNT_ID);
 
 #undef P_FLAG
 
index f98a118..be9c4c0 100644 (file)
@@ -2288,6 +2288,11 @@ static struct thread *hist_browser__selected_thread(struct hist_browser *browser
        return browser->he_selection->thread;
 }
 
+static struct res_sample *hist_browser__selected_res_sample(struct hist_browser *browser)
+{
+       return browser->he_selection ? browser->he_selection->res_samples : NULL;
+}
+
 /* Check whether the browser is for 'top' or 'report' */
 static inline bool is_report_browser(void *timer)
 {
@@ -3357,16 +3362,16 @@ skip_annotation:
                                             &options[nr_options], NULL, NULL, evsel);
                nr_options += add_res_sample_opt(browser, &actions[nr_options],
                                                 &options[nr_options],
-                                hist_browser__selected_entry(browser)->res_samples,
-                                evsel, A_NORMAL);
+                                                hist_browser__selected_res_sample(browser),
+                                                evsel, A_NORMAL);
                nr_options += add_res_sample_opt(browser, &actions[nr_options],
                                                 &options[nr_options],
-                                hist_browser__selected_entry(browser)->res_samples,
-                                evsel, A_ASM);
+                                                hist_browser__selected_res_sample(browser),
+                                                evsel, A_ASM);
                nr_options += add_res_sample_opt(browser, &actions[nr_options],
                                                 &options[nr_options],
-                                hist_browser__selected_entry(browser)->res_samples,
-                                evsel, A_SOURCE);
+                                                hist_browser__selected_res_sample(browser),
+                                                evsel, A_SOURCE);
                nr_options += add_switch_opt(browser, &actions[nr_options],
                                             &options[nr_options]);
 skip_scripting:
@@ -3598,6 +3603,23 @@ static int __perf_evlist__tui_browse_hists(struct evlist *evlist,
                                    hbt, warn_lost_event);
 }
 
+static bool perf_evlist__single_entry(struct evlist *evlist)
+{
+       int nr_entries = evlist->core.nr_entries;
+
+       if (nr_entries == 1)
+              return true;
+
+       if (nr_entries == 2) {
+               struct evsel *last = evlist__last(evlist);
+
+               if (evsel__is_dummy_event(last))
+                       return true;
+       }
+
+       return false;
+}
+
 int perf_evlist__tui_browse_hists(struct evlist *evlist, const char *help,
                                  struct hist_browser_timer *hbt,
                                  float min_pcnt,
@@ -3608,7 +3630,7 @@ int perf_evlist__tui_browse_hists(struct evlist *evlist, const char *help,
        int nr_entries = evlist->core.nr_entries;
 
 single_entry:
-       if (nr_entries == 1) {
+       if (perf_evlist__single_entry(evlist)) {
                struct evsel *first = evlist__first(evlist);
 
                return perf_evsel__hists_browse(first, nr_entries, help,
index b020a86..9887ae0 100644 (file)
@@ -142,7 +142,8 @@ static int
 gen_read_mem(struct bpf_insn_pos *pos,
             int src_base_addr_reg,
             int dst_addr_reg,
-            long offset)
+            long offset,
+            int probeid)
 {
        /* mov arg3, src_base_addr_reg */
        if (src_base_addr_reg != BPF_REG_ARG3)
@@ -159,7 +160,7 @@ gen_read_mem(struct bpf_insn_pos *pos,
                ins(BPF_MOV64_REG(BPF_REG_ARG1, dst_addr_reg), pos);
 
        /* Call probe_read  */
-       ins(BPF_EMIT_CALL(BPF_FUNC_probe_read), pos);
+       ins(BPF_EMIT_CALL(probeid), pos);
        /*
         * Error processing: if read fail, goto error code,
         * will be relocated. Target should be the start of
@@ -241,7 +242,7 @@ static int
 gen_prologue_slowpath(struct bpf_insn_pos *pos,
                      struct probe_trace_arg *args, int nargs)
 {
-       int err, i;
+       int err, i, probeid;
 
        for (i = 0; i < nargs; i++) {
                struct probe_trace_arg *arg = &args[i];
@@ -276,11 +277,16 @@ gen_prologue_slowpath(struct bpf_insn_pos *pos,
                                stack_offset), pos);
 
                ref = arg->ref;
+               probeid = BPF_FUNC_probe_read_kernel;
                while (ref) {
                        pr_debug("prologue: arg %d: offset %ld\n",
                                 i, ref->offset);
+
+                       if (ref->user_access)
+                               probeid = BPF_FUNC_probe_read_user;
+
                        err = gen_read_mem(pos, BPF_REG_3, BPF_REG_7,
-                                          ref->offset);
+                                          ref->offset, probeid);
                        if (err) {
                                pr_err("prologue: failed to generate probe_read function call\n");
                                goto errout;
index 173b4f0..ab48be4 100644 (file)
@@ -1566,6 +1566,18 @@ void perf_evlist__to_front(struct evlist *evlist,
        list_splice(&move, &evlist->core.entries);
 }
 
+struct evsel *perf_evlist__get_tracking_event(struct evlist *evlist)
+{
+       struct evsel *evsel;
+
+       evlist__for_each_entry(evlist, evsel) {
+               if (evsel->tracking)
+                       return evsel;
+       }
+
+       return evlist__first(evlist);
+}
+
 void perf_evlist__set_tracking_event(struct evlist *evlist,
                                     struct evsel *tracking_evsel)
 {
index b6f325d..a8081df 100644 (file)
@@ -335,6 +335,7 @@ void perf_evlist__to_front(struct evlist *evlist,
        evlist__cpu_iter_start(evlist);                 \
        perf_cpu_map__for_each_cpu (cpu, index, (evlist)->core.all_cpus)
 
+struct evsel *perf_evlist__get_tracking_event(struct evlist *evlist);
 void perf_evlist__set_tracking_event(struct evlist *evlist,
                                     struct evsel *tracking_evsel);
 
index 96e5171..ef802f6 100644 (file)
@@ -898,12 +898,6 @@ static void evsel__apply_config_terms(struct evsel *evsel,
        }
 }
 
-static bool is_dummy_event(struct evsel *evsel)
-{
-       return (evsel->core.attr.type == PERF_TYPE_SOFTWARE) &&
-              (evsel->core.attr.config == PERF_COUNT_SW_DUMMY);
-}
-
 struct evsel_config_term *__evsel__get_config_term(struct evsel *evsel, enum evsel_term_type type)
 {
        struct evsel_config_term *term, *found_term = NULL;
@@ -1020,12 +1014,12 @@ void evsel__config(struct evsel *evsel, struct record_opts *opts,
        if (callchain && callchain->enabled && !evsel->no_aux_samples)
                evsel__config_callchain(evsel, opts, callchain);
 
-       if (opts->sample_intr_regs) {
+       if (opts->sample_intr_regs && !evsel->no_aux_samples) {
                attr->sample_regs_intr = opts->sample_intr_regs;
                evsel__set_sample_bit(evsel, REGS_INTR);
        }
 
-       if (opts->sample_user_regs) {
+       if (opts->sample_user_regs && !evsel->no_aux_samples) {
                attr->sample_regs_user |= opts->sample_user_regs;
                evsel__set_sample_bit(evsel, REGS_USER);
        }
@@ -1161,7 +1155,7 @@ void evsel__config(struct evsel *evsel, struct record_opts *opts,
         * The software event will trigger -EOPNOTSUPP error out,
         * if BRANCH_STACK bit is set.
         */
-       if (is_dummy_event(evsel))
+       if (evsel__is_dummy_event(evsel))
                evsel__reset_sample_bit(evsel, BRANCH_STACK);
 }
 
index 0f963c2..35e3f6d 100644 (file)
@@ -399,6 +399,12 @@ static inline bool evsel__has_br_stack(const struct evsel *evsel)
               evsel->synth_sample_type & PERF_SAMPLE_BRANCH_STACK;
 }
 
+static inline bool evsel__is_dummy_event(struct evsel *evsel)
+{
+       return (evsel->core.attr.type == PERF_TYPE_SOFTWARE) &&
+              (evsel->core.attr.config == PERF_COUNT_SW_DUMMY);
+}
+
 struct perf_env *evsel__env(struct evsel *evsel);
 
 int evsel__store_ids(struct evsel *evsel, struct evlist *evlist);
index df59fd4..e0af36b 100644 (file)
 #include <stdbool.h>
 #include <stddef.h>
 #include <limits.h>
-#ifndef __WORDSIZE
-#define __WORDSIZE (__SIZEOF_LONG__ * 8)
-#endif
 
 static inline size_t hash_bits(size_t h, int bits)
 {
        /* shuffle bits and return requested number of upper bits */
-       return (h * 11400714819323198485llu) >> (__WORDSIZE - bits);
+#if (__SIZEOF_SIZE_T__ == __SIZEOF_LONG_LONG__)
+       /* LP64 case */
+       return (h * 11400714819323198485llu) >> (__SIZEOF_LONG_LONG__ * 8 - bits);
+#elif (__SIZEOF_SIZE_T__ <= __SIZEOF_LONG__)
+       return (h * 2654435769lu) >> (__SIZEOF_LONG__ * 8 - bits);
+#else
+#      error "Unsupported size_t size"
+#endif
 }
 
 typedef size_t (*hashmap_hash_fn)(const void *key, void *ctx);
index e4dd8bf..cb3c1e5 100644 (file)
@@ -1735,6 +1735,7 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
        u64 sample_type = evsel->core.attr.sample_type;
        u64 id = evsel->core.id[0];
        u8 cpumode;
+       u64 regs[8 * sizeof(sample.intr_regs.mask)];
 
        if (intel_pt_skip_event(pt))
                return 0;
@@ -1784,8 +1785,8 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
        }
 
        if (sample_type & PERF_SAMPLE_REGS_INTR &&
-           items->mask[INTEL_PT_GP_REGS_POS]) {
-               u64 regs[sizeof(sample.intr_regs.mask)];
+           (items->mask[INTEL_PT_GP_REGS_POS] ||
+            items->mask[INTEL_PT_XMM_POS])) {
                u64 regs_mask = evsel->core.attr.sample_regs_intr;
                u64 *pos;
 
index c4ca932..acef87d 100644 (file)
@@ -26,7 +26,7 @@ do { \
                YYABORT; \
 } while (0)
 
-static struct list_head* alloc_list()
+static struct list_head* alloc_list(void)
 {
        struct list_head *list;
 
@@ -349,7 +349,7 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
        struct list_head *list;
        char pmu_name[128];
 
-       snprintf(&pmu_name, 128, "%s-%s", $1, $3);
+       snprintf(pmu_name, sizeof(pmu_name), "%s-%s", $1, $3);
        free($1);
        free($3);
        if (parse_events_multi_pmu_add(_parse_state, pmu_name, &list) < 0)
index 85e0c7f..f971d9a 100644 (file)
@@ -86,7 +86,6 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
                          struct perf_pmu_info *info);
 struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
                                  struct list_head *head_terms);
-int perf_pmu_wrap(void);
 void perf_pmu_error(struct list_head *list, char *name, char const *msg);
 
 int perf_pmu__new_format(struct list_head *list, char *name,
index a08f373..df713a5 100644 (file)
@@ -1575,7 +1575,7 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
        }
 
        tmp = strchr(str, '@');
-       if (tmp && tmp != str && strcmp(tmp + 1, "user")) { /* user attr */
+       if (tmp && tmp != str && !strcmp(tmp + 1, "user")) { /* user attr */
                if (!user_access_is_supported()) {
                        semantic_error("ftrace does not support user access\n");
                        return -EINVAL;
@@ -1995,7 +1995,10 @@ static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref,
                if (depth < 0)
                        return depth;
        }
-       err = strbuf_addf(buf, "%+ld(", ref->offset);
+       if (ref->user_access)
+               err = strbuf_addf(buf, "%s%ld(", "+u", ref->offset);
+       else
+               err = strbuf_addf(buf, "%+ld(", ref->offset);
        return (err < 0) ? err : depth;
 }
 
index 8c85294..064b63a 100644 (file)
@@ -1044,7 +1044,7 @@ static struct {
        DEFINE_TYPE(FTRACE_README_PROBE_TYPE_X, "*type: * x8/16/32/64,*"),
        DEFINE_TYPE(FTRACE_README_KRETPROBE_OFFSET, "*place (kretprobe): *"),
        DEFINE_TYPE(FTRACE_README_UPROBE_REF_CTR, "*ref_ctr_offset*"),
-       DEFINE_TYPE(FTRACE_README_USER_ACCESS, "*[u]<offset>*"),
+       DEFINE_TYPE(FTRACE_README_USER_ACCESS, "*u]<offset>*"),
        DEFINE_TYPE(FTRACE_README_MULTIPROBE_EVENT, "*Create/append/*"),
        DEFINE_TYPE(FTRACE_README_IMMEDIATE_VALUE, "*\\imm-value,*"),
 };
index 3c6976f..57d0706 100644 (file)
@@ -668,7 +668,7 @@ static void print_aggr(struct perf_stat_config *config,
        int s;
        bool first;
 
-       if (!(config->aggr_map || config->aggr_get_id))
+       if (!config->aggr_map || !config->aggr_get_id)
                return;
 
        aggr_update_shadow(config, evlist);
@@ -1169,7 +1169,7 @@ static void print_percore(struct perf_stat_config *config,
        int s;
        bool first = true;
 
-       if (!(config->aggr_map || config->aggr_get_id))
+       if (!config->aggr_map || !config->aggr_get_id)
                return;
 
        if (config->percore_show_thread)
index eec23fa..83844f8 100644 (file)
@@ -47,7 +47,7 @@ static int transfer_size;
 static int iterations;
 static int interval = 5; /* interval in seconds for showing transfer rate */
 
-uint8_t default_tx[] = {
+static uint8_t default_tx[] = {
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0x40, 0x00, 0x00, 0x00, 0x00, 0x95,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -56,8 +56,8 @@ uint8_t default_tx[] = {
        0xF0, 0x0D,
 };
 
-uint8_t default_rx[ARRAY_SIZE(default_tx)] = {0, };
-char *input_tx;
+static uint8_t default_rx[ARRAY_SIZE(default_tx)] = {0, };
+static char *input_tx;
 
 static void hex_dump(const void *src, size_t length, size_t line_size,
                     char *prefix)
@@ -461,8 +461,8 @@ int main(int argc, char *argv[])
                pabort("can't get max speed hz");
 
        printf("spi mode: 0x%x\n", mode);
-       printf("bits per word: %d\n", bits);
-       printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
+       printf("bits per word: %u\n", bits);
+       printf("max speed: %u Hz (%u kHz)\n", speed, speed/1000);
 
        if (input_tx)
                transfer_escaped_string(fd, input_tx);
index 787b6d4..f9b769f 100755 (executable)
@@ -82,7 +82,9 @@ def build_tests(linux: kunit_kernel.LinuxSourceTree,
                                        request.make_options)
        build_end = time.time()
        if not success:
-               return KunitResult(KunitStatus.BUILD_FAILURE, 'could not build kernel')
+               return KunitResult(KunitStatus.BUILD_FAILURE,
+                                  'could not build kernel',
+                                  build_end - build_start)
        if not success:
                return KunitResult(KunitStatus.BUILD_FAILURE,
                                   'could not build kernel',
index e75063d..02ffc3a 100644 (file)
@@ -10,7 +10,7 @@ import collections
 import re
 
 CONFIG_IS_NOT_SET_PATTERN = r'^# CONFIG_(\w+) is not set$'
-CONFIG_PATTERN = r'^CONFIG_(\w+)=(\S+)$'
+CONFIG_PATTERN = r'^CONFIG_(\w+)=(\S+|".*")$'
 
 KconfigEntryBase = collections.namedtuple('KconfigEntry', ['name', 'value'])
 
index 64aac9d..f13e0c0 100644 (file)
@@ -265,11 +265,9 @@ def bubble_up_suite_errors(test_suite_list: List[TestSuite]) -> TestStatus:
        return bubble_up_errors(lambda x: x.status, test_suite_list)
 
 def parse_test_result(lines: List[str]) -> TestResult:
-       if not lines:
-               return TestResult(TestStatus.NO_TESTS, [], lines)
        consume_non_diagnositic(lines)
-       if not parse_tap_header(lines):
-               return None
+       if not lines or not parse_tap_header(lines):
+               return TestResult(TestStatus.NO_TESTS, [], lines)
        test_suites = []
        test_suite = parse_test_suite(lines)
        while test_suite:
@@ -282,6 +280,8 @@ def parse_run_tests(kernel_output) -> TestResult:
        failed_tests = 0
        crashed_tests = 0
        test_result = parse_test_result(list(isolate_kunit_output(kernel_output)))
+       if test_result.status == TestStatus.NO_TESTS:
+               print_with_timestamp(red('[ERROR] ') + 'no kunit output detected')
        for test_suite in test_result.suites:
                if test_suite.status == TestStatus.SUCCESS:
                        print_suite_divider(green('[PASSED] ') + test_suite.name)
index 5bb7b11..f9eeaea 100755 (executable)
@@ -170,6 +170,17 @@ class KUnitParserTest(unittest.TestCase):
                        result.status)
                file.close()
 
+       def test_no_kunit_output(self):
+               crash_log = get_absolute_path(
+                       'test_data/test_insufficient_memory.log')
+               file = open(crash_log)
+               print_mock = mock.patch('builtins.print').start()
+               result = kunit_parser.parse_run_tests(
+                       kunit_parser.isolate_kunit_output(file.readlines()))
+               print_mock.assert_any_call(StrContains("no kunit output detected"))
+               print_mock.stop()
+               file.close()
+
        def test_crashed_test(self):
                crashed_log = get_absolute_path(
                        'test_data/test_is_test_passed-crash.log')
diff --git a/tools/testing/kunit/test_data/test_insufficient_memory.log b/tools/testing/kunit/test_data/test_insufficient_memory.log
new file mode 100644 (file)
index 0000000..e69de29
index db3c07b..b5f7a99 100644 (file)
@@ -51,7 +51,7 @@ struct nd_cmd_translate_spa {
                __u32 nfit_device_handle;
                __u32 _reserved;
                __u64 dpa;
-       } __packed devices[0];
+       } __packed devices[];
 
 } __packed;
 
@@ -74,7 +74,7 @@ struct nd_cmd_ars_err_inj_stat {
        struct nd_error_stat_query_record {
                __u64 err_inj_stat_spa_range_base;
                __u64 err_inj_stat_spa_range_length;
-       } __packed record[0];
+       } __packed record[];
 } __packed;
 
 #define ND_INTEL_SMART                  1
@@ -180,7 +180,7 @@ struct nd_intel_fw_send_data {
        __u32 context;
        __u32 offset;
        __u32 length;
-       __u8 data[0];
+       __u8 data[];
 /* this field is not declared due ot variable data from input */
 /*     __u32 status; */
 } __packed;
index b497cfe..ac4ad00 100644 (file)
@@ -21,10 +21,6 @@ include ../../lib.mk
 $(TEST_GEN_PROGS): $(PROGS)
        cp $(PROGS) $(OUTPUT)/
 
-clean:
-       $(CLEAN)
-       rm -f $(PROGS)
-
 # Common test-unit targets to build common-layout test-cases executables
 # Needs secondary expansion to properly include the testcase c-file in pre-reqs
 .SECONDEXPANSION:
index 83493bd..109d034 100644 (file)
@@ -36,7 +36,7 @@ void test_fentry_fexit(void)
        fentry_res = (__u64 *)fentry_skel->bss;
        fexit_res = (__u64 *)fexit_skel->bss;
        printf("%lld\n", fentry_skel->bss->test1_result);
-       for (i = 0; i < 6; i++) {
+       for (i = 0; i < 8; i++) {
                CHECK(fentry_res[i] != 1, "result",
                      "fentry_test%d failed err %lld\n", i + 1, fentry_res[i]);
                CHECK(fexit_res[i] != 1, "result",
index ea14e3e..f11f187 100644 (file)
@@ -527,8 +527,8 @@ static void test_skb_less_prog_attach(struct bpf_flow *skel, int tap_fd)
 
        run_tests_skb_less(tap_fd, skel->maps.last_dissection);
 
-       err = bpf_prog_detach(prog_fd, BPF_FLOW_DISSECTOR);
-       CHECK(err, "bpf_prog_detach", "err %d errno %d\n", err, errno);
+       err = bpf_prog_detach2(prog_fd, 0, BPF_FLOW_DISSECTOR);
+       CHECK(err, "bpf_prog_detach2", "err %d errno %d\n", err, errno);
 }
 
 static void test_skb_less_link_create(struct bpf_flow *skel, int tap_fd)
index 15cb554..172c586 100644 (file)
@@ -1,9 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Test that the flow_dissector program can be updated with a single
- * syscall by attaching a new program that replaces the existing one.
- *
- * Corner case - the same program cannot be attached twice.
+ * Tests for attaching, detaching, and replacing flow_dissector BPF program.
  */
 
 #define _GNU_SOURCE
@@ -116,7 +113,7 @@ static void test_prog_attach_prog_attach(int netns, int prog1, int prog2)
        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog2));
 
 out_detach:
-       err = bpf_prog_detach(0, BPF_FLOW_DISSECTOR);
+       err = bpf_prog_detach2(prog2, 0, BPF_FLOW_DISSECTOR);
        if (CHECK_FAIL(err))
                perror("bpf_prog_detach");
        CHECK_FAIL(prog_is_attached(netns));
@@ -152,7 +149,7 @@ static void test_prog_attach_link_create(int netns, int prog1, int prog2)
        DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
        int err, link;
 
-       err = bpf_prog_attach(prog1, -1, BPF_FLOW_DISSECTOR, 0);
+       err = bpf_prog_attach(prog1, 0, BPF_FLOW_DISSECTOR, 0);
        if (CHECK_FAIL(err)) {
                perror("bpf_prog_attach(prog1)");
                return;
@@ -168,7 +165,7 @@ static void test_prog_attach_link_create(int netns, int prog1, int prog2)
                close(link);
        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 
-       err = bpf_prog_detach(-1, BPF_FLOW_DISSECTOR);
+       err = bpf_prog_detach2(prog1, 0, BPF_FLOW_DISSECTOR);
        if (CHECK_FAIL(err))
                perror("bpf_prog_detach");
        CHECK_FAIL(prog_is_attached(netns));
@@ -188,7 +185,7 @@ static void test_link_create_prog_attach(int netns, int prog1, int prog2)
 
        /* Expect failure attaching prog when link exists */
        errno = 0;
-       err = bpf_prog_attach(prog2, -1, BPF_FLOW_DISSECTOR, 0);
+       err = bpf_prog_attach(prog2, 0, BPF_FLOW_DISSECTOR, 0);
        if (CHECK_FAIL(!err || errno != EEXIST))
                perror("bpf_prog_attach(prog2) expected EEXIST");
        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
@@ -211,7 +208,7 @@ static void test_link_create_prog_detach(int netns, int prog1, int prog2)
 
        /* Expect failure detaching prog when link exists */
        errno = 0;
-       err = bpf_prog_detach(-1, BPF_FLOW_DISSECTOR);
+       err = bpf_prog_detach2(prog1, 0, BPF_FLOW_DISSECTOR);
        if (CHECK_FAIL(!err || errno != EINVAL))
                perror("bpf_prog_detach expected EINVAL");
        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
@@ -231,7 +228,7 @@ static void test_prog_attach_detach_query(int netns, int prog1, int prog2)
        }
        CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
 
-       err = bpf_prog_detach(0, BPF_FLOW_DISSECTOR);
+       err = bpf_prog_detach2(prog1, 0, BPF_FLOW_DISSECTOR);
        if (CHECK_FAIL(err)) {
                perror("bpf_prog_detach");
                return;
@@ -308,6 +305,31 @@ static void test_link_update_replace_old_prog(int netns, int prog1, int prog2)
        CHECK_FAIL(prog_is_attached(netns));
 }
 
+static void test_link_update_same_prog(int netns, int prog1, int prog2)
+{
+       DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
+       DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
+       int err, link;
+
+       link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
+       if (CHECK_FAIL(link < 0)) {
+               perror("bpf_link_create(prog1)");
+               return;
+       }
+       CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
+
+       /* Expect success updating the prog with the same one */
+       update_opts.flags = 0;
+       update_opts.old_prog_fd = 0;
+       err = bpf_link_update(link, prog1, &update_opts);
+       if (CHECK_FAIL(err))
+               perror("bpf_link_update");
+       CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
+
+       close(link);
+       CHECK_FAIL(prog_is_attached(netns));
+}
+
 static void test_link_update_invalid_opts(int netns, int prog1, int prog2)
 {
        DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
@@ -571,6 +593,8 @@ static void run_tests(int netns)
                  test_link_update_no_old_prog },
                { "link update with replace old prog",
                  test_link_update_replace_old_prog },
+               { "link update with same prog",
+                 test_link_update_same_prog },
                { "link update invalid opts",
                  test_link_update_invalid_opts },
                { "link update invalid prog",
index 2061a6b..5f54c6a 100644 (file)
@@ -13,6 +13,7 @@ static int getsetsockopt(void)
                char cc[16]; /* TCP_CA_NAME_MAX */
        } buf = {};
        socklen_t optlen;
+       char *big_buf = NULL;
 
        fd = socket(AF_INET, SOCK_STREAM, 0);
        if (fd < 0) {
@@ -22,24 +23,31 @@ static int getsetsockopt(void)
 
        /* IP_TOS - BPF bypass */
 
-       buf.u8[0] = 0x08;
-       err = setsockopt(fd, SOL_IP, IP_TOS, &buf, 1);
+       optlen = getpagesize() * 2;
+       big_buf = calloc(1, optlen);
+       if (!big_buf) {
+               log_err("Couldn't allocate two pages");
+               goto err;
+       }
+
+       *(int *)big_buf = 0x08;
+       err = setsockopt(fd, SOL_IP, IP_TOS, big_buf, optlen);
        if (err) {
                log_err("Failed to call setsockopt(IP_TOS)");
                goto err;
        }
 
-       buf.u8[0] = 0x00;
+       memset(big_buf, 0, optlen);
        optlen = 1;
-       err = getsockopt(fd, SOL_IP, IP_TOS, &buf, &optlen);
+       err = getsockopt(fd, SOL_IP, IP_TOS, big_buf, &optlen);
        if (err) {
                log_err("Failed to call getsockopt(IP_TOS)");
                goto err;
        }
 
-       if (buf.u8[0] != 0x08) {
-               log_err("Unexpected getsockopt(IP_TOS) buf[0] 0x%02x != 0x08",
-                       buf.u8[0]);
+       if (*(int *)big_buf != 0x08) {
+               log_err("Unexpected getsockopt(IP_TOS) optval 0x%x != 0x08",
+                       *(int *)big_buf);
                goto err;
        }
 
@@ -78,6 +86,28 @@ static int getsetsockopt(void)
                goto err;
        }
 
+       /* IP_FREEBIND - BPF can't access optval past PAGE_SIZE */
+
+       optlen = getpagesize() * 2;
+       memset(big_buf, 0, optlen);
+
+       err = setsockopt(fd, SOL_IP, IP_FREEBIND, big_buf, optlen);
+       if (err != 0) {
+               log_err("Failed to call setsockopt, ret=%d", err);
+               goto err;
+       }
+
+       err = getsockopt(fd, SOL_IP, IP_FREEBIND, big_buf, &optlen);
+       if (err != 0) {
+               log_err("Failed to call getsockopt, ret=%d", err);
+               goto err;
+       }
+
+       if (optlen != 1 || *(__u8 *)big_buf != 0x55) {
+               log_err("Unexpected IP_FREEBIND getsockopt, optlen=%d, optval=0x%x",
+                       optlen, *(__u8 *)big_buf);
+       }
+
        /* SO_SNDBUF is overwritten */
 
        buf.u32 = 0x01010101;
@@ -124,9 +154,11 @@ static int getsetsockopt(void)
                goto err;
        }
 
+       free(big_buf);
        close(fd);
        return 0;
 err:
+       free(big_buf);
        close(fd);
        return -1;
 }
index 7897c8f..ef57408 100644 (file)
@@ -480,10 +480,9 @@ static __always_inline void hystart_update(struct sock *sk, __u32 delay)
 
        if (hystart_detect & HYSTART_DELAY) {
                /* obtain the minimum delay of more than sampling packets */
+               if (ca->curr_rtt > delay)
+                       ca->curr_rtt = delay;
                if (ca->sample_cnt < HYSTART_MIN_SAMPLES) {
-                       if (ca->curr_rtt > delay)
-                               ca->curr_rtt = delay;
-
                        ca->sample_cnt++;
                } else {
                        if (ca->curr_rtt > ca->delay_min +
index e7b8753..75ecf95 100644 (file)
@@ -25,7 +25,7 @@ struct bpf_iter__netlink {
        struct netlink_sock *sk;
 } __attribute__((preserve_access_index));
 
-static inline struct inode *SOCK_INODE(struct socket *socket)
+static __attribute__((noinline)) struct inode *SOCK_INODE(struct socket *socket)
 {
        return &container_of(socket, struct socket_alloc, socket)->vfs_inode;
 }
index 9365b68..5f645fd 100644 (file)
@@ -55,3 +55,25 @@ int BPF_PROG(test6, __u64 a, void *b, short c, int d, void * e, __u64 f)
                e == (void *)20 && f == 21;
        return 0;
 }
+
+struct bpf_fentry_test_t {
+       struct bpf_fentry_test_t *a;
+};
+
+__u64 test7_result = 0;
+SEC("fentry/bpf_fentry_test7")
+int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
+{
+       if (arg == 0)
+               test7_result = 1;
+       return 0;
+}
+
+__u64 test8_result = 0;
+SEC("fentry/bpf_fentry_test8")
+int BPF_PROG(test8, struct bpf_fentry_test_t *arg)
+{
+       if (arg->a == 0)
+               test8_result = 1;
+       return 0;
+}
index bd1e17d..0952aff 100644 (file)
@@ -56,3 +56,25 @@ int BPF_PROG(test6, __u64 a, void *b, short c, int d, void *e, __u64 f, int ret)
                e == (void *)20 && f == 21 && ret == 111;
        return 0;
 }
+
+struct bpf_fentry_test_t {
+       struct bpf_fentry_test *a;
+};
+
+__u64 test7_result = 0;
+SEC("fexit/bpf_fentry_test7")
+int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
+{
+       if (arg == 0)
+               test7_result = 1;
+       return 0;
+}
+
+__u64 test8_result = 0;
+SEC("fexit/bpf_fentry_test8")
+int BPF_PROG(test8, struct bpf_fentry_test_t *arg)
+{
+       if (arg->a == 0)
+               test8_result = 1;
+       return 0;
+}
index d5a5eeb..712df7b 100644 (file)
@@ -8,6 +8,10 @@
 char _license[] SEC("license") = "GPL";
 __u32 _version SEC("version") = 1;
 
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 4096
+#endif
+
 #define SOL_CUSTOM                     0xdeadbeef
 
 struct sockopt_sk {
@@ -28,12 +32,14 @@ int _getsockopt(struct bpf_sockopt *ctx)
        __u8 *optval = ctx->optval;
        struct sockopt_sk *storage;
 
-       if (ctx->level == SOL_IP && ctx->optname == IP_TOS)
+       if (ctx->level == SOL_IP && ctx->optname == IP_TOS) {
                /* Not interested in SOL_IP:IP_TOS;
                 * let next BPF program in the cgroup chain or kernel
                 * handle it.
                 */
+               ctx->optlen = 0; /* bypass optval>PAGE_SIZE */
                return 1;
+       }
 
        if (ctx->level == SOL_SOCKET && ctx->optname == SO_SNDBUF) {
                /* Not interested in SOL_SOCKET:SO_SNDBUF;
@@ -51,6 +57,26 @@ int _getsockopt(struct bpf_sockopt *ctx)
                return 1;
        }
 
+       if (ctx->level == SOL_IP && ctx->optname == IP_FREEBIND) {
+               if (optval + 1 > optval_end)
+                       return 0; /* EPERM, bounds check */
+
+               ctx->retval = 0; /* Reset system call return value to zero */
+
+               /* Always export 0x55 */
+               optval[0] = 0x55;
+               ctx->optlen = 1;
+
+               /* Userspace buffer is PAGE_SIZE * 2, but BPF
+                * program can only see the first PAGE_SIZE
+                * bytes of data.
+                */
+               if (optval_end - optval != PAGE_SIZE)
+                       return 0; /* EPERM, unexpected data size */
+
+               return 1;
+       }
+
        if (ctx->level != SOL_CUSTOM)
                return 0; /* EPERM, deny everything except custom level */
 
@@ -81,12 +107,14 @@ int _setsockopt(struct bpf_sockopt *ctx)
        __u8 *optval = ctx->optval;
        struct sockopt_sk *storage;
 
-       if (ctx->level == SOL_IP && ctx->optname == IP_TOS)
+       if (ctx->level == SOL_IP && ctx->optname == IP_TOS) {
                /* Not interested in SOL_IP:IP_TOS;
                 * let next BPF program in the cgroup chain or kernel
                 * handle it.
                 */
+               ctx->optlen = 0; /* bypass optval>PAGE_SIZE */
                return 1;
+       }
 
        if (ctx->level == SOL_SOCKET && ctx->optname == SO_SNDBUF) {
                /* Overwrite SO_SNDBUF value */
@@ -112,6 +140,28 @@ int _setsockopt(struct bpf_sockopt *ctx)
                return 1;
        }
 
+       if (ctx->level == SOL_IP && ctx->optname == IP_FREEBIND) {
+               /* Original optlen is larger than PAGE_SIZE. */
+               if (ctx->optlen != PAGE_SIZE * 2)
+                       return 0; /* EPERM, unexpected data size */
+
+               if (optval + 1 > optval_end)
+                       return 0; /* EPERM, bounds check */
+
+               /* Make sure we can trim the buffer. */
+               optval[0] = 0;
+               ctx->optlen = 1;
+
+               /* Usepace buffer is PAGE_SIZE * 2, but BPF
+                * program can only see the first PAGE_SIZE
+                * bytes of data.
+                */
+               if (optval_end - optval != PAGE_SIZE)
+                       return 0; /* EPERM, unexpected data size */
+
+               return 1;
+       }
+
        if (ctx->level != SOL_CUSTOM)
                return 0; /* EPERM, deny everything except custom level */
 
index 057036c..3dca4c2 100644 (file)
@@ -79,7 +79,7 @@ struct {
 
 struct {
        __uint(type, BPF_MAP_TYPE_ARRAY);
-       __uint(max_entries, 2);
+       __uint(max_entries, 3);
        __type(key, int);
        __type(value, int);
 } sock_skb_opts SEC(".maps");
@@ -94,6 +94,12 @@ struct {
 SEC("sk_skb1")
 int bpf_prog1(struct __sk_buff *skb)
 {
+       int *f, two = 2;
+
+       f = bpf_map_lookup_elem(&sock_skb_opts, &two);
+       if (f && *f) {
+               return *f;
+       }
        return skb->len;
 }
 
index 3308112..0ac0864 100644 (file)
@@ -27,7 +27,7 @@ int xdp_dummy_prog(struct xdp_md *ctx)
 /* valid program on DEVMAP entry via SEC name;
  * has access to egress and ingress ifindex
  */
-SEC("xdp_devmap")
+SEC("xdp_devmap/map_prog")
 int xdp_dummy_dm(struct xdp_md *ctx)
 {
        char fmt[] = "devmap redirect: dev %u -> dev %u len %u\n";
index 6a12a0e..754cf61 100644 (file)
@@ -789,19 +789,19 @@ static void test_sockmap(unsigned int tasks, void *data)
        }
 
        err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER);
-       if (err) {
+       if (!err) {
                printf("Failed empty parser prog detach\n");
                goto out_sockmap;
        }
 
        err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT);
-       if (err) {
+       if (!err) {
                printf("Failed empty verdict prog detach\n");
                goto out_sockmap;
        }
 
        err = bpf_prog_detach(fd, BPF_SK_MSG_VERDICT);
-       if (err) {
+       if (!err) {
                printf("Failed empty msg verdict prog detach\n");
                goto out_sockmap;
        }
@@ -1090,19 +1090,19 @@ static void test_sockmap(unsigned int tasks, void *data)
                assert(status == 0);
        }
 
-       err = bpf_prog_detach(map_fd_rx, __MAX_BPF_ATTACH_TYPE);
+       err = bpf_prog_detach2(parse_prog, map_fd_rx, __MAX_BPF_ATTACH_TYPE);
        if (!err) {
                printf("Detached an invalid prog type.\n");
                goto out_sockmap;
        }
 
-       err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
+       err = bpf_prog_detach2(parse_prog, map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
        if (err) {
                printf("Failed parser prog detach\n");
                goto out_sockmap;
        }
 
-       err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
+       err = bpf_prog_detach2(verdict_prog, map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
        if (err) {
                printf("Failed parser prog detach\n");
                goto out_sockmap;
index 37695fc..78789b2 100644 (file)
@@ -85,6 +85,7 @@ int txmsg_ktls_skb_drop;
 int txmsg_ktls_skb_redir;
 int ktls;
 int peek_flag;
+int skb_use_parser;
 
 static const struct option long_options[] = {
        {"help",        no_argument,            NULL, 'h' },
@@ -174,6 +175,7 @@ static void test_reset(void)
        txmsg_apply = txmsg_cork = 0;
        txmsg_ingress = txmsg_redir_skb = 0;
        txmsg_ktls_skb = txmsg_ktls_skb_drop = txmsg_ktls_skb_redir = 0;
+       skb_use_parser = 0;
 }
 
 static int test_start_subtest(const struct _test *t, struct sockmap_options *o)
@@ -1211,6 +1213,11 @@ run:
                }
        }
 
+       if (skb_use_parser) {
+               i = 2;
+               err = bpf_map_update_elem(map_fd[7], &i, &skb_use_parser, BPF_ANY);
+       }
+
        if (txmsg_drop)
                options->drop_expected = true;
 
@@ -1650,6 +1657,16 @@ static void test_txmsg_cork(int cgrp, struct sockmap_options *opt)
        test_send(opt, cgrp);
 }
 
+static void test_txmsg_ingress_parser(int cgrp, struct sockmap_options *opt)
+{
+       txmsg_pass = 1;
+       skb_use_parser = 512;
+       opt->iov_length = 256;
+       opt->iov_count = 1;
+       opt->rate = 2;
+       test_exec(cgrp, opt);
+}
+
 char *map_names[] = {
        "sock_map",
        "sock_map_txmsg",
@@ -1748,6 +1765,7 @@ struct _test test[] = {
        {"txmsg test pull-data", test_txmsg_pull},
        {"txmsg test pop-data", test_txmsg_pop},
        {"txmsg test push/pop data", test_txmsg_push_pop},
+       {"txmsg text ingress parser", test_txmsg_ingress_parser},
 };
 
 static int check_whitelist(struct _test *t, struct sockmap_options *opt)
index a4605b5..8ec1922 100755 (executable)
@@ -263,10 +263,16 @@ CASENO=0
 
 testcase() { # testfile
   CASENO=$((CASENO+1))
-  desc=`grep "^#[ \t]*description:" $1 | cut -f2 -d:`
+  desc=`grep "^#[ \t]*description:" $1 | cut -f2- -d:`
   prlog -n "[$CASENO]$INSTANCE$desc"
 }
 
+checkreq() { # testfile
+  requires=`grep "^#[ \t]*requires:" $1 | cut -f2- -d:`
+  # Use eval to pass quoted-patterns correctly.
+  eval check_requires "$requires"
+}
+
 test_on_instance() { # testfile
   grep -q "^#[ \t]*flags:.*instance" $1
 }
@@ -356,7 +362,8 @@ trap 'SIG_RESULT=$XFAIL' $SIG_XFAIL
 
 __run_test() { # testfile
   # setup PID and PPID, $$ is not updated.
-  (cd $TRACING_DIR; read PID _ < /proc/self/stat; set -e; set -x; initialize_ftrace; . $1)
+  (cd $TRACING_DIR; read PID _ < /proc/self/stat; set -e; set -x;
+   checkreq $1; initialize_ftrace; . $1)
   [ $? -ne 0 ] && kill -s $SIG_FAIL $SIG_PID
 }
 
index 3b1f45e..13b4dab 100644 (file)
@@ -1,9 +1,8 @@
 #!/bin/sh
 # description: Snapshot and tracing setting
+# requires: snapshot
 # flags: instance
 
-[ ! -f snapshot ] && exit_unsupported
-
 echo "Set tracing off"
 echo 0 > tracing_on
 
index 5058fbc..435d07b 100644 (file)
@@ -1,10 +1,9 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: trace_pipe and trace_marker
+# requires: trace_marker
 # flags: instance
 
-[ ! -f trace_marker ] && exit_unsupported
-
 echo "test input 1" > trace_marker
 
 : "trace interface never consume the ring buffer"
index 801ecb6..e52e470 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Test ftrace direct functions against kprobes
+# requires: kprobe_events
 
 rmmod ftrace-direct ||:
 if ! modprobe ftrace-direct ; then
@@ -8,11 +9,6 @@ if ! modprobe ftrace-direct ; then
   exit_unresolved;
 fi
 
-if [ ! -f kprobe_events ]; then
-       echo "No kprobe_events file -please build CONFIG_KPROBE_EVENTS"
-       exit_unresolved;
-fi
-
 echo "Let the module run a little"
 sleep 1
 
index c6d8387..68550f9 100644 (file)
@@ -1,11 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Generic dynamic event - add/remove kprobe events
-
-[ -f dynamic_events ] || exit_unsupported
-
-grep -q "place: \[<module>:\]<symbol>" README || exit_unsupported
-grep -q "place (kretprobe): \[<module>:\]<symbol>" README || exit_unsupported
+# requires: dynamic_events "place: [<module>:]<symbol>":README "place (kretprobe): [<module>:]<symbol>":README
 
 echo 0 > events/enable
 echo > dynamic_events
index 62b77b5..2b94611 100644 (file)
@@ -1,10 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Generic dynamic event - add/remove synthetic events
-
-[ -f dynamic_events ] || exit_unsupported
-
-grep -q "s:\[synthetic/\]" README || exit_unsupported
+# requires: dynamic_events "s:[synthetic/]":README
 
 echo 0 > events/enable
 echo > dynamic_events
index e084210..c969be9 100644 (file)
@@ -1,16 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Generic dynamic event - selective clear (compatibility)
-
-[ -f dynamic_events ] || exit_unsupported
-
-grep -q "place: \[<module>:\]<symbol>" README || exit_unsupported
-grep -q "place (kretprobe): \[<module>:\]<symbol>" README || exit_unsupported
-
-grep -q "s:\[synthetic/\]" README || exit_unsupported
-
-[ -f synthetic_events ] || exit_unsupported
-[ -f kprobe_events ] || exit_unsupported
+# requires: dynamic_events kprobe_events synthetic_events "place: [<module>:]<symbol>":README "place (kretprobe): [<module>:]<symbol>":README "s:[synthetic/]":README
 
 echo 0 > events/enable
 echo > dynamic_events
index 901922e..16d543e 100644 (file)
@@ -1,13 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Generic dynamic event - generic clear event
-
-[ -f dynamic_events ] || exit_unsupported
-
-grep -q "place: \[<module>:\]<symbol>" README || exit_unsupported
-grep -q "place (kretprobe): \[<module>:\]<symbol>" README || exit_unsupported
-
-grep -q "s:\[synthetic/\]" README || exit_unsupported
+# requires: dynamic_events "place: [<module>:]<symbol>":README "place (kretprobe): [<module>:]<symbol>":README "s:[synthetic/]":README
 
 echo 0 > events/enable
 echo > dynamic_events
index dfb0d51..cfe5bd2 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event tracing - enable/disable with event level files
+# requires: set_event events/sched
 # flags: instance
 
 do_reset() {
@@ -13,11 +14,6 @@ fail() { #msg
     exit_fail
 }
 
-if [ ! -f set_event -o ! -d events/sched ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
 echo 'sched:sched_switch' > set_event
 
 yield
index f0f366f..e6eb78f 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event tracing - restricts events based on pid notrace filtering
+# requires: set_event events/sched set_event_pid set_event_notrace_pid
 # flags: instance
 
 do_reset() {
@@ -56,16 +57,6 @@ enable_events() {
     echo 1 > tracing_on
 }
 
-if [ ! -f set_event -o ! -d events/sched ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f set_event_pid -o ! -f set_event_notrace_pid ]; then
-    echo "event pid notrace filtering is not supported"
-    exit_unsupported
-fi
-
 echo 0 > options/event-fork
 
 do_reset
index f9cb214..7f5f97d 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event tracing - restricts events based on pid
+# requires: set_event set_event_pid events/sched
 # flags: instance
 
 do_reset() {
@@ -16,16 +17,6 @@ fail() { #msg
     exit_fail
 }
 
-if [ ! -f set_event -o ! -d events/sched ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f set_event_pid ]; then
-    echo "event pid filtering is not supported"
-    exit_unsupported
-fi
-
 echo 0 > options/event-fork
 
 echo 1 > events/sched/sched_switch/enable
index 83a8c57..b1ede62 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event tracing - enable/disable with subsystem level files
+# requires: set_event events/sched/enable
 # flags: instance
 
 do_reset() {
@@ -13,11 +14,6 @@ fail() { #msg
     exit_fail
 }
 
-if [ ! -f set_event -o ! -d events/sched ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
 echo 'sched:*' > set_event
 
 yield
index 84d7bda..93c10ea 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event tracing - enable/disable with top level files
+# requires: available_events set_event events/enable
 
 do_reset() {
     echo > set_event
@@ -12,11 +13,6 @@ fail() { #msg
     exit_fail
 }
 
-if [ ! -f available_events -o ! -f set_event -o ! -d events ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
 echo '*:*' > set_event
 
 yield
index f598538..cf3ea42 100644 (file)
@@ -1,17 +1,11 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: ftrace - function graph filters with stack tracer
+# requires: stack_trace set_ftrace_filter function_graph:tracer
 
 # Make sure that function graph filtering works, and is not
 # affected by other tracers enabled (like stack tracer)
 
-if ! grep -q function_graph available_tracers; then
-    echo "no function graph tracer configured"
-    exit_unsupported
-fi
-
-check_filter_file set_ftrace_filter
-
 do_reset() {
     if [ -e /proc/sys/kernel/stack_tracer_enabled ]; then
            echo 0 > /proc/sys/kernel/stack_tracer_enabled
@@ -37,12 +31,6 @@ fi
 
 echo function_graph > current_tracer
 
-if [ ! -f stack_trace ]; then
-    echo "Stack tracer not configured"
-    do_reset
-    exit_unsupported;
-fi
-
 echo "Now testing with stack tracer"
 
 echo 1 > /proc/sys/kernel/stack_tracer_enabled
index d610f47..b3ccdae 100644 (file)
@@ -1,16 +1,10 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: ftrace - function graph filters
+# requires: set_ftrace_filter function_graph:tracer
 
 # Make sure that function graph filtering works
 
-if ! grep -q function_graph available_tracers; then
-    echo "no function graph tracer configured"
-    exit_unsupported
-fi
-
-check_filter_file set_ftrace_filter
-
 fail() { # msg
     echo $1
     exit_fail
index 28936f4..4b994b6 100644 (file)
@@ -1,16 +1,10 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: ftrace - function glob filters
+# requires: set_ftrace_filter function:tracer
 
 # Make sure that function glob matching filter works.
 
-if ! grep -q function available_tracers; then
-    echo "no function tracer configured"
-    exit_unsupported
-fi
-
-check_filter_file set_ftrace_filter
-
 disable_tracing
 clear_trace
 
index 71db68a..acb17ce 100644 (file)
@@ -1,22 +1,11 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: ftrace - function pid notrace filters
+# requires: set_ftrace_notrace_pid set_ftrace_filter function:tracer
 # flags: instance
 
 # Make sure that function pid matching filter with notrace works.
 
-if ! grep -q function available_tracers; then
-    echo "no function tracer configured"
-    exit_unsupported
-fi
-
-if [ ! -f set_ftrace_notrace_pid ]; then
-    echo "set_ftrace_notrace_pid not found? Is function tracer not set?"
-    exit_unsupported
-fi
-
-check_filter_file set_ftrace_filter
-
 do_function_fork=1
 
 if [ ! -f options/function-fork ]; then
index d58403c..9f0a968 100644 (file)
@@ -1,23 +1,12 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: ftrace - function pid filters
+# requires: set_ftrace_pid set_ftrace_filter function:tracer
 # flags: instance
 
 # Make sure that function pid matching filter works.
 # Also test it on an instance directory
 
-if ! grep -q function available_tracers; then
-    echo "no function tracer configured"
-    exit_unsupported
-fi
-
-if [ ! -f set_ftrace_pid ]; then
-    echo "set_ftrace_pid not found? Is function tracer not set?"
-    exit_unsupported
-fi
-
-check_filter_file set_ftrace_filter
-
 do_function_fork=1
 
 if [ ! -f options/function-fork ]; then
index b2aff78..0f41e44 100644 (file)
@@ -1,10 +1,9 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: ftrace - stacktrace filter command
+# requires: set_ftrace_filter
 # flags: instance
 
-check_filter_file set_ftrace_filter
-
 echo _do_fork:stacktrace >> set_ftrace_filter
 
 grep -q "_do_fork:stacktrace:unlimited" set_ftrace_filter
index 71fa3f4..0c6cf77 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: ftrace - function trace with cpumask
+# requires: function:tracer
 
 if ! which nproc ; then
   nproc() {
@@ -15,11 +16,6 @@ if [ $NP -eq 1 ] ;then
   exit_unresolved
 fi
 
-if ! grep -q "function" available_tracers ; then
-  echo "Function trace is not enabled"
-  exit_unsupported
-fi
-
 ORIG_CPUMASK=`cat tracing_cpumask`
 
 do_reset() {
index e9b1fd5..3145b0f 100644 (file)
@@ -3,15 +3,14 @@
 # description: ftrace - test for function event triggers
 # flags: instance
 #
+# The triggers are set within the set_ftrace_filter file
+# requires: set_ftrace_filter
+#
 # Ftrace allows to add triggers to functions, such as enabling or disabling
 # tracing, enabling or disabling trace events, or recording a stack trace
 # within the ring buffer.
 #
 # This test is designed to test event triggers
-#
-
-# The triggers are set within the set_ftrace_filter file
-check_filter_file set_ftrace_filter
 
 do_reset() {
     reset_ftrace_filter
index 1a4b4a4..37c8feb 100644 (file)
@@ -1,8 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: ftrace - function trace on module
-
-check_filter_file set_ftrace_filter
+# requires: set_ftrace_filter
 
 : "mod: allows to filter a non exist function"
 echo 'non_exist_func:mod:non_exist_module' > set_ftrace_filter
index 0d50105..4daeffb 100644 (file)
@@ -1,8 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: ftrace - function profiling
-
-[ ! -f function_profile_enabled ] && exit_unsupported
+# requires: function_profile_enabled
 
 : "Enable function profile"
 echo 1 > function_profile_enabled
index a3dadb6..1dbd766 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: ftrace - function profiler with function tracing
+# requires: function_profile_enabled set_ftrace_filter function_graph:tracer
 
 # There was a bug after a rewrite of the ftrace infrastructure that
 # caused the function_profiler not to be able to run with the function
 # This test triggers those bugs on those kernels.
 #
 # We need function_graph and profiling to to run this test
-if ! grep -q function_graph available_tracers; then
-    echo "no function graph tracer configured"
-    exit_unsupported;
-fi
-
-check_filter_file set_ftrace_filter
-
-if [ ! -f function_profile_enabled ]; then
-    echo "function_profile_enabled not found, function profiling enabled?"
-    exit_unsupported
-fi
 
 fail() { # mesg
     echo $1
index 70bad44..e96e279 100644 (file)
@@ -2,6 +2,9 @@
 # SPDX-License-Identifier: GPL-2.0
 # description: ftrace - test reading of set_ftrace_filter
 #
+# The triggers are set within the set_ftrace_filter file
+# requires: set_ftrace_filter
+#
 # The set_ftrace_filter file of ftrace is used to list functions as well as
 # triggers (probes) attached to functions. The code to read this file is not
 # straight forward and has had various bugs in the past. This test is designed
@@ -9,9 +12,6 @@
 # file in various ways (cat vs dd).
 #
 
-# The triggers are set within the set_ftrace_filter file
-check_filter_file set_ftrace_filter
-
 fail() { # mesg
     echo $1
     exit_fail
index 51e9e80..61264e4 100644 (file)
@@ -1,15 +1,9 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: ftrace - Max stack tracer
+# requires: stack_trace stack_trace_filter
 # Test the basic function of max-stack usage tracing
 
-if [ ! -f stack_trace ]; then
-  echo "Max stack tracer is not supported - please make CONFIG_STACK_TRACER=y"
-  exit_unsupported
-fi
-
-check_filter_file stack_trace_filter
-
 echo > stack_trace_filter
 echo 0 > stack_max_size
 echo 1 > /proc/sys/kernel/stack_tracer_enabled
index 3ed173f..aee2228 100644 (file)
@@ -3,6 +3,9 @@
 # description: ftrace - test for function traceon/off triggers
 # flags: instance
 #
+# The triggers are set within the set_ftrace_filter file
+# requires: set_ftrace_filter
+#
 # Ftrace allows to add triggers to functions, such as enabling or disabling
 # tracing, enabling or disabling trace events, or recording a stack trace
 # within the ring buffer.
@@ -10,9 +13,6 @@
 # This test is designed to test enabling and disabling tracing triggers
 #
 
-# The triggers are set within the set_ftrace_filter file
-check_filter_file set_ftrace_filter
-
 fail() { # mesg
     echo $1
     exit_fail
index 2346582..6c19062 100644 (file)
@@ -1,21 +1,15 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: ftrace - test tracing error log support
+# event tracing is currently the only ftrace tracer that uses the
+# tracing error_log, hence this check
+# requires: set_event error_log
 
 fail() { #msg
     echo $1
     exit_fail
 }
 
-# event tracing is currently the only ftrace tracer that uses the
-# tracing error_log, hence this check
-if [ ! -f set_event ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-[ -f error_log ] || exit_unsupported
-
 ftrace_errlog_check 'event filter parse error' '((sig >= 10 && sig < 15) || dsig ^== 17) && comm != bash' 'events/signal/signal_generate/filter'
 
 exit 0
index 697c77e..c5dec55 100644 (file)
@@ -1,10 +1,3 @@
-check_filter_file() { # check filter file introduced by dynamic ftrace
-    if [ ! -f "$1" ]; then
-        echo "$1 not found? Is dynamic ftrace not set?"
-        exit_unsupported
-    fi
-}
-
 clear_trace() { # reset trace output
     echo > trace
 }
@@ -113,6 +106,27 @@ initialize_ftrace() { # Reset ftrace to initial-state
     enable_tracing
 }
 
+check_requires() { # Check required files and tracers
+    for i in "$@" ; do
+        r=${i%:README}
+        t=${i%:tracer}
+        if [ $t != $i ]; then
+            if ! grep -wq $t available_tracers ; then
+                echo "Required tracer $t is not configured."
+                exit_unsupported
+            fi
+        elif [ $r != $i ]; then
+            if ! grep -Fq "$r" README ; then
+                echo "Required feature pattern \"$r\" is not in README."
+                exit_unsupported
+            fi
+        elif [ ! -e $i ]; then
+            echo "Required feature interface $i doesn't exist."
+            exit_unsupported
+        fi
+    done
+}
+
 LOCALHOST=127.0.0.1
 
 yield() {
index 4fa0f79..0eb47fb 100644 (file)
@@ -1,11 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Test creation and deletion of trace instances while setting an event
-
-if [ ! -d instances ] ; then
-    echo "no instance directory with this kernel"
-    exit_unsupported;
-fi
+# requires: instances
 
 fail() { # mesg
     rmdir foo 2>/dev/null
index b846512..607521d 100644 (file)
@@ -1,11 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Test creation and deletion of trace instances
-
-if [ ! -d instances ] ; then
-    echo "no instance directory with this kernel"
-    exit_unsupported;
-fi
+# requires: instances
 
 fail() { # mesg
     rmdir x y z 2>/dev/null
index bb1eb5a..eba858c 100644 (file)
@@ -1,8 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Kprobe dynamic event - adding and removing
-
-[ -f kprobe_events ] || exit_unsupported # this is configurable
+# requires: kprobe_events
 
 echo p:myevent _do_fork > kprobe_events
 grep myevent kprobe_events
index 442c1a8..d10bf4f 100644 (file)
@@ -1,8 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Kprobe dynamic event - busy event check
-
-[ -f kprobe_events ] || exit_unsupported
+# requires: kprobe_events
 
 echo p:myevent _do_fork > kprobe_events
 test -d events/kprobes/myevent
index bcdecf8..61f2ac4 100644 (file)
@@ -1,8 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Kprobe dynamic event with arguments
-
-[ -f kprobe_events ] || exit_unsupported # this is configurable
+# requires: kprobe_events
 
 echo 'p:testprobe _do_fork $stack $stack0 +0($stack)' > kprobe_events
 grep testprobe kprobe_events | grep -q 'arg1=\$stack arg2=\$stack0 arg3=+0(\$stack)'
index 15c1f70..05aaeed 100644 (file)
@@ -1,8 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Kprobe event with comm arguments
-
-[ -f kprobe_events ] || exit_unsupported # this is configurable
+# requires: kprobe_events
 
 grep -A1 "fetcharg:" README | grep -q "\$comm" || exit_unsupported # this is too old
 
index 46e7744..b5fa054 100644 (file)
@@ -1,8 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Kprobe event string type argument
-
-[ -f kprobe_events ] || exit_unsupported # this is configurable
+# requires: kprobe_events
 
 case `uname -m` in
 x86_64)
index 2b6dd33..b8c75a3 100644 (file)
@@ -1,8 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Kprobe event symbol argument
-
-[ -f kprobe_events ] || exit_unsupported # this is configurable
+# requires: kprobe_events
 
 SYMBOL="linux_proc_banner"
 
index 6f0f199..474ca1a 100644 (file)
@@ -1,10 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Kprobe event argument syntax
-
-[ -f kprobe_events ] || exit_unsupported # this is configurable
-
-grep "x8/16/32/64" README > /dev/null || exit_unsupported # version issue
+# requires: kprobe_events "x8/16/32/64":README
 
 PROBEFUNC="vfs_read"
 GOODREG=
index 81490ec..0610e0b 100644 (file)
@@ -1,10 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Kprobes event arguments with types
-
-[ -f kprobe_events ] || exit_unsupported # this is configurable
-
-grep "x8/16/32/64" README > /dev/null || exit_unsupported # version issue
+# requires: kprobe_events "x8/16/32/64":README
 
 gen_event() { # Bitsize
   echo "p:testprobe _do_fork \$stack0:s$1 \$stack0:u$1 \$stack0:x$1 \$stack0:b4@4/$1"
index 0f60087..a30a9c0 100644 (file)
@@ -1,10 +1,8 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Kprobe event user-memory access
+# requires: kprobe_events '$arg<N>':README
 
-[ -f kprobe_events ] || exit_unsupported # this is configurable
-
-grep -q '\$arg<N>' README || exit_unresolved # depends on arch
 grep -A10 "fetcharg:" README | grep -q 'ustring' || exit_unsupported
 grep -A10 "fetcharg:" README | grep -q '\[u\]<offset>' || exit_unsupported
 
index 3ff2367..1f6981e 100644 (file)
@@ -1,8 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Kprobe event auto/manual naming
-
-[ -f kprobe_events ] || exit_unsupported # this is configurable
+# requires: kprobe_events
 
 :;: "Add an event on function without name" ;:
 
index df50728..81d8b58 100644 (file)
@@ -1,11 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Kprobe dynamic event with function tracer
-
-[ -f kprobe_events ] || exit_unsupported # this is configurable
-grep "function" available_tracers || exit_unsupported # this is configurable
-
-check_filter_file set_ftrace_filter
+# requires: kprobe_events stack_trace_filter function:tracer
 
 # prepare
 echo nop > current_tracer
index d861bd7..7e74ee1 100644 (file)
@@ -1,8 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Kprobe dynamic event - probing module
-
-[ -f kprobe_events ] || exit_unsupported # this is configurable
+# requires: kprobe_events
 
 rmmod trace-printk ||:
 if ! modprobe trace-printk ; then
index 44494ba..366b7e1 100644 (file)
@@ -1,10 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Create/delete multiprobe on kprobe event
-
-[ -f kprobe_events ] || exit_unsupported
-
-grep -q "Create/append/" README || exit_unsupported
+# requires: kprobe_events "Create/append/":README
 
 # Choose 2 symbols for target
 SYM1=_do_fork
index eb0f4ab..b4d8346 100644 (file)
@@ -1,10 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Kprobe event parser error log check
-
-[ -f kprobe_events ] || exit_unsupported # this is configurable
-
-[ -f error_log ] || exit_unsupported
+# requires: kprobe_events error_log
 
 check_error() { # command-with-error-pos-by-^
     ftrace_errlog_check 'trace_kprobe' "$1" 'kprobe_events'
index ac9ab4a..523fde6 100644 (file)
@@ -1,8 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Kretprobe dynamic event with arguments
-
-[ -f kprobe_events ] || exit_unsupported # this is configurable
+# requires: kprobe_events
 
 # Add new kretprobe event
 echo 'r:testprobe2 _do_fork $retval' > kprobe_events
index 8e05b17..4f0b268 100644 (file)
@@ -1,9 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Kretprobe dynamic event with maxactive
-
-[ -f kprobe_events ] || exit_unsupported # this is configurable
-grep -q 'r\[maxactive\]' README || exit_unsupported # this is older version
+# requires: kprobe_events 'r[maxactive]':README
 
 # Test if we successfully reject unknown messages
 if echo 'a:myprobeaccept inet_csk_accept' > kprobe_events; then false; else true; fi
index 6e3dbe5..312d237 100644 (file)
@@ -1,8 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Register/unregister many kprobe events
-
-[ -f kprobe_events ] || exit_unsupported # this is configurable
+# requires: kprobe_events
 
 # ftrace fentry skip size depends on the machine architecture.
 # Currently HAVE_KPROBES_ON_FTRACE defined on x86 and powerpc64le
index a902aa0..624269c 100644 (file)
@@ -1,8 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Kprobe events - probe points
-
-[ -f kprobe_events ] || exit_unsupported # this is configurable
+# requires: kprobe_events
 
 TARGET_FUNC=tracefs_create_dir
 
index 0384b52..ff6c44a 100644 (file)
@@ -1,8 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Kprobe dynamic event - adding and removing
-
-[ -f kprobe_events ] || exit_unsupported # this is configurable
+# requires: kprobe_events
 
 ! grep -q 'myevent' kprobe_profile
 echo p:myevent _do_fork > kprobe_events
index 14229d5..7b5b60c 100644 (file)
@@ -1,10 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Uprobe event parser error log check
-
-[ -f uprobe_events ] || exit_unsupported # this is configurable
-
-[ -f error_log ] || exit_unsupported
+# requires: uprobe_events error_log
 
 check_error() { # command-with-error-pos-by-^
     ftrace_errlog_check 'trace_uprobe' "$1" 'uprobe_events'
index 2b82c80..22bff12 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: test for the preemptirqsoff tracer
+# requires: preemptoff:tracer irqsoff:tracer
 
 MOD=preemptirq_delay_test
 
@@ -27,9 +28,6 @@ unres() { #msg
 modprobe $MOD || unres "$MOD module not available"
 rmmod $MOD
 
-grep -q "preemptoff" available_tracers || unsup "preemptoff tracer not enabled"
-grep -q "irqsoff" available_tracers || unsup "irqsoff tracer not enabled"
-
 reset_tracer
 
 # Simulate preemptoff section for half a second couple of times
index e1a5d14..2cd8947 100644 (file)
@@ -1,6 +1,10 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: %HERE DESCRIBE WHAT THIS DOES%
+# requires: %HERE LIST THE REQUIRED FILES, TRACERS OR README-STRINGS%
+# The required tracer needs :tracer suffix, e.g. function:tracer
+# The required README string needs :README suffix, e.g. "x8/16/32/64":README
+# and the README string is treated as a fixed-string instead of regexp pattern.
 # you have to add ".tc" extention for your testcase file
 # Note that all tests are run with "errexit" option.
 
index b0893d7..11be10e 100644 (file)
@@ -1,17 +1,13 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Test wakeup tracer
+# requires: wakeup:tracer
 
 if ! which chrt ; then
   echo "chrt is not found. This test requires nice command."
   exit_unresolved
 fi
 
-if ! grep -wq "wakeup" available_tracers ; then
-  echo "wakeup tracer is not supported"
-  exit_unsupported
-fi
-
 echo wakeup > current_tracer
 echo 1 > tracing_on
 echo 0 > tracing_max_latency
index b9b6669..3a77198 100644 (file)
@@ -1,17 +1,13 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: Test wakeup RT tracer
+# requires: wakeup_rt:tracer
 
 if ! which chrt ; then
   echo "chrt is not found. This test requires chrt command."
   exit_unresolved
 fi
 
-if ! grep -wq "wakeup_rt" available_tracers ; then
-  echo "wakeup_rt tracer is not supported"
-  exit_unsupported
-fi
-
 echo wakeup_rt > current_tracer
 echo 1 > tracing_on
 echo 0 > tracing_max_latency
index 3f2aee1..1590d6b 100644 (file)
@@ -1,24 +1,13 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test inter-event histogram trigger expected fail actions
+# requires: set_event snapshot "snapshot()":README
 
 fail() { #msg
     echo $1
     exit_fail
 }
 
-if [ ! -f set_event ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f snapshot ]; then
-    echo "snapshot is not supported"
-    exit_unsupported
-fi
-
-grep -q "snapshot()" README || exit_unsupported # version issue
-
 echo "Test expected snapshot action failure"
 
 echo 'hist:keys=comm:onmatch(sched.sched_wakeup).snapshot()' >> events/sched/sched_waking/trigger && exit_fail
index e232059..41119e0 100644 (file)
@@ -1,27 +1,13 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test field variable support
+# requires: set_event synthetic_events events/sched/sched_process_fork/hist
 
 fail() { #msg
     echo $1
     exit_fail
 }
 
-if [ ! -f set_event ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f synthetic_events ]; then
-    echo "synthetic event is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/sched/sched_process_fork/hist ]; then
-    echo "hist trigger is not supported"
-    exit_unsupported
-fi
-
 echo "Test field variable support"
 
 echo 'wakeup_latency u64 lat; pid_t pid; int prio; char comm[16]' > synthetic_events
index 07cfcb8..7449a4b 100644 (file)
@@ -1,27 +1,13 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test inter-event combined histogram trigger
+# requires: set_event synthetic_events events/sched/sched_process_fork/hist
 
 fail() { #msg
     echo $1
     exit_fail
 }
 
-if [ ! -f set_event ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f synthetic_events ]; then
-    echo "synthetic event is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/sched/sched_process_fork/hist ]; then
-    echo "hist trigger is not supported"
-    exit_unsupported
-fi
-
 echo "Test create synthetic event"
 
 echo 'waking_latency  u64 lat pid_t pid' > synthetic_events
index 73e413c..3ad6e3f 100644 (file)
@@ -1,27 +1,13 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test multiple actions on hist trigger
+# requires: set_event synthetic_events events/sched/sched_process_fork/hist
 
 fail() { #msg
     echo $1
     exit_fail
 }
 
-if [ ! -f set_event ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f synthetic_events ]; then
-    echo "synthetic event is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/sched/sched_process_fork/hist ]; then
-    echo "hist trigger is not supported"
-    exit_unsupported
-fi
-
 echo "Test multiple actions on hist trigger"
 echo 'wakeup_latency u64 lat; pid_t pid' >> synthetic_events
 TRIGGER1=events/sched/sched_wakeup/trigger
index c80007a..adaabb8 100644 (file)
@@ -1,19 +1,13 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test inter-event histogram trigger onchange action
+# requires: set_event "onchange(var)":README
 
 fail() { #msg
     echo $1
     exit_fail
 }
 
-if [ ! -f set_event ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-grep -q "onchange(var)" README || exit_unsupported # version issue
-
 echo "Test onchange action"
 
 echo 'hist:keys=comm:newprio=prio:onchange($newprio).save(comm,prio) if comm=="ping"' >> events/sched/sched_waking/trigger
index ebe0ad8..20e3947 100644 (file)
@@ -1,27 +1,13 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test inter-event histogram trigger onmatch action
+# requires: set_event synthetic_events events/sched/sched_process_fork/hist
 
 fail() { #msg
     echo $1
     exit_fail
 }
 
-if [ ! -f set_event ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f synthetic_events ]; then
-    echo "synthetic event is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/sched/sched_process_fork/hist ]; then
-    echo "hist trigger is not supported"
-    exit_unsupported
-fi
-
 echo "Test create synthetic event"
 
 echo 'wakeup_latency  u64 lat pid_t pid char comm[16]' > synthetic_events
index 2a2ef76..f4b03ab 100644 (file)
@@ -1,27 +1,13 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test inter-event histogram trigger onmatch-onmax action
+# requires: set_event synthetic_events events/sched/sched_process_fork/hist
 
 fail() { #msg
     echo $1
     exit_fail
 }
 
-if [ ! -f set_event ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f synthetic_events ]; then
-    echo "synthetic event is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/sched/sched_process_fork/hist ]; then
-    echo "hist trigger is not supported"
-    exit_unsupported
-fi
-
 echo "Test create synthetic event"
 
 echo 'wakeup_latency  u64 lat pid_t pid char comm[16]' > synthetic_events
index 98d73bf..71c9b59 100644 (file)
@@ -1,27 +1,13 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test inter-event histogram trigger onmax action
+# requires: set_event synthetic_events events/sched/sched_process_fork/hist
 
 fail() { #msg
     echo $1
     exit_fail
 }
 
-if [ ! -f set_event ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f synthetic_events ]; then
-    echo "synthetic event is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/sched/sched_process_fork/hist ]; then
-    echo "hist trigger is not supported"
-    exit_unsupported
-fi
-
 echo "Test create synthetic event"
 
 echo 'wakeup_latency  u64 lat pid_t pid char comm[16]' > synthetic_events
index 01b01b9..67fa328 100644 (file)
@@ -1,31 +1,13 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test inter-event histogram trigger snapshot action
+# requires: set_event snapshot events/sched/sched_process_fork/hist "onchange(var)":README "snapshot()":README
 
 fail() { #msg
     echo $1
     exit_fail
 }
 
-if [ ! -f set_event ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/sched/sched_process_fork/hist ]; then
-    echo "hist trigger is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f snapshot ]; then
-    echo "snapshot is not supported"
-    exit_unsupported
-fi
-
-grep -q "onchange(var)" README || exit_unsupported # version issue
-
-grep -q "snapshot()" README || exit_unsupported # version issue
-
 echo "Test snapshot action"
 
 echo 1 > events/sched/enable
index df44b14..a152b55 100644 (file)
@@ -1,22 +1,13 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test synthetic event create remove
+# requires: set_event synthetic_events
 
 fail() { #msg
     echo $1
     exit_fail
 }
 
-if [ ! -f set_event ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f synthetic_events ]; then
-    echo "synthetic event is not supported"
-    exit_unsupported
-fi
-
 echo "Test create synthetic event"
 
 echo 'wakeup_latency  u64 lat pid_t pid char comm[16]' > synthetic_events
index 88e6c3f..59216f3 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test synthetic_events syntax parser
+# requires: set_event synthetic_events
 
 do_reset() {
     reset_trigger
@@ -14,16 +15,6 @@ fail() { #msg
     exit_fail
 }
 
-if [ ! -f set_event ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f synthetic_events ]; then
-    echo "synthetic event is not supported"
-    exit_unsupported
-fi
-
 reset_tracer
 do_reset
 
index c3baa48..c126d23 100644 (file)
@@ -1,29 +1,13 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test inter-event histogram trigger trace action
+# requires: set_event synthetic_events events/sched/sched_process_fork/hist "trace(<synthetic_event>":README
 
 fail() { #msg
     echo $1
     exit_fail
 }
 
-if [ ! -f set_event ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f synthetic_events ]; then
-    echo "synthetic event is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/sched/sched_process_fork/hist ]; then
-    echo "hist trigger is not supported"
-    exit_unsupported
-fi
-
-grep -q "trace(<synthetic_event>" README || exit_unsupported # version issue
-
 echo "Test create synthetic event"
 
 echo 'wakeup_latency  u64 lat pid_t pid char comm[16]' > synthetic_events
index eddb51e..c226ace 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test event enable/disable trigger
+# requires: set_event events/sched/sched_process_fork/trigger
 # flags: instance
 
 fail() { #msg
@@ -8,16 +9,6 @@ fail() { #msg
     exit_fail
 }
 
-if [ ! -f set_event -o ! -d events/sched ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/sched/sched_process_fork/trigger ]; then
-    echo "event trigger is not supported"
-    exit_unsupported
-fi
-
 FEATURE=`grep enable_event events/sched/sched_process_fork/trigger`
 if [ -z "$FEATURE" ]; then
     echo "event enable/disable trigger is not supported"
index 2dcc229..d9a198c 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test trigger filter
+# requires: set_event events/sched/sched_process_fork/trigger
 # flags: instance
 
 fail() { #msg
@@ -8,16 +9,6 @@ fail() { #msg
     exit_fail
 }
 
-if [ ! -f set_event -o ! -d events/sched ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/sched/sched_process_fork/trigger ]; then
-    echo "event trigger is not supported"
-    exit_unsupported
-fi
-
 echo "Test trigger filter"
 echo 1 > tracing_on
 echo 'traceoff if child_pid == 0' > events/sched/sched_process_fork/trigger
index fab4431..4562e13 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test histogram modifiers
+# requires: set_event events/sched/sched_process_fork/trigger events/sched/sched_process_fork/hist
 # flags: instance
 
 fail() { #msg
@@ -8,21 +9,6 @@ fail() { #msg
     exit_fail
 }
 
-if [ ! -f set_event -o ! -d events/sched ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/sched/sched_process_fork/trigger ]; then
-    echo "event trigger is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/sched/sched_process_fork/hist ]; then
-    echo "hist trigger is not supported"
-    exit_unsupported
-fi
-
 echo "Test histogram with execname modifier"
 
 echo 'hist:keys=common_pid.execname' > events/sched/sched_process_fork/trigger
index d44087a..52cfe78 100644 (file)
@@ -1,23 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test histogram parser errors
-
-if [ ! -f set_event -o ! -d events/kmem ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/kmem/kmalloc/trigger ]; then
-    echo "event trigger is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/kmem/kmalloc/hist ]; then
-    echo "hist trigger is not supported"
-    exit_unsupported
-fi
-
-[ -f error_log ] || exit_unsupported
+# requires: set_event events/kmem/kmalloc/trigger events/kmem/kmalloc/hist error_log
 
 check_error() { # command-with-error-pos-by-^
     ftrace_errlog_check 'hist:kmem:kmalloc' "$1" 'events/kmem/kmalloc/trigger'
index 177e8d4..2950bfb 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test histogram trigger
+# requires: set_event events/sched/sched_process_fork/trigger events/sched/sched_process_fork/hist
 # flags: instance
 
 fail() { #msg
@@ -8,22 +9,7 @@ fail() { #msg
     exit_fail
 }
 
-if [ ! -f set_event -o ! -d events/sched ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/sched/sched_process_fork/trigger ]; then
-    echo "event trigger is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/sched/sched_process_fork/hist ]; then
-    echo "hist trigger is not supported"
-    exit_unsupported
-fi
-
-echo "Test histogram basic tigger"
+echo "Test histogram basic trigger"
 
 echo 'hist:keys=parent_pid:vals=child_pid' > events/sched/sched_process_fork/trigger
 for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
index 68ff3f4..7129b52 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test multiple histogram triggers
+# requires: set_event events/sched/sched_process_fork/trigger events/sched/sched_process_fork/hist
 # flags: instance
 
 fail() { #msg
@@ -8,21 +9,6 @@ fail() { #msg
     exit_fail
 }
 
-if [ ! -f set_event -o ! -d events/sched ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/sched/sched_process_fork/trigger ]; then
-    echo "event trigger is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/sched/sched_process_fork/hist ]; then
-    echo "hist trigger is not supported"
-    exit_unsupported
-fi
-
 echo "Test histogram multiple triggers"
 
 echo 'hist:keys=parent_pid:vals=child_pid' > events/sched/sched_process_fork/trigger
index ac73850..33f5bde 100644 (file)
@@ -1,27 +1,13 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test snapshot-trigger
+# requires: set_event events/sched/sched_process_fork/trigger snapshot
 
 fail() { #msg
     echo $1
     exit_fail
 }
 
-if [ ! -f set_event -o ! -d events/sched ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/sched/sched_process_fork/trigger ]; then
-    echo "event trigger is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f snapshot ]; then
-    echo "snapshot is not supported"
-    exit_unsupported
-fi
-
 FEATURE=`grep snapshot events/sched/sched_process_fork/trigger`
 if [ -z "$FEATURE" ]; then
     echo "snapshot trigger is not supported"
index 398c05c..320ea9b 100644 (file)
@@ -1,29 +1,20 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test stacktrace-trigger
+# requires: set_event events/sched/sched_process_fork/trigger
 
 fail() { #msg
     echo $1
     exit_fail
 }
 
-if [ ! -f set_event -o ! -d events/sched ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/sched/sched_process_fork/trigger ]; then
-    echo "event trigger is not supported"
-    exit_unsupported
-fi
-
 FEATURE=`grep stacktrace events/sched/sched_process_fork/trigger`
 if [ -z "$FEATURE" ]; then
     echo "stacktrace trigger is not supported"
     exit_unsupported
 fi
 
-echo "Test stacktrace tigger"
+echo "Test stacktrace trigger"
 echo 0 > trace
 echo 0 > options/stacktrace
 echo 'stacktrace' > events/sched/sched_process_fork/trigger
index ab6bedb..68f3af9 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: trace_marker trigger - test histogram trigger
+# requires: set_event events/ftrace/print/trigger events/ftrace/print/hist
 # flags: instance
 
 fail() { #msg
@@ -8,27 +9,7 @@ fail() { #msg
     exit_fail
 }
 
-if [ ! -f set_event ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -d events/ftrace/print ]; then
-    echo "event trace_marker is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/ftrace/print/trigger ]; then
-    echo "event trigger is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/ftrace/print/hist ]; then
-    echo "hist trigger is not supported"
-    exit_unsupported
-fi
-
-echo "Test histogram trace_marker tigger"
+echo "Test histogram trace_marker trigger"
 
 echo 'hist:keys=common_pid' > events/ftrace/print/trigger
 for i in `seq 1 10` ; do echo "hello" > trace_marker; done
index df246e5..27da2db 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: trace_marker trigger - test snapshot trigger
+# requires: set_event snapshot events/ftrace/print/trigger
 # flags: instance
 
 fail() { #msg
@@ -8,26 +9,6 @@ fail() { #msg
     exit_fail
 }
 
-if [ ! -f set_event ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f snapshot ]; then
-    echo "snapshot is not supported"
-    exit_unsupported
-fi
-
-if [ ! -d events/ftrace/print ]; then
-    echo "event trace_marker is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/ftrace/print/trigger ]; then
-    echo "event trigger is not supported"
-    exit_unsupported
-fi
-
 test_trace() {
     file=$1
     x=$2
@@ -46,7 +27,7 @@ test_trace() {
     done
 }
 
-echo "Test snapshot trace_marker tigger"
+echo "Test snapshot trace_marker trigger"
 
 echo 'snapshot' > events/ftrace/print/trigger
 
index 18b4d1c..531139f 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: trace_marker trigger - test histogram with synthetic event against kernel event
+# requires: set_event synthetic_events events/sched/sched_waking events/ftrace/print/trigger events/ftrace/print/hist
 # flags:
 
 fail() { #msg
@@ -8,36 +9,6 @@ fail() { #msg
     exit_fail
 }
 
-if [ ! -f set_event ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f synthetic_events ]; then
-    echo "synthetic events not supported"
-    exit_unsupported
-fi
-
-if [ ! -d events/ftrace/print ]; then
-    echo "event trace_marker is not supported"
-    exit_unsupported
-fi
-
-if [ ! -d events/sched/sched_waking ]; then
-    echo "event sched_waking is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/ftrace/print/trigger ]; then
-    echo "event trigger is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/ftrace/print/hist ]; then
-    echo "hist trigger is not supported"
-    exit_unsupported
-fi
-
 echo "Test histogram kernel event to trace_marker latency histogram trigger"
 
 echo 'latency u64 lat' > synthetic_events
index dd262d6..cc99cbb 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: trace_marker trigger - test histogram with synthetic event
+# requires: set_event synthetic_events events/ftrace/print/trigger events/ftrace/print/hist
 # flags:
 
 fail() { #msg
@@ -8,31 +9,6 @@ fail() { #msg
     exit_fail
 }
 
-if [ ! -f set_event ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f synthetic_events ]; then
-    echo "synthetic events not supported"
-    exit_unsupported
-fi
-
-if [ ! -d events/ftrace/print ]; then
-    echo "event trace_marker is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/ftrace/print/trigger ]; then
-    echo "event trigger is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/ftrace/print/hist ]; then
-    echo "hist trigger is not supported"
-    exit_unsupported
-fi
-
 echo "Test histogram trace_marker to trace_marker latency histogram trigger"
 
 echo 'latency u64 lat' > synthetic_events
index d5d2dcb..9ca0467 100644 (file)
@@ -1,22 +1,13 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test traceon/off trigger
+# requires: set_event events/sched/sched_process_fork/trigger
 
 fail() { #msg
     echo $1
     exit_fail
 }
 
-if [ ! -f set_event -o ! -d events/sched ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f events/sched/sched_process_fork/trigger ]; then
-    echo "event trigger is not supported"
-    exit_unsupported
-fi
-
 echo "Test traceoff trigger"
 echo 1 > tracing_on
 echo 'traceoff' > events/sched/sched_process_fork/trigger
index 3702dbc..c82aa77 100755 (executable)
@@ -63,6 +63,8 @@ ALL_TESTS="$ALL_TESTS 0008:150:1"
 ALL_TESTS="$ALL_TESTS 0009:150:1"
 ALL_TESTS="$ALL_TESTS 0010:1:1"
 ALL_TESTS="$ALL_TESTS 0011:1:1"
+ALL_TESTS="$ALL_TESTS 0012:1:1"
+ALL_TESTS="$ALL_TESTS 0013:1:1"
 
 # Kselftest framework requirement - SKIP code is 4.
 ksft_skip=4
@@ -470,6 +472,38 @@ kmod_test_0011()
        echo "$MODPROBE" > /proc/sys/kernel/modprobe
 }
 
+kmod_check_visibility()
+{
+       local name="$1"
+       local cmd="$2"
+
+       modprobe $DEFAULT_KMOD_DRIVER
+
+       local priv=$(eval $cmd)
+       local unpriv=$(capsh --drop=CAP_SYSLOG -- -c "$cmd")
+
+       if [ "$priv" = "$unpriv" ] || \
+          [ "${priv:0:3}" = "0x0" ] || \
+          [ "${unpriv:0:3}" != "0x0" ] ; then
+               echo "${FUNCNAME[0]}: FAIL, $name visible to unpriv: '$priv' vs '$unpriv'" >&2
+               exit 1
+       else
+               echo "${FUNCNAME[0]}: OK!"
+       fi
+}
+
+kmod_test_0012()
+{
+       kmod_check_visibility /proc/modules \
+               "grep '^${DEFAULT_KMOD_DRIVER}\b' /proc/modules | awk '{print \$NF}'"
+}
+
+kmod_test_0013()
+{
+       kmod_check_visibility '/sys/module/*/sections/*' \
+               "cat /sys/module/${DEFAULT_KMOD_DRIVER}/sections/.*text | head -n1"
+}
+
 list_tests()
 {
        echo "Test ID list:"
@@ -489,6 +523,8 @@ list_tests()
        echo "0009 x $(get_test_count 0009) - multithreaded - push kmod_concurrent over max_modprobes for get_fs_type()"
        echo "0010 x $(get_test_count 0010) - test nonexistent modprobe path"
        echo "0011 x $(get_test_count 0011) - test completely disabling module autoloading"
+       echo "0012 x $(get_test_count 0012) - test /proc/modules address visibility under CAP_SYSLOG"
+       echo "0013 x $(get_test_count 0013) - test /sys/module/*/sections/* visibility under CAP_SYSLOG"
 }
 
 usage()
index 0ac49d9..862eee7 100644 (file)
@@ -36,7 +36,7 @@ struct ksft_count {
 static struct ksft_count ksft_cnt;
 static unsigned int ksft_plan;
 
-static inline int ksft_test_num(void)
+static inline unsigned int ksft_test_num(void)
 {
        return ksft_cnt.ksft_pass + ksft_cnt.ksft_fail +
                ksft_cnt.ksft_xfail + ksft_cnt.ksft_xpass +
index 9dc35a1..51df5e3 100755 (executable)
@@ -144,7 +144,7 @@ setup()
 
 cleanup()
 {
-       for n in h1 r1 h2 h3 h4
+       for n in h0 r1 h1 h2 h3
        do
                ip netns del ${n} 2>/dev/null
        done
index dee567f..22dc2f3 100755 (executable)
@@ -747,6 +747,19 @@ ipv6_fcnal_runtime()
        run_cmd "$IP nexthop add id 86 via 2001:db8:91::2 dev veth1"
        run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
 
+       # rpfilter and default route
+       $IP nexthop flush >/dev/null 2>&1
+       run_cmd "ip netns exec me ip6tables -t mangle -I PREROUTING 1 -m rpfilter --invert -j DROP"
+       run_cmd "$IP nexthop add id 91 via 2001:db8:91::2 dev veth1"
+       run_cmd "$IP nexthop add id 92 via 2001:db8:92::2 dev veth3"
+       run_cmd "$IP nexthop add id 93 group 91/92"
+       run_cmd "$IP -6 ro add default nhid 91"
+       run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
+       log_test $? 0 "Nexthop with default route and rpfilter"
+       run_cmd "$IP -6 ro replace default nhid 93"
+       run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
+       log_test $? 0 "Nexthop with multipath default route and rpfilter"
+
        # TO-DO:
        # existing route with old nexthop; append route with new nexthop
        # existing route with old nexthop; replace route with new
index 15d3489..ceb7ad4 100755 (executable)
@@ -6,6 +6,8 @@
 set +x
 set -e
 
+modprobe -q nf_defrag_ipv6
+
 readonly NETNS="ns-$(mktemp -u XXXXXX)"
 
 setup() {
index 383bac0..ceaad78 100644 (file)
@@ -15,8 +15,9 @@
 #include <inttypes.h>
 #include <linux/net_tstamp.h>
 #include <linux/errqueue.h>
+#include <linux/if_ether.h>
 #include <linux/ipv6.h>
-#include <linux/tcp.h>
+#include <linux/udp.h>
 #include <stdbool.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -140,8 +141,8 @@ static void do_recv_errqueue_timeout(int fdt)
 {
        char control[CMSG_SPACE(sizeof(struct sock_extended_err)) +
                     CMSG_SPACE(sizeof(struct sockaddr_in6))] = {0};
-       char data[sizeof(struct ipv6hdr) +
-                 sizeof(struct tcphdr) + 1];
+       char data[sizeof(struct ethhdr) + sizeof(struct ipv6hdr) +
+                 sizeof(struct udphdr) + 1];
        struct sock_extended_err *err;
        struct msghdr msg = {0};
        struct iovec iov = {0};
@@ -159,6 +160,8 @@ static void do_recv_errqueue_timeout(int fdt)
        msg.msg_controllen = sizeof(control);
 
        while (1) {
+               const char *reason;
+
                ret = recvmsg(fdt, &msg, MSG_ERRQUEUE);
                if (ret == -1 && errno == EAGAIN)
                        break;
@@ -176,14 +179,30 @@ static void do_recv_errqueue_timeout(int fdt)
                err = (struct sock_extended_err *)CMSG_DATA(cm);
                if (err->ee_origin != SO_EE_ORIGIN_TXTIME)
                        error(1, 0, "errqueue: origin 0x%x\n", err->ee_origin);
-               if (err->ee_code != ECANCELED)
-                       error(1, 0, "errqueue: code 0x%x\n", err->ee_code);
+
+               switch (err->ee_errno) {
+               case ECANCELED:
+                       if (err->ee_code != SO_EE_CODE_TXTIME_MISSED)
+                               error(1, 0, "errqueue: unknown ECANCELED %u\n",
+                                     err->ee_code);
+                       reason = "missed txtime";
+               break;
+               case EINVAL:
+                       if (err->ee_code != SO_EE_CODE_TXTIME_INVALID_PARAM)
+                               error(1, 0, "errqueue: unknown EINVAL %u\n",
+                                     err->ee_code);
+                       reason = "invalid txtime";
+               break;
+               default:
+                       error(1, 0, "errqueue: errno %u code %u\n",
+                             err->ee_errno, err->ee_code);
+               };
 
                tstamp = ((int64_t) err->ee_data) << 32 | err->ee_info;
                tstamp -= (int64_t) glob_tstart;
                tstamp /= 1000 * 1000;
-               fprintf(stderr, "send: pkt %c at %" PRId64 "ms dropped\n",
-                               data[ret - 1], tstamp);
+               fprintf(stderr, "send: pkt %c at %" PRId64 "ms dropped: %s\n",
+                       data[ret - 1], tstamp, reason);
 
                msg.msg_flags = 0;
                msg.msg_controllen = sizeof(control);
index eea6f51..3163776 100755 (executable)
@@ -75,7 +75,7 @@ main() {
        fi
 }
 
-if [[ "$(ip netns identify)" == "root" ]]; then
+if [[ -z "$(ip netns identify)" ]]; then
        ./in_netns.sh $0 $@
 else
        main $@
index 9c0f758..a179f0d 100644 (file)
@@ -3,7 +3,7 @@
 
 TEST_PROGS := nft_trans_stress.sh nft_nat.sh bridge_brouter.sh \
        conntrack_icmp_related.sh nft_flowtable.sh ipvs.sh \
-       nft_concat_range.sh \
+       nft_concat_range.sh nft_conntrack_helper.sh \
        nft_queue.sh
 
 LDLIBS = -lmnl
diff --git a/tools/testing/selftests/netfilter/nft_conntrack_helper.sh b/tools/testing/selftests/netfilter/nft_conntrack_helper.sh
new file mode 100755 (executable)
index 0000000..edf0a48
--- /dev/null
@@ -0,0 +1,175 @@
+#!/bin/bash
+#
+# This tests connection tracking helper assignment:
+# 1. can attach ftp helper to a connection from nft ruleset.
+# 2. auto-assign still works.
+#
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+ret=0
+
+sfx=$(mktemp -u "XXXXXXXX")
+ns1="ns1-$sfx"
+ns2="ns2-$sfx"
+testipv6=1
+
+cleanup()
+{
+       ip netns del ${ns1}
+       ip netns del ${ns2}
+}
+
+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
+
+conntrack -V > /dev/null 2>&1
+if [ $? -ne 0 ];then
+       echo "SKIP: Could not run test without conntrack tool"
+       exit $ksft_skip
+fi
+
+which nc >/dev/null 2>&1
+if [ $? -ne 0 ];then
+       echo "SKIP: Could not run test without netcat tool"
+       exit $ksft_skip
+fi
+
+trap cleanup EXIT
+
+ip netns add ${ns1}
+ip netns add ${ns2}
+
+ip link add veth0 netns ${ns1} type veth peer name veth0 netns ${ns2} > /dev/null 2>&1
+if [ $? -ne 0 ];then
+    echo "SKIP: No virtual ethernet pair device support in kernel"
+    exit $ksft_skip
+fi
+
+ip -net ${ns1} link set lo up
+ip -net ${ns1} link set veth0 up
+
+ip -net ${ns2} link set lo up
+ip -net ${ns2} link set veth0 up
+
+ip -net ${ns1} addr add 10.0.1.1/24 dev veth0
+ip -net ${ns1} addr add dead:1::1/64 dev veth0
+
+ip -net ${ns2} addr add 10.0.1.2/24 dev veth0
+ip -net ${ns2} addr add dead:1::2/64 dev veth0
+
+load_ruleset_family() {
+       local family=$1
+       local ns=$2
+
+ip netns exec ${ns} nft -f - <<EOF
+table $family raw {
+       ct helper ftp {
+             type "ftp" protocol tcp
+        }
+       chain pre {
+               type filter hook prerouting priority 0; policy accept;
+               tcp dport 2121 ct helper set "ftp"
+       }
+       chain output {
+               type filter hook output priority 0; policy accept;
+               tcp dport 2121 ct helper set "ftp"
+       }
+}
+EOF
+       return $?
+}
+
+check_for_helper()
+{
+       local netns=$1
+       local message=$2
+       local port=$3
+
+       ip netns exec ${netns} conntrack -L -p tcp --dport $port 2> /dev/null |grep -q 'helper=ftp'
+       if [ $? -ne 0 ] ; then
+               echo "FAIL: ${netns} did not show attached helper $message" 1>&2
+               ret=1
+       fi
+
+       echo "PASS: ${netns} connection on port $port has ftp helper attached" 1>&2
+       return 0
+}
+
+test_helper()
+{
+       local port=$1
+       local msg=$2
+
+       sleep 3 | ip netns exec ${ns2} nc -w 2 -l -p $port > /dev/null &
+
+       sleep 1
+       sleep 1 | ip netns exec ${ns1} nc -w 2 10.0.1.2 $port > /dev/null &
+
+       check_for_helper "$ns1" "ip $msg" $port
+       check_for_helper "$ns2" "ip $msg" $port
+
+       wait
+
+       if [ $testipv6 -eq 0 ] ;then
+               return 0
+       fi
+
+       ip netns exec ${ns1} conntrack -F 2> /dev/null
+       ip netns exec ${ns2} conntrack -F 2> /dev/null
+
+       sleep 3 | ip netns exec ${ns2} nc -w 2 -6 -l -p $port > /dev/null &
+
+       sleep 1
+       sleep 1 | ip netns exec ${ns1} nc -w 2 -6 dead:1::2 $port > /dev/null &
+
+       check_for_helper "$ns1" "ipv6 $msg" $port
+       check_for_helper "$ns2" "ipv6 $msg" $port
+
+       wait
+}
+
+load_ruleset_family ip ${ns1}
+if [ $? -ne 0 ];then
+       echo "FAIL: ${ns1} cannot load ip ruleset" 1>&2
+       exit 1
+fi
+
+load_ruleset_family ip6 ${ns1}
+if [ $? -ne 0 ];then
+       echo "SKIP: ${ns1} cannot load ip6 ruleset" 1>&2
+       testipv6=0
+fi
+
+load_ruleset_family inet ${ns2}
+if [ $? -ne 0 ];then
+       echo "SKIP: ${ns1} cannot load inet ruleset" 1>&2
+       load_ruleset_family ip ${ns2}
+       if [ $? -ne 0 ];then
+               echo "FAIL: ${ns2} cannot load ip ruleset" 1>&2
+               exit 1
+       fi
+
+       if [ $testipv6 -eq 1 ] ;then
+               load_ruleset_family ip6 ${ns2}
+               if [ $? -ne 0 ];then
+                       echo "FAIL: ${ns2} cannot load ip6 ruleset" 1>&2
+                       exit 1
+               fi
+       fi
+fi
+
+test_helper 2121 "set via ruleset"
+ip netns exec ${ns1} sysctl -q 'net.netfilter.nf_conntrack_helper=1'
+ip netns exec ${ns2} sysctl -q 'net.netfilter.nf_conntrack_helper=1'
+test_helper 21 "auto-assign"
+
+exit $ret
index c1921a5..8d728ed 100644 (file)
@@ -95,4 +95,9 @@ static inline int sys_pidfd_getfd(int pidfd, int fd, int flags)
        return syscall(__NR_pidfd_getfd, pidfd, fd, flags);
 }
 
+static inline int sys_memfd_create(const char *name, unsigned int flags)
+{
+       return syscall(__NR_memfd_create, name, flags);
+}
+
 #endif /* __PIDFD_H */
index 401a7c1..84b65ec 100644 (file)
@@ -34,11 +34,6 @@ static int sys_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1,
        return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
 }
 
-static int sys_memfd_create(const char *name, unsigned int flags)
-{
-       return syscall(__NR_memfd_create, name, flags);
-}
-
 static int __child(int sk, int memfd)
 {
        int ret;
index 133ec5b..9418108 100644 (file)
@@ -470,4 +470,16 @@ TEST_F(current_nsset, no_foul_play)
        }
 }
 
+TEST(setns_einval)
+{
+       int fd;
+
+       fd = sys_memfd_create("rostock", 0);
+       EXPECT_GT(fd, 0);
+
+       ASSERT_NE(setns(fd, 0), 0);
+       EXPECT_EQ(errno, EINVAL);
+       close(fd);
+}
+
 TEST_HARNESS_MAIN
index 6ee0fde..7c23d3d 100644 (file)
@@ -698,13 +698,13 @@ restart_nx:
 
        switch (cc) {
 
-       case ERR_NX_TRANSLATION:
+       case ERR_NX_AT_FAULT:
 
                /* We touched the pages ahead of time.  In the most common case
                 * we shouldn't be here.  But may be some pages were paged out.
                 * Kernel should have placed the faulting address to fsaddr.
                 */
-               NXPRT(fprintf(stderr, "ERR_NX_TRANSLATION %p\n",
+               NXPRT(fprintf(stderr, "ERR_NX_AT_FAULT %p\n",
                              (void *)cmdp->crb.csb.fsaddr));
 
                if (pgfault_retries == NX_MAX_FAULTS) {
index 7496a83..02dffb6 100644 (file)
@@ -306,13 +306,13 @@ int compress_file(int argc, char **argv, void *handle)
                        lzcounts, cmdp, handle);
 
                if (cc != ERR_NX_OK && cc != ERR_NX_TPBC_GT_SPBC &&
-                   cc != ERR_NX_TRANSLATION) {
+                   cc != ERR_NX_AT_FAULT) {
                        fprintf(stderr, "nx error: cc= %d\n", cc);
                        exit(-1);
                }
 
                /* Page faults are handled by the user code */
-               if (cc == ERR_NX_TRANSLATION) {
+               if (cc == ERR_NX_AT_FAULT) {
                        NXPRT(fprintf(stderr, "page fault: cc= %d, ", cc));
                        NXPRT(fprintf(stderr, "try= %d, fsa= %08llx\n",
                                  fault_tries,
index ca35dd8..af3df79 100644 (file)
@@ -7,7 +7,7 @@ noarg:
 # The EBB handler is 64-bit code and everything links against it
 CFLAGS += -m64
 
-TMPOUT = $(OUTPUT)/
+TMPOUT = $(OUTPUT)/TMPDIR/
 # Toolchains may build PIE by default which breaks the assembly
 no-pie-option := $(call try-run, echo 'int main() { return 0; }' | \
         $(CC) -Werror $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -no-pie -x c - -o "$$TMP", -no-pie)
index c0aa46c..252140a 100644 (file)
@@ -1615,6 +1615,7 @@ TEST_F(TRACE_poke, getpid_runs_normally)
 # define ARCH_REGS     s390_regs
 # define SYSCALL_NUM   gprs[2]
 # define SYSCALL_RET   gprs[2]
+# define SYSCALL_NUM_RET_SHARE_REG
 #elif defined(__mips__)
 # define ARCH_REGS     struct pt_regs
 # define SYSCALL_NUM   regs[2]
index 47a3082..503982b 100644 (file)
                 255
             ]
         ],
-        "cmdUnderTest": "$TC action add action bpf bytecode '4,40 0 0 12,21 0 1 2054,6 0 0 262144,6 0 0 0' index 4294967296 cookie 12345",
+        "cmdUnderTest": "$TC action add action bpf bytecode '4,40 0 0 12,21 0 1 2054,6 0 0 262144,6 0 0 0' index 4294967296 cookie 123456",
         "expExitCode": "255",
         "verifyCmd": "$TC action ls action bpf",
-        "matchPattern": "action order [0-9]*: bpf bytecode '4,40 0 0 12,21 0 1 2048,6 0 0 262144,6 0 0 0' default-action pipe.*cookie 12345",
+        "matchPattern": "action order [0-9]*: bpf bytecode '4,40 0 0 12,21 0 1 2048,6 0 0 262144,6 0 0 0' default-action pipe.*cookie 123456",
         "matchCount": "0",
         "teardown": [
             "$TC action flush action bpf"
index 88ec134..072febf 100644 (file)
                 255
             ]
         ],
-        "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action csum tcp continue index \\$i cookie aaabbbcccdddeee \\\"; args=\"\\$args\\$cmd\"; done && $TC actions add \\$args\"",
+        "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action csum tcp continue index \\$i cookie 123456789abcde \\\"; args=\"\\$args\\$cmd\"; done && $TC actions add \\$args\"",
         "expExitCode": "0",
         "verifyCmd": "$TC actions ls action csum",
         "matchPattern": "^[ \t]+index [0-9]* ref",
                 1,
                 255
             ],
-            "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action csum tcp continue index \\$i cookie aaabbbcccdddeee \\\"; args=\"\\$args\\$cmd\"; done && $TC actions add \\$args\""
+            "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action csum tcp continue index \\$i cookie 123456789abcde \\\"; args=\"\\$args\\$cmd\"; done && $TC actions add \\$args\""
         ],
         "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action csum index \\$i \\\"; args=\"\\$args\\$cmd\"; done && $TC actions del \\$args\"",
         "expExitCode": "0",
index fbeb919..d063469 100644 (file)
         "cmdUnderTest": "$TC actions add action tunnel_key set src_ip 1.1.1.1 dst_ip 2.2.2.2 id 42 dst_port 6081 geneve_opts 0102:80:00880022 index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action tunnel_key index 1",
-        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 1.1.1.1.*dst_ip 2.2.2.2.*key_id 42.*dst_port 6081.*geneve_opt 0102:80:00880022.*index 1",
+        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 1.1.1.1.*dst_ip 2.2.2.2.*key_id 42.*dst_port 6081.*geneve_opt[s]? 0102:80:00880022.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action tunnel_key"
         "cmdUnderTest": "$TC actions add action tunnel_key set src_ip 1.1.1.1 dst_ip 2.2.2.2 id 42 dst_port 6081 geneve_opts 0102:80:00880022,0408:42:0040007611223344,0111:02:1020304011223344 index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action tunnel_key index 1",
-        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 1.1.1.1.*dst_ip 2.2.2.2.*key_id 42.*dst_port 6081.*geneve_opt 0102:80:00880022,0408:42:0040007611223344,0111:02:1020304011223344.*index 1",
+        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 1.1.1.1.*dst_ip 2.2.2.2.*key_id 42.*dst_port 6081.*geneve_opt[s]? 0102:80:00880022,0408:42:0040007611223344,0111:02:1020304011223344.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action tunnel_key"
         "cmdUnderTest": "$TC actions add action tunnel_key set src_ip 1.1.1.1 dst_ip 2.2.2.2 id 42 dst_port 6081 geneve_opts 824212:80:00880022 index 1",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action tunnel_key index 1",
-        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 1.1.1.1.*dst_ip 2.2.2.2.*key_id 42.*dst_port 6081.*geneve_opt 824212:80:00880022.*index 1",
+        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 1.1.1.1.*dst_ip 2.2.2.2.*key_id 42.*dst_port 6081.*geneve_opt[s]? 824212:80:00880022.*index 1",
         "matchCount": "0",
         "teardown": [
             "$TC actions flush action tunnel_key"
         "cmdUnderTest": "$TC actions add action tunnel_key set src_ip 1.1.1.1 dst_ip 2.2.2.2 id 42 dst_port 6081 geneve_opts 0102:4224:00880022 index 1",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action tunnel_key index 1",
-        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 1.1.1.1.*dst_ip 2.2.2.2.*key_id 42.*dst_port 6081.*geneve_opt 0102:4224:00880022.*index 1",
+        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 1.1.1.1.*dst_ip 2.2.2.2.*key_id 42.*dst_port 6081.*geneve_opt[s]? 0102:4224:00880022.*index 1",
         "matchCount": "0",
         "teardown": [
             "$TC actions flush action tunnel_key"
         "cmdUnderTest": "$TC actions add action tunnel_key set src_ip 1.1.1.1 dst_ip 2.2.2.2 id 42 dst_port 6081 geneve_opts 0102:80:4288 index 1",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action tunnel_key index 1",
-        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 1.1.1.1.*dst_ip 2.2.2.2.*key_id 42.*dst_port 6081.*geneve_opt 0102:80:4288.*index 1",
+        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 1.1.1.1.*dst_ip 2.2.2.2.*key_id 42.*dst_port 6081.*geneve_opt[s]? 0102:80:4288.*index 1",
         "matchCount": "0",
         "teardown": [
             "$TC actions flush action tunnel_key"
         "cmdUnderTest": "$TC actions add action tunnel_key set src_ip 1.1.1.1 dst_ip 2.2.2.2 id 42 dst_port 6081 geneve_opts 0102:80:4288428822 index 1",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action tunnel_key index 1",
-        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 1.1.1.1.*dst_ip 2.2.2.2.*key_id 42.*dst_port 6081.*geneve_opt 0102:80:4288428822.*index 1",
+        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 1.1.1.1.*dst_ip 2.2.2.2.*key_id 42.*dst_port 6081.*geneve_opt[s]? 0102:80:4288428822.*index 1",
         "matchCount": "0",
         "teardown": [
             "$TC actions flush action tunnel_key"
         "cmdUnderTest": "$TC actions add action tunnel_key set src_ip 1.1.1.1 dst_ip 2.2.2.2 id 42 dst_port 6081 geneve_opts 0102:80:00880022,0408:42: index 1",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action tunnel_key index 1",
-        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 1.1.1.1.*dst_ip 2.2.2.2.*key_id 42.*dst_port 6081.*geneve_opt 0102:80:00880022,0408:42:.*index 1",
+        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 1.1.1.1.*dst_ip 2.2.2.2.*key_id 42.*dst_port 6081.*geneve_opt[s]? 0102:80:00880022,0408:42:.*index 1",
         "matchCount": "0",
         "teardown": [
             "$TC actions flush action tunnel_key"
                 1,
                 255
             ],
-            "$TC actions add action tunnel_key set src_ip 10.10.10.1 dst_ip 20.20.20.2 dst_port 3128 nocsum id 1 index 1 cookie aabbccddeeff112233445566778800a"
+            "$TC actions add action tunnel_key set src_ip 10.10.10.1 dst_ip 20.20.20.2 dst_port 3128 nocsum id 1 index 1 cookie 123456"
         ],
-        "cmdUnderTest": "$TC actions replace action tunnel_key set src_ip 11.11.11.1 dst_ip 21.21.21.2 dst_port 3129 id 11 csum reclassify index 1 cookie a1b1c1d1",
+        "cmdUnderTest": "$TC actions replace action tunnel_key set src_ip 11.11.11.1 dst_ip 21.21.21.2 dst_port 3129 id 11 csum reclassify index 1 cookie 123456",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action tunnel_key index 1",
-        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 11.11.11.1.*dst_ip 21.21.21.2.*key_id 11.*dst_port 3129.*csum reclassify.*index 1.*cookie a1b1c1d1",
+        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 11.11.11.1.*dst_ip 21.21.21.2.*key_id 11.*dst_port 3129.*csum reclassify.*index 1.*cookie 123456",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action tunnel_key"
index 6630627..3e5ff29 100755 (executable)
@@ -1,15 +1,10 @@
-#!/bin/bash
+#!/bin/sh
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
 
 # Kselftest framework requirement - SKIP code is 4.
 ksft_skip=4
 
-[ -f /dev/tpm0 ] || exit $ksft_skip
+[ -e /dev/tpm0 ] || exit $ksft_skip
 
-python -m unittest -v tpm2_tests.SmokeTest
-python -m unittest -v tpm2_tests.AsyncTest
-
-CLEAR_CMD=$(which tpm2_clear)
-if [ -n $CLEAR_CMD ]; then
-       tpm2_clear -T device
-fi
+python3 -m unittest -v tpm2_tests.SmokeTest
+python3 -m unittest -v tpm2_tests.AsyncTest
index 36c9d03..04c47b1 100755 (executable)
@@ -1,9 +1,9 @@
-#!/bin/bash
+#!/bin/sh
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
 
 # Kselftest framework requirement - SKIP code is 4.
 ksft_skip=4
 
-[ -f /dev/tpmrm0 ] || exit $ksft_skip
+[ -e /dev/tpmrm0 ] || exit $ksft_skip
 
-python -m unittest -v tpm2_tests.SpaceTest
+python3 -m unittest -v tpm2_tests.SpaceTest
index d0fcb66..f34486c 100644 (file)
@@ -247,14 +247,14 @@ class ProtocolError(Exception):
 class AuthCommand(object):
     """TPMS_AUTH_COMMAND"""
 
-    def __init__(self, session_handle=TPM2_RS_PW, nonce='', session_attributes=0,
-                 hmac=''):
+    def __init__(self, session_handle=TPM2_RS_PW, nonce=bytes(),
+                 session_attributes=0, hmac=bytes()):
         self.session_handle = session_handle
         self.nonce = nonce
         self.session_attributes = session_attributes
         self.hmac = hmac
 
-    def __str__(self):
+    def __bytes__(self):
         fmt = '>I H%us B H%us' % (len(self.nonce), len(self.hmac))
         return struct.pack(fmt, self.session_handle, len(self.nonce),
                            self.nonce, self.session_attributes, len(self.hmac),
@@ -268,11 +268,11 @@ class AuthCommand(object):
 class SensitiveCreate(object):
     """TPMS_SENSITIVE_CREATE"""
 
-    def __init__(self, user_auth='', data=''):
+    def __init__(self, user_auth=bytes(), data=bytes()):
         self.user_auth = user_auth
         self.data = data
 
-    def __str__(self):
+    def __bytes__(self):
         fmt = '>H%us H%us' % (len(self.user_auth), len(self.data))
         return struct.pack(fmt, len(self.user_auth), self.user_auth,
                            len(self.data), self.data)
@@ -296,8 +296,9 @@ class Public(object):
         return '>HHIH%us%usH%us' % \
             (len(self.auth_policy), len(self.parameters), len(self.unique))
 
-    def __init__(self, object_type, name_alg, object_attributes, auth_policy='',
-                 parameters='', unique=''):
+    def __init__(self, object_type, name_alg, object_attributes,
+                 auth_policy=bytes(), parameters=bytes(),
+                 unique=bytes()):
         self.object_type = object_type
         self.name_alg = name_alg
         self.object_attributes = object_attributes
@@ -305,7 +306,7 @@ class Public(object):
         self.parameters = parameters
         self.unique = unique
 
-    def __str__(self):
+    def __bytes__(self):
         return struct.pack(self.__fmt(),
                            self.object_type,
                            self.name_alg,
@@ -343,7 +344,7 @@ def get_algorithm(name):
 
 def hex_dump(d):
     d = [format(ord(x), '02x') for x in d]
-    d = [d[i: i + 16] for i in xrange(0, len(d), 16)]
+    d = [d[i: i + 16] for i in range(0, len(d), 16)]
     d = [' '.join(x) for x in d]
     d = os.linesep.join(d)
 
@@ -401,7 +402,7 @@ class Client:
         pcrsel_len = max((i >> 3) + 1, 3)
         pcrsel = [0] * pcrsel_len
         pcrsel[i >> 3] = 1 << (i & 7)
-        pcrsel = ''.join(map(chr, pcrsel))
+        pcrsel = ''.join(map(chr, pcrsel)).encode()
 
         fmt = '>HII IHB%us' % (pcrsel_len)
         cmd = struct.pack(fmt,
@@ -443,7 +444,7 @@ class Client:
             TPM2_CC_PCR_EXTEND,
             i,
             len(auth_cmd),
-            str(auth_cmd),
+            bytes(auth_cmd),
             1, bank_alg, dig)
 
         self.send_cmd(cmd)
@@ -457,7 +458,7 @@ class Client:
                           TPM2_RH_NULL,
                           TPM2_RH_NULL,
                           16,
-                          '\0' * 16,
+                          ('\0' * 16).encode(),
                           0,
                           session_type,
                           TPM2_ALG_NULL,
@@ -472,7 +473,7 @@ class Client:
 
         for i in pcrs:
             pcr = self.read_pcr(i, bank_alg)
-            if pcr == None:
+            if pcr is None:
                 return None
             x += pcr
 
@@ -489,7 +490,7 @@ class Client:
         pcrsel = [0] * pcrsel_len
         for i in pcrs:
             pcrsel[i >> 3] |= 1 << (i & 7)
-        pcrsel = ''.join(map(chr, pcrsel))
+        pcrsel = ''.join(map(chr, pcrsel)).encode()
 
         fmt = '>HII IH%usIHB3s' % ds
         cmd = struct.pack(fmt,
@@ -497,7 +498,8 @@ class Client:
                           struct.calcsize(fmt),
                           TPM2_CC_POLICY_PCR,
                           handle,
-                          len(dig), str(dig),
+                          len(dig),
+                          bytes(dig),
                           1,
                           bank_alg,
                           pcrsel_len, pcrsel)
@@ -534,7 +536,7 @@ class Client:
 
         self.send_cmd(cmd)
 
-    def create_root_key(self, auth_value = ''):
+    def create_root_key(self, auth_value = bytes()):
         attributes = \
             Public.FIXED_TPM | \
             Public.FIXED_PARENT | \
@@ -570,11 +572,11 @@ class Client:
             TPM2_CC_CREATE_PRIMARY,
             TPM2_RH_OWNER,
             len(auth_cmd),
-            str(auth_cmd),
+            bytes(auth_cmd),
             len(sensitive),
-            str(sensitive),
+            bytes(sensitive),
             len(public),
-            str(public),
+            bytes(public),
             0, 0)
 
         return struct.unpack('>I', self.send_cmd(cmd)[10:14])[0]
@@ -587,7 +589,7 @@ class Client:
         attributes = 0
         if not policy_dig:
             attributes |= Public.USER_WITH_AUTH
-            policy_dig = ''
+            policy_dig = bytes()
 
         auth_cmd =  AuthCommand()
         sensitive = SensitiveCreate(user_auth=auth_value, data=data)
@@ -608,11 +610,11 @@ class Client:
             TPM2_CC_CREATE,
             parent_key,
             len(auth_cmd),
-            str(auth_cmd),
+            bytes(auth_cmd),
             len(sensitive),
-            str(sensitive),
+            bytes(sensitive),
             len(public),
-            str(public),
+            bytes(public),
             0, 0)
 
         rsp = self.send_cmd(cmd)
@@ -635,7 +637,7 @@ class Client:
             TPM2_CC_LOAD,
             parent_key,
             len(auth_cmd),
-            str(auth_cmd),
+            bytes(auth_cmd),
             blob)
 
         data_handle = struct.unpack('>I', self.send_cmd(cmd)[10:14])[0]
@@ -653,7 +655,7 @@ class Client:
             TPM2_CC_UNSEAL,
             data_handle,
             len(auth_cmd),
-            str(auth_cmd))
+            bytes(auth_cmd))
 
         try:
             rsp = self.send_cmd(cmd)
@@ -675,7 +677,7 @@ class Client:
             TPM2_CC_DICTIONARY_ATTACK_LOCK_RESET,
             TPM2_RH_LOCKOUT,
             len(auth_cmd),
-            str(auth_cmd))
+            bytes(auth_cmd))
 
         self.send_cmd(cmd)
 
@@ -693,7 +695,7 @@ class Client:
         more_data, cap, cnt = struct.unpack('>BII', rsp[:9])
         rsp = rsp[9:]
 
-        for i in xrange(0, cnt):
+        for i in range(0, cnt):
             handle = struct.unpack('>I', rsp[:4])[0]
             handles.append(handle)
             rsp = rsp[4:]
index 728be7c..9d76430 100644 (file)
@@ -20,8 +20,8 @@ class SmokeTest(unittest.TestCase):
         self.client.close()
 
     def test_seal_with_auth(self):
-        data = 'X' * 64
-        auth = 'A' * 15
+        data = ('X' * 64).encode()
+        auth = ('A' * 15).encode()
 
         blob = self.client.seal(self.root_key, data, auth, None)
         result = self.client.unseal(self.root_key, blob, auth, None)
@@ -30,8 +30,8 @@ class SmokeTest(unittest.TestCase):
     def test_seal_with_policy(self):
         handle = self.client.start_auth_session(tpm2.TPM2_SE_TRIAL)
 
-        data = 'X' * 64
-        auth = 'A' * 15
+        data = ('X' * 64).encode()
+        auth = ('A' * 15).encode()
         pcrs = [16]
 
         try:
@@ -58,14 +58,15 @@ class SmokeTest(unittest.TestCase):
         self.assertEqual(data, result)
 
     def test_unseal_with_wrong_auth(self):
-        data = 'X' * 64
-        auth = 'A' * 20
+        data = ('X' * 64).encode()
+        auth = ('A' * 20).encode()
         rc = 0
 
         blob = self.client.seal(self.root_key, data, auth, None)
         try:
-            result = self.client.unseal(self.root_key, blob, auth[:-1] + 'B', None)
-        except ProtocolError, e:
+            result = self.client.unseal(self.root_key, blob,
+                        auth[:-1] + 'B'.encode(), None)
+        except ProtocolError as e:
             rc = e.rc
 
         self.assertEqual(rc, tpm2.TPM2_RC_AUTH_FAIL)
@@ -73,8 +74,8 @@ class SmokeTest(unittest.TestCase):
     def test_unseal_with_wrong_policy(self):
         handle = self.client.start_auth_session(tpm2.TPM2_SE_TRIAL)
 
-        data = 'X' * 64
-        auth = 'A' * 17
+        data = ('X' * 64).encode()
+        auth = ('A' * 17).encode()
         pcrs = [16]
 
         try:
@@ -91,7 +92,7 @@ class SmokeTest(unittest.TestCase):
         # This should succeed.
 
         ds = tpm2.get_digest_size(tpm2.TPM2_ALG_SHA1)
-        self.client.extend_pcr(1, 'X' * ds)
+        self.client.extend_pcr(1, ('X' * ds).encode())
 
         handle = self.client.start_auth_session(tpm2.TPM2_SE_POLICY)
 
@@ -108,7 +109,7 @@ class SmokeTest(unittest.TestCase):
 
         # Then, extend a PCR that is part of the policy and try to unseal.
         # This should fail.
-        self.client.extend_pcr(16, 'X' * ds)
+        self.client.extend_pcr(16, ('X' * ds).encode())
 
         handle = self.client.start_auth_session(tpm2.TPM2_SE_POLICY)
 
@@ -119,7 +120,7 @@ class SmokeTest(unittest.TestCase):
             self.client.policy_password(handle)
 
             result = self.client.unseal(self.root_key, blob, auth, handle)
-        except ProtocolError, e:
+        except ProtocolError as e:
             rc = e.rc
             self.client.flush_context(handle)
         except:
@@ -130,13 +131,13 @@ class SmokeTest(unittest.TestCase):
 
     def test_seal_with_too_long_auth(self):
         ds = tpm2.get_digest_size(tpm2.TPM2_ALG_SHA1)
-        data = 'X' * 64
-        auth = 'A' * (ds + 1)
+        data = ('X' * 64).encode()
+        auth = ('A' * (ds + 1)).encode()
 
         rc = 0
         try:
             blob = self.client.seal(self.root_key, data, auth, None)
-        except ProtocolError, e:
+        except ProtocolError as e:
             rc = e.rc
 
         self.assertEqual(rc, tpm2.TPM2_RC_SIZE)
@@ -152,7 +153,7 @@ class SmokeTest(unittest.TestCase):
                               0xDEADBEEF)
 
             self.client.send_cmd(cmd)
-        except IOError, e:
+        except IOError as e:
             rejected = True
         except:
             pass
@@ -212,7 +213,7 @@ class SmokeTest(unittest.TestCase):
             self.client.tpm.write(cmd)
             rsp = self.client.tpm.read()
 
-        except IOError, e:
+        except IOError as e:
             # read the response
             rsp = self.client.tpm.read()
             rejected = True
@@ -283,7 +284,7 @@ class SpaceTest(unittest.TestCase):
         rc = 0
         try:
             space1.send_cmd(cmd)
-        except ProtocolError, e:
+        except ProtocolError as e:
             rc = e.rc
 
         self.assertEqual(rc, tpm2.TPM2_RC_COMMAND_CODE |
index 17a1f53..d77f482 100755 (executable)
@@ -587,9 +587,20 @@ ip0 link set wg0 up
 kill $ncat_pid
 ip0 link del wg0
 
+# Ensure there aren't circular reference loops
+ip1 link add wg1 type wireguard
+ip2 link add wg2 type wireguard
+ip1 link set wg1 netns $netns2
+ip2 link set wg2 netns $netns1
+pp ip netns delete $netns1
+pp ip netns delete $netns2
+pp ip netns add $netns1
+pp ip netns add $netns2
+
+sleep 2 # Wait for cleanup and grace periods
 declare -A objects
 while read -t 0.1 -r line 2>/dev/null || [[ $? -ne 142 ]]; do
-       [[ $line =~ .*(wg[0-9]+:\ [A-Z][a-z]+\ [0-9]+)\ .*(created|destroyed).* ]] || continue
+       [[ $line =~ .*(wg[0-9]+:\ [A-Z][a-z]+\ ?[0-9]*)\ .*(created|destroyed).* ]] || continue
        objects["${BASH_REMATCH[1]}"]+="${BASH_REMATCH[2]}"
 done < /dev/kmsg
 alldeleted=1
index 5f16821..d2796ea 100644 (file)
@@ -70,10 +70,10 @@ all_64: $(BINARIES_64)
 
 EXTRA_CLEAN := $(BINARIES_32) $(BINARIES_64)
 
-$(BINARIES_32): $(OUTPUT)/%_32: %.c
+$(BINARIES_32): $(OUTPUT)/%_32: %.c helpers.h
        $(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl -lm
 
-$(BINARIES_64): $(OUTPUT)/%_64: %.c
+$(BINARIES_64): $(OUTPUT)/%_64: %.c helpers.h
        $(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl
 
 # x86_64 users should be encouraged to install 32-bit libraries
diff --git a/tools/testing/selftests/x86/helpers.h b/tools/testing/selftests/x86/helpers.h
new file mode 100644 (file)
index 0000000..f5ff2a2
--- /dev/null
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#ifndef __SELFTESTS_X86_HELPERS_H
+#define __SELFTESTS_X86_HELPERS_H
+
+#include <asm/processor-flags.h>
+
+static inline unsigned long get_eflags(void)
+{
+       unsigned long eflags;
+
+       asm volatile (
+#ifdef __x86_64__
+               "subq $128, %%rsp\n\t"
+               "pushfq\n\t"
+               "popq %0\n\t"
+               "addq $128, %%rsp"
+#else
+               "pushfl\n\t"
+               "popl %0"
+#endif
+               : "=r" (eflags) :: "memory");
+
+       return eflags;
+}
+
+static inline void set_eflags(unsigned long eflags)
+{
+       asm volatile (
+#ifdef __x86_64__
+               "subq $128, %%rsp\n\t"
+               "pushq %0\n\t"
+               "popfq\n\t"
+               "addq $128, %%rsp"
+#else
+               "pushl %0\n\t"
+               "popfl"
+#endif
+               :: "r" (eflags) : "flags", "memory");
+}
+
+#endif /* __SELFTESTS_X86_HELPERS_H */
index 1063328..120ac74 100644 (file)
@@ -31,6 +31,8 @@
 #include <sys/ptrace.h>
 #include <sys/user.h>
 
+#include "helpers.h"
+
 static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
                       int flags)
 {
@@ -67,21 +69,6 @@ static unsigned char altstack_data[SIGSTKSZ];
 # define INT80_CLOBBERS
 #endif
 
-static unsigned long get_eflags(void)
-{
-       unsigned long eflags;
-       asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags));
-       return eflags;
-}
-
-static void set_eflags(unsigned long eflags)
-{
-       asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH
-                     : : "rm" (eflags) : "flags");
-}
-
-#define X86_EFLAGS_TF (1UL << 8)
-
 static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
 {
        ucontext_t *ctx = (ucontext_t*)ctx_void;
index bc0ecc2..5b7abeb 100644 (file)
 #include <setjmp.h>
 #include <errno.h>
 
-#ifdef __x86_64__
-# define WIDTH "q"
-#else
-# define WIDTH "l"
-#endif
+#include "helpers.h"
 
 /* Our sigaltstack scratch space. */
 static unsigned char altstack_data[SIGSTKSZ];
 
-static unsigned long get_eflags(void)
-{
-       unsigned long eflags;
-       asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags));
-       return eflags;
-}
-
-static void set_eflags(unsigned long eflags)
-{
-       asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH
-                     : : "rm" (eflags) : "flags");
-}
-
-#define X86_EFLAGS_TF (1UL << 8)
-
 static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
                       int flags)
 {
index 02309a1..a108b80 100644 (file)
 #include <signal.h>
 #include <err.h>
 #include <sys/syscall.h>
-#include <asm/processor-flags.h>
 
-#ifdef __x86_64__
-# define WIDTH "q"
-#else
-# define WIDTH "l"
-#endif
+#include "helpers.h"
 
 static unsigned int nerrs;
 
-static unsigned long get_eflags(void)
-{
-       unsigned long eflags;
-       asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags));
-       return eflags;
-}
-
-static void set_eflags(unsigned long eflags)
-{
-       asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH
-                     : : "rm" (eflags) : "flags");
-}
-
 static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
                       int flags)
 {
@@ -59,6 +41,7 @@ static void do_it(unsigned long extraflags)
        set_eflags(get_eflags() | extraflags);
        syscall(SYS_getpid);
        flags = get_eflags();
+       set_eflags(X86_EFLAGS_IF | X86_EFLAGS_FIXED);
        if ((flags & extraflags) == extraflags) {
                printf("[OK]\tThe syscall worked and flags are still set\n");
        } else {
@@ -73,6 +56,12 @@ int main(void)
        printf("[RUN]\tSet NT and issue a syscall\n");
        do_it(X86_EFLAGS_NT);
 
+       printf("[RUN]\tSet AC and issue a syscall\n");
+       do_it(X86_EFLAGS_AC);
+
+       printf("[RUN]\tSet NT|AC and issue a syscall\n");
+       do_it(X86_EFLAGS_NT | X86_EFLAGS_AC);
+
        /*
         * Now try it again with TF set -- TF forces returns via IRET in all
         * cases except non-ptregs-using 64-bit full fast path syscalls.
@@ -80,8 +69,28 @@ int main(void)
 
        sethandler(SIGTRAP, sigtrap, 0);
 
+       printf("[RUN]\tSet TF and issue a syscall\n");
+       do_it(X86_EFLAGS_TF);
+
        printf("[RUN]\tSet NT|TF and issue a syscall\n");
        do_it(X86_EFLAGS_NT | X86_EFLAGS_TF);
 
+       printf("[RUN]\tSet AC|TF and issue a syscall\n");
+       do_it(X86_EFLAGS_AC | X86_EFLAGS_TF);
+
+       printf("[RUN]\tSet NT|AC|TF and issue a syscall\n");
+       do_it(X86_EFLAGS_NT | X86_EFLAGS_AC | X86_EFLAGS_TF);
+
+       /*
+        * Now try DF.  This is evil and it's plausible that we will crash
+        * glibc, but glibc would have to do something rather surprising
+        * for this to happen.
+        */
+       printf("[RUN]\tSet DF and issue a syscall\n");
+       do_it(X86_EFLAGS_DF);
+
+       printf("[RUN]\tSet TF|DF and issue a syscall\n");
+       do_it(X86_EFLAGS_TF | X86_EFLAGS_DF);
+
        return nerrs == 0 ? 0 : 1;
 }
index a4f4d4c..c41f24b 100644 (file)
@@ -20,6 +20,8 @@
 #include <setjmp.h>
 #include <sys/uio.h>
 
+#include "helpers.h"
+
 #ifdef __x86_64__
 # define VSYS(x) (x)
 #else
@@ -493,21 +495,8 @@ static int test_process_vm_readv(void)
 }
 
 #ifdef __x86_64__
-#define X86_EFLAGS_TF (1UL << 8)
 static volatile sig_atomic_t num_vsyscall_traps;
 
-static unsigned long get_eflags(void)
-{
-       unsigned long eflags;
-       asm volatile ("pushfq\n\tpopq %0" : "=rm" (eflags));
-       return eflags;
-}
-
-static void set_eflags(unsigned long eflags)
-{
-       asm volatile ("pushq %0\n\tpopfq" : : "rm" (eflags) : "flags");
-}
-
 static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
 {
        ucontext_t *ctx = (ucontext_t *)ctx_void;
index 0075ccd..4c311e1 100644 (file)
@@ -11,6 +11,8 @@
 #include <features.h>
 #include <stdio.h>
 
+#include "helpers.h"
+
 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 16
 
 int main()
@@ -53,27 +55,6 @@ static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
                err(1, "sigaction");
 }
 
-#ifdef __x86_64__
-# define WIDTH "q"
-#else
-# define WIDTH "l"
-#endif
-
-static unsigned long get_eflags(void)
-{
-       unsigned long eflags;
-       asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags));
-       return eflags;
-}
-
-static void set_eflags(unsigned long eflags)
-{
-       asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH
-                     : : "rm" (eflags) : "flags");
-}
-
-#define X86_EFLAGS_TF (1UL << 8)
-
 static volatile sig_atomic_t nerrs;
 static unsigned long sysinfo;
 static bool got_sysinfo = false;
index 6683b4a..caab980 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
+#include <linux/list.h>
 #include <linux/printk.h>
 #include <linux/bug.h>
 #include <errno.h>
@@ -135,10 +136,4 @@ static inline void free_page(unsigned long addr)
        (void) (&_min1 == &_min2);              \
        _min1 < _min2 ? _min1 : _min2; })
 
-/* TODO: empty stubs for now. Broken but enough for virtio_ring.c */
-#define list_add_tail(a, b) do {} while (0)
-#define list_del(a) do {} while (0)
-#define list_for_each_entry(a, b, c) while (0)
-/* end of stubs */
-
 #endif /* KERNEL_H */
index b751350..5d90254 100644 (file)
@@ -11,12 +11,11 @@ struct device {
 struct virtio_device {
        struct device dev;
        u64 features;
+       struct list_head vqs;
 };
 
 struct virtqueue {
-       /* TODO: commented as list macros are empty stubs for now.
-        * Broken but enough for virtio_ring.c
-        * struct list_head list; */
+       struct list_head list;
        void (*callback)(struct virtqueue *vq);
        const char *name;
        struct virtio_device *vdev;
index b427def..cb3f29c 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #define _GNU_SOURCE
 #include <getopt.h>
+#include <limits.h>
 #include <string.h>
 #include <poll.h>
 #include <sys/eventfd.h>
@@ -18,6 +19,8 @@
 #include <linux/virtio_ring.h>
 #include "../../drivers/vhost/test.h"
 
+#define RANDOM_BATCH -1
+
 /* Unused */
 void *__kmalloc_fake, *__kfree_ignore_start, *__kfree_ignore_end;
 
@@ -43,6 +46,10 @@ struct vdev_info {
        struct vhost_memory *mem;
 };
 
+static const struct vhost_vring_file no_backend = { .fd = -1 },
+                                    backend = { .fd = 1 };
+static const struct vhost_vring_state null_state = {};
+
 bool vq_notify(struct virtqueue *vq)
 {
        struct vq_info *info = vq->priv;
@@ -88,6 +95,19 @@ void vhost_vq_setup(struct vdev_info *dev, struct vq_info *info)
        assert(r >= 0);
 }
 
+static void vq_reset(struct vq_info *info, int num, struct virtio_device *vdev)
+{
+       if (info->vq)
+               vring_del_virtqueue(info->vq);
+
+       memset(info->ring, 0, vring_size(num, 4096));
+       vring_init(&info->vring, num, info->ring, 4096);
+       info->vq = __vring_new_virtqueue(info->idx, info->vring, vdev, true,
+                                        false, vq_notify, vq_callback, "test");
+       assert(info->vq);
+       info->vq->priv = info;
+}
+
 static void vq_info_add(struct vdev_info *dev, int num)
 {
        struct vq_info *info = &dev->vqs[dev->nvqs];
@@ -97,14 +117,7 @@ static void vq_info_add(struct vdev_info *dev, int num)
        info->call = eventfd(0, EFD_NONBLOCK);
        r = posix_memalign(&info->ring, 4096, vring_size(num, 4096));
        assert(r >= 0);
-       memset(info->ring, 0, vring_size(num, 4096));
-       vring_init(&info->vring, num, info->ring, 4096);
-       info->vq = vring_new_virtqueue(info->idx,
-                                      info->vring.num, 4096, &dev->vdev,
-                                      true, false, info->ring,
-                                      vq_notify, vq_callback, "test");
-       assert(info->vq);
-       info->vq->priv = info;
+       vq_reset(info, num, &dev->vdev);
        vhost_vq_setup(dev, info);
        dev->fds[info->idx].fd = info->call;
        dev->fds[info->idx].events = POLLIN;
@@ -116,6 +129,7 @@ static void vdev_info_init(struct vdev_info* dev, unsigned long long features)
        int r;
        memset(dev, 0, sizeof *dev);
        dev->vdev.features = features;
+       INIT_LIST_HEAD(&dev->vdev.vqs);
        dev->buf_size = 1024;
        dev->buf = malloc(dev->buf_size);
        assert(dev->buf);
@@ -152,41 +166,93 @@ static void wait_for_interrupt(struct vdev_info *dev)
 }
 
 static void run_test(struct vdev_info *dev, struct vq_info *vq,
-                    bool delayed, int bufs)
+                    bool delayed, int batch, int reset_n, int bufs)
 {
        struct scatterlist sl;
-       long started = 0, completed = 0;
-       long completed_before;
+       long started = 0, completed = 0, next_reset = reset_n;
+       long completed_before, started_before;
        int r, test = 1;
        unsigned len;
        long long spurious = 0;
+       const bool random_batch = batch == RANDOM_BATCH;
+
        r = ioctl(dev->control, VHOST_TEST_RUN, &test);
        assert(r >= 0);
+       if (!reset_n) {
+               next_reset = INT_MAX;
+       }
+
        for (;;) {
                virtqueue_disable_cb(vq->vq);
                completed_before = completed;
+               started_before = started;
                do {
-                       if (started < bufs) {
+                       const bool reset = completed > next_reset;
+                       if (random_batch)
+                               batch = (random() % vq->vring.num) + 1;
+
+                       while (started < bufs &&
+                              (started - completed) < batch) {
                                sg_init_one(&sl, dev->buf, dev->buf_size);
                                r = virtqueue_add_outbuf(vq->vq, &sl, 1,
                                                         dev->buf + started,
                                                         GFP_ATOMIC);
-                               if (likely(r == 0)) {
-                                       ++started;
-                                       if (unlikely(!virtqueue_kick(vq->vq)))
+                               if (unlikely(r != 0)) {
+                                       if (r == -ENOSPC &&
+                                           started > started_before)
+                                               r = 0;
+                                       else
                                                r = -1;
+                                       break;
                                }
-                       } else
+
+                               ++started;
+
+                               if (unlikely(!virtqueue_kick(vq->vq))) {
+                                       r = -1;
+                                       break;
+                               }
+                       }
+
+                       if (started >= bufs)
                                r = -1;
 
+                       if (reset) {
+                               r = ioctl(dev->control, VHOST_TEST_SET_BACKEND,
+                                         &no_backend);
+                               assert(!r);
+                       }
+
                        /* Flush out completed bufs if any */
-                       if (virtqueue_get_buf(vq->vq, &len)) {
+                       while (virtqueue_get_buf(vq->vq, &len)) {
                                ++completed;
                                r = 0;
                        }
 
+                       if (reset) {
+                               struct vhost_vring_state s = { .index = 0 };
+
+                               vq_reset(vq, vq->vring.num, &dev->vdev);
+
+                               r = ioctl(dev->control, VHOST_GET_VRING_BASE,
+                                         &s);
+                               assert(!r);
+
+                               s.num = 0;
+                               r = ioctl(dev->control, VHOST_SET_VRING_BASE,
+                                         &null_state);
+                               assert(!r);
+
+                               r = ioctl(dev->control, VHOST_TEST_SET_BACKEND,
+                                         &backend);
+                               assert(!r);
+
+                               started = completed;
+                               while (completed > next_reset)
+                                       next_reset += completed;
+                       }
                } while (r == 0);
-               if (completed == completed_before)
+               if (completed == completed_before && started == started_before)
                        ++spurious;
                assert(completed <= bufs);
                assert(started <= bufs);
@@ -203,7 +269,9 @@ static void run_test(struct vdev_info *dev, struct vq_info *vq,
        test = 0;
        r = ioctl(dev->control, VHOST_TEST_RUN, &test);
        assert(r >= 0);
-       fprintf(stderr, "spurious wakeups: 0x%llx\n", spurious);
+       fprintf(stderr,
+               "spurious wakeups: 0x%llx started=0x%lx completed=0x%lx\n",
+               spurious, started, completed);
 }
 
 const char optstring[] = "h";
@@ -244,6 +312,16 @@ const struct option longopts[] = {
                .name = "no-delayed-interrupt",
                .val = 'd',
        },
+       {
+               .name = "batch",
+               .val = 'b',
+               .has_arg = required_argument,
+       },
+       {
+               .name = "reset",
+               .val = 'r',
+               .has_arg = optional_argument,
+       },
        {
        }
 };
@@ -255,6 +333,8 @@ static void help(void)
                " [--no-event-idx]"
                " [--no-virtio-1]"
                " [--delayed-interrupt]"
+               " [--batch=random/N]"
+               " [--reset=N]"
                "\n");
 }
 
@@ -263,6 +343,7 @@ int main(int argc, char **argv)
        struct vdev_info dev;
        unsigned long long features = (1ULL << VIRTIO_RING_F_INDIRECT_DESC) |
                (1ULL << VIRTIO_RING_F_EVENT_IDX) | (1ULL << VIRTIO_F_VERSION_1);
+       long batch = 1, reset = 0;
        int o;
        bool delayed = false;
 
@@ -289,6 +370,24 @@ int main(int argc, char **argv)
                case 'D':
                        delayed = true;
                        break;
+               case 'b':
+                       if (0 == strcmp(optarg, "random")) {
+                               batch = RANDOM_BATCH;
+                       } else {
+                               batch = strtol(optarg, NULL, 10);
+                               assert(batch > 0);
+                               assert(batch < (long)INT_MAX + 1);
+                       }
+                       break;
+               case 'r':
+                       if (!optarg) {
+                               reset = 1;
+                       } else {
+                               reset = strtol(optarg, NULL, 10);
+                               assert(reset > 0);
+                               assert(reset < (long)INT_MAX + 1);
+                       }
+                       break;
                default:
                        assert(0);
                        break;
@@ -298,6 +397,6 @@ int main(int argc, char **argv)
 done:
        vdev_info_init(&dev, features);
        vq_info_add(&dev, 256);
-       run_test(&dev, &dev.vqs[0], delayed, 0x100000);
+       run_test(&dev, &dev.vqs[0], delayed, batch, reset, 0x100000);
        return 0;
 }
index 2936534..fa87b58 100644 (file)
@@ -307,6 +307,7 @@ static int parallel_test(u64 features,
                close(to_host[0]);
 
                gvdev.vdev.features = features;
+               INIT_LIST_HEAD(&gvdev.vdev.vqs);
                gvdev.to_host_fd = to_host[1];
                gvdev.notifies = 0;
 
@@ -453,6 +454,7 @@ int main(int argc, char *argv[])
 
        getrange = getrange_iov;
        vdev.features = 0;
+       INIT_LIST_HEAD(&vdev.vqs);
 
        while (argv[1]) {
                if (strcmp(argv[1], "--indirect") == 0)
index a852af5..0a68c9d 100644 (file)
@@ -3350,7 +3350,8 @@ static long kvm_vcpu_compat_ioctl(struct file *filp,
                        if (kvm_sigmask.len != sizeof(compat_sigset_t))
                                goto out;
                        r = -EFAULT;
-                       if (get_compat_sigset(&sigset, (void *)sigmask_arg->sigset))
+                       if (get_compat_sigset(&sigset,
+                                             (compat_sigset_t __user *)sigmask_arg->sigset))
                                goto out;
                        r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset);
                } else